Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into rmobile-fixes...
authorPaul Mundt <lethal@linux-sh.org>
Fri, 24 Feb 2012 04:23:23 +0000 (13:23 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 24 Feb 2012 04:23:23 +0000 (13:23 +0900)
1939 files changed:
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/deviceiobook.tmpl
Documentation/DocBook/media/dvb/dvbproperty.xml
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
Documentation/DocBook/media/v4l/vidioc-g-input.xml
Documentation/DocBook/media/v4l/vidioc-g-output.xml
Documentation/acpi/apei/einj.txt
Documentation/devices.txt
Documentation/devicetree/bindings/dma/atmel-dma.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/omap-i2c.txt [new file with mode: 0644]
Documentation/dmaengine.txt
Documentation/driver-model/devres.txt
Documentation/feature-removal-schedule.txt
Documentation/input/event-codes.txt
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/pinctrl.txt
Documentation/power/basic-pm-debugging.txt
Documentation/power/freezing-of-tasks.txt
Documentation/scsi/ChangeLog.megaraid_sas
Documentation/scsi/LICENSE.qla4xxx
Documentation/stable_kernel_rules.txt
Documentation/sysctl/kernel.txt
Documentation/target/tcm_mod_builder.py
Documentation/thermal/sysfs-api.txt
Documentation/video4linux/v4l2-controls.txt
Documentation/virtual/00-INDEX
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/tegra-paz00.dts
arch/arm/common/gic.c
arch/arm/common/it8152.c
arch/arm/common/pl330.c
arch/arm/configs/imx_v6_v7_defconfig [new file with mode: 0644]
arch/arm/configs/mx3_defconfig [deleted file]
arch/arm/configs/mx5_defconfig [deleted file]
arch/arm/include/asm/assembler.h
arch/arm/include/asm/domain.h
arch/arm/include/asm/futex.h
arch/arm/include/asm/hardware/pl330.h
arch/arm/include/asm/kprobes.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/ptrace.h
arch/arm/include/asm/smp.h
arch/arm/include/asm/smp_plat.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/tlb.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/unified.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/lib/uaccess.S
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91cap9.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.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/at91sam9_alt_reset.S
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_reset.S [new file with mode: 0644]
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/at91_rstc.h
arch/arm/mach-at91/include/mach/at91cap9.h
arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9260.h
arch/arm/mach-at91/include/mach/at91sam9261.h
arch/arm/mach-at91/include/mach/at91sam9263.h
arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h
arch/arm/mach-at91/include/mach/at91sam9_smc.h
arch/arm/mach-at91/include/mach/at91sam9g45.h
arch/arm/mach-at91/include/mach/at91sam9rl.h
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_slowclock.S
arch/arm/mach-at91/sam9_smc.c
arch/arm/mach-at91/sam9_smc.h
arch/arm/mach-at91/setup.c
arch/arm/mach-bcmring/arch.c
arch/arm/mach-bcmring/dma.c
arch/arm/mach-bcmring/include/mach/dma.h
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-omapl138-hawk.c
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-dove/common.c
arch/arm/mach-ep93xx/include/mach/dma.h
arch/arm/mach-ep93xx/vision_ep9307.c
arch/arm/mach-exynos/clock-exynos4210.c
arch/arm/mach-exynos/clock-exynos4212.c
arch/arm/mach-exynos/clock.c
arch/arm/mach-exynos/headsmp.S
arch/arm/mach-exynos/hotplug.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-exynos/pm.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/Makefile.boot
arch/arm/mach-imx/clock-imx6q.c
arch/arm/mach-imx/clock-mx51-mx53.c [new file with mode: 0644]
arch/arm/mach-imx/cpu-imx5.c [new file with mode: 0644]
arch/arm/mach-imx/cpu_op-mx51.c [new file with mode: 0644]
arch/arm/mach-imx/cpu_op-mx51.h [new file with mode: 0644]
arch/arm/mach-imx/crm-regs-imx5.h [new file with mode: 0644]
arch/arm/mach-imx/devices-imx50.h [new file with mode: 0644]
arch/arm/mach-imx/devices-imx51.h [new file with mode: 0644]
arch/arm/mach-imx/devices-imx53.h [new file with mode: 0644]
arch/arm/mach-imx/efika.h [new file with mode: 0644]
arch/arm/mach-imx/ehci-imx5.c [new file with mode: 0644]
arch/arm/mach-imx/eukrea_mbimx51-baseboard.c [new file with mode: 0644]
arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c [new file with mode: 0644]
arch/arm/mach-imx/imx51-dt.c [new file with mode: 0644]
arch/arm/mach-imx/imx53-dt.c [new file with mode: 0644]
arch/arm/mach-imx/mach-cpuimx51.c [new file with mode: 0644]
arch/arm/mach-imx/mach-cpuimx51sd.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx50_rdp.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx51_3ds.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx51_babbage.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx51_efikamx.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx51_efikasb.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx53_ard.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx53_evk.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx53_loco.c [new file with mode: 0644]
arch/arm/mach-imx/mach-mx53_smd.c [new file with mode: 0644]
arch/arm/mach-imx/mm-imx5.c [new file with mode: 0644]
arch/arm/mach-imx/mx51_efika.c [new file with mode: 0644]
arch/arm/mach-imx/pm-imx5.c [new file with mode: 0644]
arch/arm/mach-imx/src.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/mpp.h
arch/arm/mach-msm/headsmp.S
arch/arm/mach-msm/hotplug.c
arch/arm/mach-msm/platsmp.c
arch/arm/mach-msm/vreg.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-mv78xx0/mpp.h
arch/arm/mach-mx5/Kconfig [deleted file]
arch/arm/mach-mx5/Makefile [deleted file]
arch/arm/mach-mx5/Makefile.boot [deleted file]
arch/arm/mach-mx5/board-cpuimx51.c [deleted file]
arch/arm/mach-mx5/board-cpuimx51sd.c [deleted file]
arch/arm/mach-mx5/board-mx50_rdp.c [deleted file]
arch/arm/mach-mx5/board-mx51_3ds.c [deleted file]
arch/arm/mach-mx5/board-mx51_babbage.c [deleted file]
arch/arm/mach-mx5/board-mx51_efikamx.c [deleted file]
arch/arm/mach-mx5/board-mx51_efikasb.c [deleted file]
arch/arm/mach-mx5/board-mx53_ard.c [deleted file]
arch/arm/mach-mx5/board-mx53_evk.c [deleted file]
arch/arm/mach-mx5/board-mx53_loco.c [deleted file]
arch/arm/mach-mx5/board-mx53_smd.c [deleted file]
arch/arm/mach-mx5/clock-mx51-mx53.c [deleted file]
arch/arm/mach-mx5/cpu.c [deleted file]
arch/arm/mach-mx5/cpu_op-mx51.c [deleted file]
arch/arm/mach-mx5/cpu_op-mx51.h [deleted file]
arch/arm/mach-mx5/crm_regs.h [deleted file]
arch/arm/mach-mx5/devices-imx50.h [deleted file]
arch/arm/mach-mx5/devices-imx51.h [deleted file]
arch/arm/mach-mx5/devices-imx53.h [deleted file]
arch/arm/mach-mx5/efika.h [deleted file]
arch/arm/mach-mx5/ehci.c [deleted file]
arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c [deleted file]
arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c [deleted file]
arch/arm/mach-mx5/imx51-dt.c [deleted file]
arch/arm/mach-mx5/imx53-dt.c [deleted file]
arch/arm/mach-mx5/mm.c [deleted file]
arch/arm/mach-mx5/mx51_efika.c [deleted file]
arch/arm/mach-mx5/pm-imx5.c [deleted file]
arch/arm/mach-mx5/system.c [deleted file]
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/omap-headsmp.S
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_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/pm24xx.c
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/smartreflex.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-omap2/voltagedomains3xxx_data.c
arch/arm/mach-omap2/voltagedomains44xx_data.c
arch/arm/mach-omap2/vp.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-picoxcell/time.c
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa300.c
arch/arm/mach-pxa/pxa320.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/pxa95x.c
arch/arm/mach-realview/hotplug.c
arch/arm/mach-realview/include/mach/board-eb.h
arch/arm/mach-realview/include/mach/board-pb11mp.h
arch/arm/mach-realview/platsmp.c
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-s3c2410/cpu-freq.c
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/pll.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2412/cpu-freq.c
arch/arm/mach-s3c2412/dma.c
arch/arm/mach-s3c2412/irq.c
arch/arm/mach-s3c2412/pm.c
arch/arm/mach-s3c2416/irq.c
arch/arm/mach-s3c2416/pm.c
arch/arm/mach-s3c2440/clock.c
arch/arm/mach-s3c2440/dma.c
arch/arm/mach-s3c2440/irq.c
arch/arm/mach-s3c2440/s3c2440-cpufreq.c
arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2440/s3c244x-clock.c
arch/arm/mach-s3c2440/s3c244x-irq.c
arch/arm/mach-s3c2443/dma.c
arch/arm/mach-s3c2443/irq.c
arch/arm/mach-s3c64xx/clock.c
arch/arm/mach-s3c64xx/common.c
arch/arm/mach-s3c64xx/include/mach/crag6410.h
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/pm.c
arch/arm/mach-s5p64x0/pm.c
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/pm.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/clock.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/cpu-sa1100.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/include/mach/mcp.h
arch/arm/mach-sa1100/jornada720_ssp.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/shannon.c
arch/arm/mach-sa1100/simpad.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-sh73a0.c
arch/arm/mach-tegra/board-paz00.c
arch/arm/mach-tegra/board-paz00.h
arch/arm/mach-tegra/include/mach/dma.h
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/cache-l2x0.c
arch/arm/mach-ux500/headsmp.S
arch/arm/mach-ux500/hotplug.c
arch/arm/mach-ux500/platsmp.c
arch/arm/mach-ux500/usb.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/hotplug.c
arch/arm/mach-vexpress/platsmp.c
arch/arm/mm/Kconfig
arch/arm/mm/cache-v7.S
arch/arm/mm/init.c
arch/arm/mm/proc-v7.S
arch/arm/plat-mxc/Kconfig
arch/arm/plat-mxc/include/mach/iomux-v1.h
arch/arm/plat-mxc/include/mach/mx3fb.h
arch/arm/plat-nomadik/include/plat/ste_dma40.h
arch/arm/plat-omap/include/plat/omap-secure.h
arch/arm/plat-orion/common.c
arch/arm/plat-orion/include/plat/common.h
arch/arm/plat-orion/mpp.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/include/plat/dma-ops.h
arch/arm/plat-samsung/include/plat/dma.h
arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
arch/arm/plat-versatile/headsmp.S
arch/arm/plat-versatile/platsmp.c
arch/avr32/Kconfig
arch/ia64/include/asm/ptrace.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/ptrace.c
arch/m68k/atari/config.c
arch/m68k/include/asm/irq.h
arch/m68k/include/asm/mcf_pgtable.h
arch/m68k/kernel/process_mm.c
arch/m68k/kernel/process_no.c
arch/m68k/kernel/traps.c
arch/m68k/mm/cache.c
arch/m68k/mm/mcfmmu.c
arch/m68k/platform/coldfire/entry.S
arch/microblaze/Kconfig
arch/microblaze/include/asm/atomic.h
arch/microblaze/include/asm/ptrace.h
arch/microblaze/kernel/ptrace.c
arch/mips/Kconfig
arch/mips/include/asm/ptrace.h
arch/mips/kernel/ptrace.c
arch/mips/lib/iomap-pci.c
arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
arch/powerpc/boot/dts/p1020rdb.dtsi
arch/powerpc/boot/dts/p1021mds.dts
arch/powerpc/boot/dts/p2020ds.dtsi
arch/powerpc/boot/dts/p2020rdb.dts
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/include/asm/ppc-pci.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/perf_event.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal.h
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/suspend.c
arch/powerpc/platforms/wsp/ics.c
arch/powerpc/platforms/wsp/smp.c
arch/powerpc/platforms/wsp/wsp_pci.c
arch/powerpc/sysdev/fsl_pci.c
arch/s390/Makefile
arch/s390/include/asm/kexec.h
arch/s390/include/asm/ptrace.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/time.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/mm/pgtable.c
arch/score/kernel/entry.S
arch/sh/Kconfig
arch/sh/drivers/pci/pci.c
arch/sh/include/asm/ptrace_32.h
arch/sh/include/asm/ptrace_64.h
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sparc/Kconfig
arch/sparc/include/asm/ptrace.h
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/sun4m_irq.c
arch/sparc/lib/divdi3.S
arch/um/kernel/ptrace.c
arch/x86/.gitignore
arch/x86/Kconfig
arch/x86/boot/compressed/misc.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/cmpxchg.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/i387.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/include/asm/uv/uv_hub.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_lbr.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/e820.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/reboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/vm86_32.c
arch/x86/kernel/xsave.c
arch/x86/kvm/emulate.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/x86-opcode-map.txt
arch/x86/mm/fault.c
arch/x86/mm/srat.c
arch/x86/net/bpf_jit_comp.c
arch/x86/pci/xen.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/platform/uv/uv_irq.c
arch/x86/um/shared/sysdep/ptrace.h
arch/x86/xen/smp.c
arch/x86/xen/spinlock.c
arch/xtensa/include/asm/string.h
arch/xtensa/kernel/ptrace.c
block/blk-cgroup.c
block/blk-core.c
block/blk-ioc.c
block/blk-merge.c
block/blk.h
block/bsg.c
block/cfq-iosched.c
block/elevator.c
crypto/sha512_generic.c
drivers/acpi/Makefile
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/accommon.h
drivers/acpi/acpica/acconfig.h
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acdispat.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/achware.h
drivers/acpi/acpica/acinterp.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/acopcode.h
drivers/acpi/acpica/acparser.h
drivers/acpi/acpica/acpredef.h
drivers/acpi/acpica/acresrc.h
drivers/acpi/acpica/acstruct.h
drivers/acpi/acpica/actables.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/amlcode.h
drivers/acpi/acpica/amlresrc.h
drivers/acpi/acpica/dsargs.c
drivers/acpi/acpica/dscontrol.c
drivers/acpi/acpica/dsfield.c
drivers/acpi/acpica/dsinit.c
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dsmthdat.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/dsutils.c
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/dswload.c
drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/dswscope.c
drivers/acpi/acpica/dswstate.c
drivers/acpi/acpica/evevent.c
drivers/acpi/acpica/evglock.c
drivers/acpi/acpica/evgpe.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/acpica/evgpeutil.c
drivers/acpi/acpica/evmisc.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/evrgnini.c
drivers/acpi/acpica/evsci.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfevnt.c
drivers/acpi/acpica/evxfgpe.c
drivers/acpi/acpica/evxfregn.c
drivers/acpi/acpica/exconfig.c
drivers/acpi/acpica/exconvrt.c
drivers/acpi/acpica/excreate.c
drivers/acpi/acpica/exdebug.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/exfield.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exmisc.c
drivers/acpi/acpica/exmutex.c
drivers/acpi/acpica/exnames.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/exoparg2.c
drivers/acpi/acpica/exoparg3.c
drivers/acpi/acpica/exoparg6.c
drivers/acpi/acpica/exprep.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/exresnte.c
drivers/acpi/acpica/exresolv.c
drivers/acpi/acpica/exresop.c
drivers/acpi/acpica/exstore.c
drivers/acpi/acpica/exstoren.c
drivers/acpi/acpica/exstorob.c
drivers/acpi/acpica/exsystem.c
drivers/acpi/acpica/exutils.c
drivers/acpi/acpica/hwacpi.c
drivers/acpi/acpica/hwgpe.c
drivers/acpi/acpica/hwpci.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/acpica/hwsleep.c
drivers/acpi/acpica/hwtimer.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/hwxface.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nsalloc.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nsdumpdv.c
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/acpica/nsload.c
drivers/acpi/acpica/nsnames.c
drivers/acpi/acpica/nsobject.c
drivers/acpi/acpica/nsparse.c
drivers/acpi/acpica/nspredef.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/nssearch.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/nswalk.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/nsxfobj.c
drivers/acpi/acpica/psargs.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/psopcode.c
drivers/acpi/acpica/psparse.c
drivers/acpi/acpica/psscope.c
drivers/acpi/acpica/pstree.c
drivers/acpi/acpica/psutils.c
drivers/acpi/acpica/pswalk.c
drivers/acpi/acpica/psxface.c
drivers/acpi/acpica/rsaddr.c
drivers/acpi/acpica/rscalc.c
drivers/acpi/acpica/rscreate.c
drivers/acpi/acpica/rsdump.c
drivers/acpi/acpica/rsinfo.c
drivers/acpi/acpica/rsio.c
drivers/acpi/acpica/rsirq.c
drivers/acpi/acpica/rslist.c
drivers/acpi/acpica/rsmemory.c
drivers/acpi/acpica/rsmisc.c
drivers/acpi/acpica/rsserial.c [new file with mode: 0644]
drivers/acpi/acpica/rsutils.c
drivers/acpi/acpica/rsxface.c
drivers/acpi/acpica/tbfadt.c
drivers/acpi/acpica/tbfind.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxface.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/utaddress.c [new file with mode: 0644]
drivers/acpi/acpica/utalloc.c
drivers/acpi/acpica/utcopy.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/utdecode.c
drivers/acpi/acpica/utdelete.c
drivers/acpi/acpica/uteval.c
drivers/acpi/acpica/utglobal.c
drivers/acpi/acpica/utids.c
drivers/acpi/acpica/utinit.c
drivers/acpi/acpica/utlock.c
drivers/acpi/acpica/utmath.c
drivers/acpi/acpica/utmisc.c
drivers/acpi/acpica/utmutex.c
drivers/acpi/acpica/utobject.c
drivers/acpi/acpica/utosi.c
drivers/acpi/acpica/utresrc.c
drivers/acpi/acpica/utstate.c
drivers/acpi/acpica/utxface.c
drivers/acpi/acpica/utxferror.c
drivers/acpi/acpica/utxfmutex.c [new file with mode: 0644]
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/apei-internal.h
drivers/acpi/apei/einj.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/ghes.c
drivers/acpi/apei/hest.c
drivers/acpi/atomicio.c [deleted file]
drivers/acpi/numa.c
drivers/acpi/nvs.c
drivers/acpi/osl.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/sleep.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-transport.c
drivers/ata/pata_at91.c
drivers/ata/pata_bf54x.c
drivers/ata/sata_fsl.c
drivers/base/Makefile
drivers/base/bus.c
drivers/base/core.c
drivers/base/cpu.c
drivers/base/firmware_class.c
drivers/base/memory.c
drivers/base/node.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap.c
drivers/base/sys.c [deleted file]
drivers/bcma/bcma_private.h
drivers/bcma/host_pci.c
drivers/bcma/main.c
drivers/bcma/scan.c
drivers/block/Kconfig
drivers/block/Makefile
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/nvme.c [new file with mode: 0644]
drivers/block/rbd.c
drivers/cdrom/cdrom.c
drivers/char/agp/backend.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/cpuidle/Kconfig
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/coh901318.c
drivers/dma/coh901318_lli.c
drivers/dma/coh901318_lli.h
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/dw_dmac.c
drivers/dma/dw_dmac_regs.h
drivers/dma/ep93xx_dma.c
drivers/dma/fsldma.c
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/intel_mid_dma_regs.h
drivers/dma/iop-adma.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/mpc512x_dma.c
drivers/dma/mxs-dma.c
drivers/dma/pch_dma.c
drivers/dma/pl330.c
drivers/dma/shdma.c
drivers/dma/sirf-dma.c [new file with mode: 0644]
drivers/dma/ste_dma40.c
drivers/dma/ste_dma40_ll.h
drivers/dma/timb_dma.c
drivers/dma/txx9dmac.c
drivers/edac/i3200_edac.c
drivers/firewire/ohci.c
drivers/gpio/Kconfig
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-ml-ioh.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-tps65910.c
drivers/gpu/drm/drm_auth.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_core.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_drm_encoder.h
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/gtt.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i810/i810_drv.h
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_mxm.c
drivers/gpu/drm/nouveau/nv50_pm.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_bios.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_encoders.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-wacom.c
drivers/hid/hid-wiimote-core.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/f71805f.c
drivers/hwmon/f75375s.c
drivers/hwmon/sht15.c
drivers/hwmon/w83627ehf.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-tegra.c
drivers/ide/Makefile
drivers/ide/at91_ide.c [deleted file]
drivers/idle/intel_idle.c
drivers/infiniband/Kconfig
drivers/infiniband/Makefile
drivers/infiniband/core/ucma.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_cm.h
drivers/infiniband/hw/nes/nes_context.h
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_hw.h
drivers/infiniband/hw/nes/nes_mgt.c
drivers/infiniband/hw/nes/nes_mgt.h
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/nes/nes_user.h
drivers/infiniband/hw/nes/nes_utils.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/hw/nes/nes_verbs.h
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_pcie.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/srpt/Kconfig [new file with mode: 0644]
drivers/infiniband/ulp/srpt/Makefile [new file with mode: 0644]
drivers/infiniband/ulp/srpt/ib_dm_mad.h [new file with mode: 0644]
drivers/infiniband/ulp/srpt/ib_srpt.c [new file with mode: 0644]
drivers/infiniband/ulp/srpt/ib_srpt.h [new file with mode: 0644]
drivers/input/evdev.c
drivers/input/keyboard/twl4030_keypad.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/serio_raw.c
drivers/iommu/amd_iommu.c
drivers/iommu/msm_iommu.c
drivers/isdn/i4l/isdn_net.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-lm3530.c
drivers/leds/leds-ot200.c [new file with mode: 0644]
drivers/macintosh/adb.c
drivers/md/dm-raid.c
drivers/md/md.c
drivers/media/common/tuners/tuner-xc2028.c
drivers/media/common/tuners/xc4000.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/cinergyT2-fe.c
drivers/media/dvb/dvb-usb/dib0700.h
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/frontends/cxd2820r.h
drivers/media/dvb/frontends/cxd2820r_core.c
drivers/media/dvb/frontends/ds3000.c
drivers/media/dvb/frontends/mb86a20s.c
drivers/media/dvb/frontends/tda18271c2dd.c
drivers/media/video/as3645a.c
drivers/media/video/atmel-isi.c
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-yuv.c
drivers/media/video/mx3_camera.c
drivers/media/video/omap/omap_vout.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-dec1.c
drivers/media/video/pwc/pwc-dec1.h
drivers/media/video/pwc/pwc-dec23.c
drivers/media/video/pwc/pwc-dec23.h
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-misc.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-mdevice.c
drivers/media/video/s5p-g2d/g2d.c
drivers/media/video/s5p-jpeg/jpeg-core.c
drivers/media/video/s5p-mfc/s5p_mfc.c
drivers/media/video/s5p-mfc/s5p_mfc_dec.c
drivers/media/video/saa7164/saa7164-cards.c
drivers/media/video/timblogiw.c
drivers/media/video/tlg2300/pd-main.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/zoran/zoran_driver.c
drivers/mfd/Kconfig
drivers/mfd/mcp-core.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-power.c
drivers/mfd/twl6040-core.c
drivers/mfd/ucb1x00-core.c
drivers/mfd/ucb1x00-ts.c
drivers/misc/Kconfig
drivers/misc/c2port/c2port-duramar2150.c
drivers/misc/carma/carma-fpga-program.c
drivers/misc/cb710/core.c
drivers/misc/cs5535-mfgpt.c
drivers/misc/lkdtm.c
drivers/misc/vmw_balloon.c
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/host.h
drivers/mmc/core/mmc.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_irq.c
drivers/mmc/host/Kconfig
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/of_mmc_spi.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/tmio_mmc.h
drivers/mmc/host/tmio_mmc_dma.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/nand_base.c
drivers/net/bonding/bond_alb.c
drivers/net/can/cc770/cc770.c
drivers/net/can/cc770/cc770_isa.c
drivers/net/can/flexcan.c
drivers/net/can/pch_can.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/ems_usb.c
drivers/net/dsa/mv88e6060.c
drivers/net/dsa/mv88e6123_61_65.c
drivers/net/dsa/mv88e6131.c
drivers/net/dsa/mv88e6xxx.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/brocade/bna/bnad_ethtool.c
drivers/net/ethernet/cisco/enic/enic.h
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/freescale/fec.c
drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/ehea/ehea_qmr.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/igb/Makefile
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/e1000_82575.h
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/e1000_hw.h
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/intel/igb/e1000_mac.h
drivers/net/ethernet/intel/igb/e1000_mbx.c
drivers/net/ethernet/intel/igb/e1000_mbx.h
drivers/net/ethernet/intel/igb/e1000_nvm.c
drivers/net/ethernet/intel/igb/e1000_nvm.h
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/e1000_phy.h
drivers/net/ethernet/intel/igb/e1000_regs.h
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/Makefile
drivers/net/ethernet/intel/igbvf/defines.h
drivers/net/ethernet/intel/igbvf/ethtool.c
drivers/net/ethernet/intel/igbvf/igbvf.h
drivers/net/ethernet/intel/igbvf/mbx.c
drivers/net/ethernet/intel/igbvf/mbx.h
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/igbvf/regs.h
drivers/net/ethernet/intel/igbvf/vf.c
drivers/net/ethernet/intel/igbvf/vf.h
drivers/net/ethernet/intel/ixgbe/Makefile
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
drivers/net/ethernet/intel/ixgbevf/Makefile
drivers/net/ethernet/intel/ixgbevf/defines.h
drivers/net/ethernet/intel/ixgbevf/ethtool.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/intel/ixgbevf/mbx.c
drivers/net/ethernet/intel/ixgbevf/mbx.h
drivers/net/ethernet/intel/ixgbevf/regs.h
drivers/net/ethernet/intel/ixgbevf/vf.c
drivers/net/ethernet/intel/ixgbevf/vf.h
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/fw.h
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx4/pd.c
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx4/profile.c
drivers/net/ethernet/mellanox/mlx4/qp.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx4/srq.c
drivers/net/ethernet/micrel/Kconfig
drivers/net/ethernet/micrel/ks8842.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/octeon/octeon_mgmt.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/norm_desc.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/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/ethernet/toshiba/Kconfig
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/macvlan.c
drivers/net/phy/mdio_bus.c
drivers/net/team/team.c
drivers/net/tokenring/Kconfig
drivers/net/usb/ipheth.c
drivers/net/veth.c
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/b43/Kconfig
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/xen-netfront.c
drivers/pci/iov.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/remove.c
drivers/pci/xen-pcifront.c
drivers/pcmcia/ds.c
drivers/pcmcia/sa1111_generic.c
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinconf.h
drivers/pinctrl/pinmux.c
drivers/pinctrl/pinmux.h
drivers/platform/x86/ibm_rtl.c
drivers/platform/x86/intel_ips.c
drivers/power/bq27x00_battery.c
drivers/power/charger-manager.c
drivers/power/lp8727_charger.c
drivers/regulator/core.c
drivers/regulator/max8649.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/of_regulator.c
drivers/rtc/Kconfig
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-sa1100.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_int.h
drivers/s390/char/con3215.c
drivers/scsi/Kconfig
drivers/scsi/bfa/bfa_defs_svc.h
drivers/scsi/bfa/bfa_fc.h
drivers/scsi/bfa/bfa_fcpim.c
drivers/scsi/bfa/bfa_fcpim.h
drivers/scsi/bfa/bfa_svc.h
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_attr.c
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/bfa/bfad_im.c
drivers/scsi/bfa/bfad_im.h
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe.h
drivers/scsi/hpsa.c
drivers/scsi/isci/firmware/Makefile [deleted file]
drivers/scsi/isci/firmware/README [deleted file]
drivers/scsi/isci/firmware/create_fw.c [deleted file]
drivers/scsi/isci/firmware/create_fw.h [deleted file]
drivers/scsi/isci/host.c
drivers/scsi/isci/host.h
drivers/scsi/isci/init.c
drivers/scsi/isci/isci.h
drivers/scsi/isci/phy.c
drivers/scsi/isci/port.c
drivers/scsi/isci/port.h
drivers/scsi/isci/port_config.c
drivers/scsi/isci/probe_roms.c
drivers/scsi/isci/probe_roms.h
drivers/scsi/isci/remote_device.c
drivers/scsi/isci/task.c
drivers/scsi/isci/task.h
drivers/scsi/libfc/fc_disc.c
drivers/scsi/libfc/fc_elsct.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/mac_esp.c
drivers/scsi/mac_scsi.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_nx.c
drivers/scsi/qla4xxx/ql4_nx.h
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qla4xxx/ql4_version.h
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sg.c
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/spi/Kconfig
drivers/spi/spi-dw-mid.c
drivers/spi/spi-ep93xx.c
drivers/spi/spi-pl022.c
drivers/spi/spi-topcliff-pch.c
drivers/ssb/driver_pcicore.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/Kconfig
drivers/staging/android/Makefile
drivers/staging/android/android_pmem.h [deleted file]
drivers/staging/android/binder.c
drivers/staging/android/lowmemorykiller.c
drivers/staging/android/pmem.c [deleted file]
drivers/staging/asus_oled/asus_oled.c
drivers/staging/gma500/Kconfig [deleted file]
drivers/staging/gma500/Makefile [deleted file]
drivers/staging/gma500/TODO [deleted file]
drivers/staging/gma500/accel_2d.c [deleted file]
drivers/staging/gma500/backlight.c [deleted file]
drivers/staging/gma500/cdv_device.c [deleted file]
drivers/staging/gma500/cdv_device.h [deleted file]
drivers/staging/gma500/cdv_intel_crt.c [deleted file]
drivers/staging/gma500/cdv_intel_display.c [deleted file]
drivers/staging/gma500/cdv_intel_hdmi.c [deleted file]
drivers/staging/gma500/cdv_intel_lvds.c [deleted file]
drivers/staging/gma500/displays/hdmi.h [deleted file]
drivers/staging/gma500/displays/pyr_cmd.h [deleted file]
drivers/staging/gma500/displays/pyr_vid.h [deleted file]
drivers/staging/gma500/displays/tmd_cmd.h [deleted file]
drivers/staging/gma500/displays/tmd_vid.h [deleted file]
drivers/staging/gma500/displays/tpo_cmd.h [deleted file]
drivers/staging/gma500/displays/tpo_vid.h [deleted file]
drivers/staging/gma500/framebuffer.c [deleted file]
drivers/staging/gma500/framebuffer.h [deleted file]
drivers/staging/gma500/gem.c [deleted file]
drivers/staging/gma500/gem_glue.c [deleted file]
drivers/staging/gma500/gem_glue.h [deleted file]
drivers/staging/gma500/gtt.c [deleted file]
drivers/staging/gma500/gtt.h [deleted file]
drivers/staging/gma500/intel_bios.c [deleted file]
drivers/staging/gma500/intel_bios.h [deleted file]
drivers/staging/gma500/intel_i2c.c [deleted file]
drivers/staging/gma500/intel_opregion.c [deleted file]
drivers/staging/gma500/mdfld_device.c [deleted file]
drivers/staging/gma500/mdfld_dsi_dbi.c [deleted file]
drivers/staging/gma500/mdfld_dsi_dbi.h [deleted file]
drivers/staging/gma500/mdfld_dsi_dbi_dpu.c [deleted file]
drivers/staging/gma500/mdfld_dsi_dbi_dpu.h [deleted file]
drivers/staging/gma500/mdfld_dsi_dpi.c [deleted file]
drivers/staging/gma500/mdfld_dsi_dpi.h [deleted file]
drivers/staging/gma500/mdfld_dsi_output.c [deleted file]
drivers/staging/gma500/mdfld_dsi_output.h [deleted file]
drivers/staging/gma500/mdfld_dsi_pkg_sender.c [deleted file]
drivers/staging/gma500/mdfld_dsi_pkg_sender.h [deleted file]
drivers/staging/gma500/mdfld_intel_display.c [deleted file]
drivers/staging/gma500/mdfld_msic.h [deleted file]
drivers/staging/gma500/mdfld_output.c [deleted file]
drivers/staging/gma500/mdfld_output.h [deleted file]
drivers/staging/gma500/mdfld_pyr_cmd.c [deleted file]
drivers/staging/gma500/mdfld_tmd_vid.c [deleted file]
drivers/staging/gma500/mdfld_tpo_cmd.c [deleted file]
drivers/staging/gma500/mdfld_tpo_vid.c [deleted file]
drivers/staging/gma500/medfield.h [deleted file]
drivers/staging/gma500/mid_bios.c [deleted file]
drivers/staging/gma500/mid_bios.h [deleted file]
drivers/staging/gma500/mmu.c [deleted file]
drivers/staging/gma500/mrst.h [deleted file]
drivers/staging/gma500/mrst_crtc.c [deleted file]
drivers/staging/gma500/mrst_device.c [deleted file]
drivers/staging/gma500/mrst_hdmi.c [deleted file]
drivers/staging/gma500/mrst_hdmi_i2c.c [deleted file]
drivers/staging/gma500/mrst_lvds.c [deleted file]
drivers/staging/gma500/power.c [deleted file]
drivers/staging/gma500/power.h [deleted file]
drivers/staging/gma500/psb_device.c [deleted file]
drivers/staging/gma500/psb_drm.h [deleted file]
drivers/staging/gma500/psb_drv.c [deleted file]
drivers/staging/gma500/psb_drv.h [deleted file]
drivers/staging/gma500/psb_intel_display.c [deleted file]
drivers/staging/gma500/psb_intel_display.h [deleted file]
drivers/staging/gma500/psb_intel_drv.h [deleted file]
drivers/staging/gma500/psb_intel_lvds.c [deleted file]
drivers/staging/gma500/psb_intel_modes.c [deleted file]
drivers/staging/gma500/psb_intel_reg.h [deleted file]
drivers/staging/gma500/psb_intel_sdvo.c [deleted file]
drivers/staging/gma500/psb_intel_sdvo_regs.h [deleted file]
drivers/staging/gma500/psb_irq.c [deleted file]
drivers/staging/gma500/psb_irq.h [deleted file]
drivers/staging/gma500/psb_lid.c [deleted file]
drivers/staging/gma500/psb_reg.h [deleted file]
drivers/staging/media/go7007/go7007-usb.c
drivers/staging/omapdrm/Makefile
drivers/staging/omapdrm/omap_crtc.c
drivers/staging/omapdrm/omap_drv.c
drivers/staging/omapdrm/omap_drv.h
drivers/staging/omapdrm/omap_fb.c
drivers/staging/omapdrm/omap_fbdev.c
drivers/staging/omapdrm/omap_gem.c
drivers/staging/omapdrm/omap_plane.c [new file with mode: 0644]
drivers/staging/omapdrm/omap_priv.h
drivers/staging/pohmelfs/Kconfig [deleted file]
drivers/staging/pohmelfs/Makefile [deleted file]
drivers/staging/pohmelfs/config.c [deleted file]
drivers/staging/pohmelfs/crypto.c [deleted file]
drivers/staging/pohmelfs/dir.c [deleted file]
drivers/staging/pohmelfs/inode.c [deleted file]
drivers/staging/pohmelfs/lock.c [deleted file]
drivers/staging/pohmelfs/mcache.c [deleted file]
drivers/staging/pohmelfs/net.c [deleted file]
drivers/staging/pohmelfs/netfs.h [deleted file]
drivers/staging/pohmelfs/path_entry.c [deleted file]
drivers/staging/pohmelfs/trans.c [deleted file]
drivers/staging/rtl8712/drv_types.h
drivers/staging/rtl8712/hal_init.c
drivers/staging/rtl8712/os_intfs.c
drivers/staging/rtl8712/rtl8712_hal.h
drivers/staging/rtl8712/rtl871x_sta_mgt.c
drivers/staging/rtl8712/usb_intf.c
drivers/staging/tidspbridge/core/tiomap3430.c
drivers/staging/tidspbridge/rmgr/drv_interface.c
drivers/staging/usbip/stub_main.c
drivers/staging/zcache/zcache-main.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_auth.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_device.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_erl2.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/iscsi/iscsi_target_nodeattrib.c
drivers/target/iscsi/iscsi_target_stat.c
drivers/target/iscsi/iscsi_target_tmr.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/loopback/tcm_loop.c
drivers/target/loopback/tcm_loop.h
drivers/target/target_core_alua.c
drivers/target/target_core_cdb.c
drivers/target/target_core_cdb.h [deleted file]
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_fabric_lib.c
drivers/target/target_core_file.c
drivers/target/target_core_hba.c
drivers/target/target_core_hba.h [deleted file]
drivers/target/target_core_iblock.c
drivers/target/target_core_internal.h [new file with mode: 0644]
drivers/target/target_core_pr.c
drivers/target/target_core_pr.h
drivers/target/target_core_pscsi.c
drivers/target/target_core_rd.c
drivers/target/target_core_stat.c
drivers/target/target_core_stat.h [deleted file]
drivers/target/target_core_tmr.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_ua.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_conf.c
drivers/target/tcm_fc/tfc_io.c
drivers/target/tcm_fc/tfc_sess.c
drivers/thermal/thermal_sys.c
drivers/tty/serial/8250.c [deleted file]
drivers/tty/serial/8250.h [deleted file]
drivers/tty/serial/8250/8250.c [new file with mode: 0644]
drivers/tty/serial/8250/8250.h [new file with mode: 0644]
drivers/tty/serial/8250/8250_accent.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_acorn.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_boca.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_dw.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_early.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_exar_st16c554.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_fourport.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_fsl.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_gsc.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_hp300.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_hub6.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_mca.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_pci.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_pnp.c [new file with mode: 0644]
drivers/tty/serial/8250/Kconfig [new file with mode: 0644]
drivers/tty/serial/8250/Makefile [new file with mode: 0644]
drivers/tty/serial/8250/serial_cs.c [new file with mode: 0644]
drivers/tty/serial/8250_accent.c [deleted file]
drivers/tty/serial/8250_acorn.c [deleted file]
drivers/tty/serial/8250_boca.c [deleted file]
drivers/tty/serial/8250_dw.c [deleted file]
drivers/tty/serial/8250_early.c [deleted file]
drivers/tty/serial/8250_exar_st16c554.c [deleted file]
drivers/tty/serial/8250_fourport.c [deleted file]
drivers/tty/serial/8250_fsl.c [deleted file]
drivers/tty/serial/8250_gsc.c [deleted file]
drivers/tty/serial/8250_hp300.c [deleted file]
drivers/tty/serial/8250_hub6.c [deleted file]
drivers/tty/serial/8250_mca.c [deleted file]
drivers/tty/serial/8250_pci.c [deleted file]
drivers/tty/serial/8250_pnp.c [deleted file]
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/jsm/jsm_driver.c
drivers/tty/serial/max3107-aava.c [deleted file]
drivers/tty/serial/omap-serial.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/samsung.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_cs.c [deleted file]
drivers/tty/serial/sh-sci.c
drivers/tty/tty_port.c
drivers/tty/vt/vt_ioctl.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/epautoconf.c
drivers/usb/gadget/f_loopback.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/langwell_udc.c
drivers/usb/gadget/langwell_udc.h
drivers/usb/gadget/storage_common.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-fsl.h
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-xilinx-of.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/emi26.c
drivers/usb/misc/emi62.c
drivers/usb/misc/usbsevseg.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_io.h
drivers/usb/musb/omap2430.c
drivers/usb/musb/ux500_dma.c
drivers/usb/otg/Kconfig
drivers/usb/otg/Makefile
drivers/usb/otg/langwell_otg.c [deleted file]
drivers/usb/otg/mv_otg.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/option.c
drivers/usb/serial/qcaux.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/ti_usb_3410_5052.h
drivers/usb/storage/realtek_cr.c
drivers/usb/storage/usb.c
drivers/usb/storage/usb.h
drivers/usb/usb-skeleton.c
drivers/usb/wusbcore/Kconfig
drivers/vhost/net.c
drivers/video/atmel_lcdfb.c
drivers/video/backlight/adp8860_bl.c
drivers/video/backlight/adp8870_bl.c
drivers/video/backlight/l4f00242t03.c
drivers/video/fsl-diu-fb.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/macfb.c
drivers/video/mx3fb.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/ti_hdmi.h
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
drivers/video/omap2/dss/venc.c
drivers/virtio/virtio_ring.c
drivers/watchdog/dw_wdt.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/nuc900_wdt.c
drivers/watchdog/omap_wdt.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/stmp3xxx_wdt.c
drivers/watchdog/via_wdt.c
drivers/watchdog/wafer5823wdt.c
drivers/watchdog/wm8350_wdt.c
drivers/xen/biomerge.c
drivers/xen/cpu_hotplug.c
drivers/xen/grant-table.c
drivers/xen/xen-balloon.c
drivers/xen/xen-pciback/pci_stub.c
drivers/xen/xen-pciback/xenbus.c
drivers/xen/xenbus/xenbus_dev_frontend.c
firmware/Makefile
firmware/isci/isci_firmware.bin.ihex [deleted file]
fs/autofs4/expire.c
fs/bio.c
fs/btrfs/Kconfig
fs/btrfs/Makefile
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/btrfs_inode.h
fs/btrfs/check-integrity.c [new file with mode: 0644]
fs/btrfs/check-integrity.h [new file with mode: 0644]
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-ref.c
fs/btrfs/delayed-ref.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/export.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/locking.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/ulist.c [new file with mode: 0644]
fs/btrfs/ulist.h [new file with mode: 0644]
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/btrfs/xattr.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/xattr.c
fs/cifs/Kconfig
fs/cifs/cifs_debug.c
fs/cifs/cifs_spnego.c
fs/cifs/cifs_unicode.c
fs/cifs/cifs_unicode.h
fs/cifs/cifsacl.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/cifs/smbencrypt.c
fs/compat.c
fs/dcache.c
fs/debugfs/file.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/miscdev.c
fs/ecryptfs/mmap.c
fs/ecryptfs/read_write.c
fs/ecryptfs/super.c
fs/exec.c
fs/ext2/ioctl.c
fs/fs-writeback.c
fs/inode.c
fs/ioprio.c
fs/jbd/checkpoint.c
fs/jbd/recovery.c
fs/jffs2/erase.c
fs/logfs/dev_mtd.c
fs/logfs/dir.c
fs/logfs/file.c
fs/logfs/gc.c
fs/logfs/inode.c
fs/logfs/journal.c
fs/logfs/logfs.h
fs/logfs/readwrite.c
fs/logfs/segment.c
fs/logfs/super.c
fs/namei.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nilfs2/ioctl.c
fs/ocfs2/namei.c
fs/proc/base.c
fs/proc/stat.c
fs/proc/task_mmu.c
fs/qnx4/inode.c
fs/quota/dquot.c
fs/quota/quota.c
fs/select.c
fs/super.c
fs/sysfs/file.c
fs/sysfs/inode.c
fs/xfs/kmem.h
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_file.c
fs/xfs/xfs_fs_subr.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm.h
fs/xfs/xfs_qm_stats.c
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_super.c
fs/xfs/xfs_sync.c
fs/xfs/xfs_trace.h
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans_dquot.c
fs/xfs/xfs_vnodeops.c
include/acpi/acnames.h
include/acpi/acpi_numa.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/acrestyp.h
include/acpi/actbl.h
include/acpi/actbl1.h
include/acpi/actbl3.h [new file with mode: 0644]
include/acpi/actypes.h
include/acpi/atomicio.h [deleted file]
include/acpi/processor.h
include/asm-generic/io-64-nonatomic-hi-lo.h [new file with mode: 0644]
include/asm-generic/io-64-nonatomic-lo-hi.h [new file with mode: 0644]
include/asm-generic/pci_iomap.h
include/drm/drmP.h
include/keys/user-type.h
include/linux/acpi.h
include/linux/acpi_io.h
include/linux/amba/pl08x.h
include/linux/audit.h
include/linux/bcma/bcma.h
include/linux/binfmts.h
include/linux/bitops.h
include/linux/blkdev.h
include/linux/cdrom.h
include/linux/cpuidle.h
include/linux/device.h
include/linux/digsig.h
include/linux/dmaengine.h
include/linux/dw_dmac.h
include/linux/elevator.h
include/linux/freezer.h
include/linux/fs.h
include/linux/gpio_keys.h
include/linux/hyperv.h
include/linux/if_team.h
include/linux/iocontext.h
include/linux/kexec.h
include/linux/key.h
include/linux/kref.h
include/linux/lp8727.h [changed mode: 0755->0644]
include/linux/mfd/mcp.h
include/linux/mfd/twl6040.h
include/linux/mfd/ucb1x00.h
include/linux/migrate.h
include/linux/migrate_mode.h [new file with mode: 0644]
include/linux/miscdevice.h
include/linux/mlx4/device.h
include/linux/mmc/card.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/host.h
include/linux/mod_devicetable.h
include/linux/mpi.h
include/linux/mtd/gpmi-nand.h [new file with mode: 0644]
include/linux/mtd/mtd.h
include/linux/netfilter/nf_conntrack_common.h
include/linux/netfilter/xt_CT.h
include/linux/nfs_xdr.h
include/linux/nvme.h [new file with mode: 0644]
include/linux/perf_event.h
include/linux/pm_qos.h
include/linux/proportions.h
include/linux/ptrace.h
include/linux/quota.h
include/linux/res_counter.h
include/linux/sched.h
include/linux/sh_dma.h
include/linux/shmem_fs.h
include/linux/sirfsoc_dma.h [new file with mode: 0644]
include/linux/snmp.h
include/linux/suspend.h
include/linux/swap.h
include/linux/syscalls.h
include/linux/sysdev.h [deleted file]
include/linux/thermal.h
include/linux/tty_driver.h
include/linux/usb.h
include/linux/usb/ch11.h
include/linux/usb/ch9.h
include/linux/usb/langwell_otg.h [deleted file]
include/media/tuner.h
include/net/bluetooth/hci.h
include/net/cfg80211.h
include/net/flow.h
include/net/netns/generic.h
include/net/netprio_cgroup.h
include/net/route.h
include/net/sch_generic.h
include/net/sock.h
include/net/tcp.h
include/scsi/libfc.h
include/sound/core.h
include/target/target_core_backend.h [new file with mode: 0644]
include/target/target_core_base.h
include/target/target_core_device.h [deleted file]
include/target/target_core_fabric.h [new file with mode: 0644]
include/target/target_core_fabric_lib.h [deleted file]
include/target/target_core_fabric_ops.h [deleted file]
include/target/target_core_tmr.h [deleted file]
include/target/target_core_tpg.h [deleted file]
include/target/target_core_transport.h [deleted file]
include/trace/events/btrfs.h
include/trace/events/writeback.h
include/video/omapdss.h
init/Kconfig
ipc/mqueue.c
ipc/shm.c
kernel/audit.c
kernel/audit.h
kernel/auditfilter.c
kernel/auditsc.c
kernel/capability.c
kernel/events/callchain.c
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/kprobes.c
kernel/params.c
kernel/pid.c
kernel/power/power.h
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/user.c
kernel/rcutorture.c
kernel/relay.c
kernel/res_counter.c
kernel/sched/core.c
kernel/sched/cpupri.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/seccomp.c
kernel/tracepoint.c
kernel/watchdog.c
lib/Kconfig
lib/Makefile
lib/bug.c
lib/clz_tab.c [new file with mode: 0644]
lib/digsig.c
lib/kstrtox.c
lib/mpi/longlong.h
lib/mpi/mpi-bit.c
lib/mpi/mpi-div.c
lib/mpi/mpi-pow.c
lib/mpi/mpicoder.c
lib/mpi/mpih-div.c
lib/mpi/mpiutil.c
lib/pci_iomap.c
mm/backing-dev.c
mm/compaction.c
mm/filemap.c
mm/filemap_xip.c
mm/huge_memory.c
mm/hugetlb.c
mm/kmemleak.c
mm/memblock.c
mm/memcontrol.c
mm/memory.c
mm/migrate.c
mm/page_alloc.c
mm/process_vm_access.c
mm/shmem.c
mm/swap.c
mm/vmscan.c
net/bluetooth/hci_core.c
net/bridge/br_fdb.c
net/caif/caif_dev.c
net/caif/caif_socket.c
net/caif/caif_usb.c
net/caif/cfcnfg.c
net/caif/cfmuxl.c
net/ceph/ceph_common.c
net/ceph/mon_client.c
net/core/dev.c
net/core/ethtool.c
net/core/flow_dissector.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/core/netpoll.c
net/core/netprio_cgroup.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/secure_seq.c
net/core/sock.c
net/ipv4/Kconfig
net/ipv4/arp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inetpeer.c
net/ipv4/ip_gre.c
net/ipv4/ip_options.c
net/ipv4/ipconfig.c
net/ipv4/ping.c
net/ipv4/proc.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_bic.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/udp_diag.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/proc.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/l2tp/l2tp_ip.c
net/llc/af_llc.c
net/mac80211/cfg.c
net/mac80211/debugfs_key.c
net/mac80211/ibss.c
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/tx.c
net/mac80211/wpa.c
net/mac80211/wpa.h
net/netfilter/ipset/ip_set_core.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/xt_CT.c
net/netfilter/xt_hashlimit.c
net/openvswitch/datapath.c
net/openvswitch/datapath.h
net/openvswitch/flow.c
net/openvswitch/vport-internal_dev.c
net/openvswitch/vport.c
net/rds/af_rds.c
net/rxrpc/ar-key.c
net/sched/sch_choke.c
net/sched/sch_netem.c
net/sched/sch_sfb.c
net/sched/sch_sfq.c
net/sunrpc/auth_generic.c
net/unix/af_unix.c
scripts/checkpatch.pl
scripts/kernel-doc
scripts/mod/file2alias.c
scripts/mod/modpost.c
security/integrity/Kconfig
security/integrity/Makefile
security/integrity/ima/ima_audit.c
security/integrity/ima/ima_policy.c
security/integrity/integrity.h
security/keys/encrypted-keys/encrypted.c
security/keys/encrypted-keys/masterkey_trusted.c
security/keys/gc.c
security/keys/internal.h
security/keys/key.c
security/keys/keyring.c
security/keys/trusted.c
security/keys/user_defined.c
security/lsm_audit.c
security/tomoyo/util.c
sound/atmel/abdac.c
sound/atmel/ac97c.c
sound/core/Kconfig
sound/core/compress_offload.c
sound/isa/sb/emu8000_patch.c
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0.h
sound/pci/au88x0/au88x0_pcm.c
sound/pci/hda/alc880_quirks.c
sound/pci/hda/alc882_quirks.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.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/oxygen/oxygen_mixer.c
sound/pci/oxygen/xonar_wm87x6.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/cs42l73.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm8996.h
sound/soc/codecs/wm_hubs.c
sound/soc/ep93xx/ep93xx-pcm.c
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-saif.c
sound/soc/samsung/dma.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/sh/fsi.c
sound/soc/sh/siu_pcm.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/txx9/txx9aclc.c
sound/usb/caiaq/audio.c
sound/usb/card.h
sound/usb/format.c
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/perf/Makefile
tools/perf/bench/mem-memcpy-x86-64-asm.S
tools/perf/builtin-probe.c
tools/perf/builtin-top.c
tools/perf/util/event.c
tools/perf/util/evsel.c
tools/perf/util/header.c
tools/perf/util/probe-event.c
tools/perf/util/symbol.c
tools/perf/util/trace-event-parse.c
tools/perf/util/ui/browsers/hists.c
tools/perf/util/ui/helpline.c
tools/perf/util/util.h
tools/power/x86/turbostat/turbostat.c
virt/kvm/kvm_main.c

index b638e50cf8f604b8bacb3a4a0f974653ca055071..9c27e5125dd26efb5ca49c4b2bc9beadb4d559d7 100644 (file)
@@ -50,7 +50,9 @@
 
      <sect1><title>Delaying, scheduling, and timer routines</title>
 !Iinclude/linux/sched.h
-!Ekernel/sched.c
+!Ekernel/sched/core.c
+!Ikernel/sched/cpupri.c
+!Ikernel/sched/fair.c
 !Iinclude/linux/completion.h
 !Ekernel/timer.c
      </sect1>
@@ -100,9 +102,12 @@ X!Iinclude/linux/kobject.h
 !Iinclude/linux/device.h
      </sect1>
      <sect1><title>Device Drivers Base</title>
+!Idrivers/base/init.c
 !Edrivers/base/driver.c
 !Edrivers/base/core.c
+!Edrivers/base/syscore.c
 !Edrivers/base/class.c
+!Idrivers/base/node.c
 !Edrivers/base/firmware_class.c
 !Edrivers/base/transport_class.c
 <!-- Cannot be included, because
@@ -111,13 +116,18 @@ X!Iinclude/linux/kobject.h
      exceed allowed 44 characters maximum
 X!Edrivers/base/attribute_container.c
 -->
-!Edrivers/base/sys.c
+!Edrivers/base/dd.c
 <!--
 X!Edrivers/base/interface.c
 -->
 !Iinclude/linux/platform_device.h
 !Edrivers/base/platform.c
 !Edrivers/base/bus.c
+     </sect1>
+     <sect1><title>Device Drivers DMA Management</title>
+!Edrivers/base/dma-buf.c
+!Edrivers/base/dma-coherent.c
+!Edrivers/base/dma-mapping.c
      </sect1>
      <sect1><title>Device Drivers Power Management</title>
 !Edrivers/base/power/main.c
@@ -216,9 +226,8 @@ X!Isound/sound_firmware.c
 
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
-!Iinclude/linux/serial_core.h
 !Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250.c
+!Edrivers/tty/serial/8250/8250.c
   </chapter>
 
   <chapter id="fbdev">
index c1ed6a49e598cd992552fa6e3b0da70f59aa7829..54199a0dcf9adc325d61a168d54fa913742faebf 100644 (file)
@@ -317,7 +317,7 @@ CPU B:  spin_unlock_irqrestore(&amp;dev_lock, flags)
   <chapter id="pubfunctions">
      <title>Public Functions Provided</title>
 !Iarch/x86/include/asm/io.h
-!Elib/iomap.c
+!Elib/pci_iomap.c
   </chapter>
 
 </book>
index ffee1fbbc001ae316f40be9def3b2456e20c9118..c7a4ca51785980264b37b19b3b63987a3871fe33 100644 (file)
@@ -163,14 +163,16 @@ get/set up to 64 properties. The actual meaning of each property is described on
        <section id="DTV-FREQUENCY">
                <title><constant>DTV_FREQUENCY</constant></title>
 
-               <para>Central frequency of the channel, in HZ.</para>
+               <para>Central frequency of the channel.</para>
 
                <para>Notes:</para>
-               <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
+               <para>1)For satellital delivery systems, it is measured in kHz.
+                       For the other ones, it is measured in Hz.</para>
+               <para>2)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
                        E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
                        the channel which is 6MHz.</para>
 
-               <para>2)As in ISDB-Tsb the channel consists of only one or three segments the
+               <para>3)As in ISDB-Tsb the channel consists of only one or three segments the
                        frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
                        central frequency of the channel is expected.</para>
        </section>
@@ -735,14 +737,10 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ISDBT-LAYER-ENABLED"><constant>DTV_ISDBT_LAYER_ENABLED</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ISDBT-PARTIAL-RECEPTION"><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ISDBT-SOUND-BROADCASTING"><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></link></para></listitem>
index 6f1f9a629dc34d1508bd550342d810f05f2b5028..b17a7aac6997482379e1b43c8b0d7e5cf914e1f0 100644 (file)
@@ -183,7 +183,12 @@ applications must set the array to zero.</entry>
            <entry>__u32</entry>
            <entry><structfield>ctrl_class</structfield></entry>
            <entry>The control class to which all controls belong, see
-<xref linkend="ctrl-class" />.</entry>
+<xref linkend="ctrl-class" />. Drivers that use a kernel framework for handling
+controls will also accept a value of 0 here, meaning that the controls can
+belong to any control class. Whether drivers support this can be tested by setting
+<structfield>ctrl_class</structfield> to 0 and calling <constant>VIDIOC_TRY_EXT_CTRLS</constant>
+with a <structfield>count</structfield> of 0. If that succeeds, then the driver
+supports this feature.</entry>
          </row>
          <row>
            <entry>__u32</entry>
@@ -194,10 +199,13 @@ also be zero.</entry>
          <row>
            <entry>__u32</entry>
            <entry><structfield>error_idx</structfield></entry>
-           <entry>Set by the driver in case of an error. It is the
-index of the control causing the error or equal to 'count' when the
-error is not associated with a particular control. Undefined when the
-ioctl returns 0 (success).</entry>
+           <entry>Set by the driver in case of an error. If it is equal
+to <structfield>count</structfield>, then no actual changes were made to
+controls. In other words, the error was not associated with setting a particular
+control. If it is another value, then only the controls up to <structfield>error_idx-1</structfield>
+were modified and control <structfield>error_idx</structfield> is the one that
+caused the error. The <structfield>error_idx</structfield> value is undefined
+if the ioctl returned 0 (success).</entry>
          </row>
          <row>
            <entry>__u32</entry>
index 93817f33703305beae49acafa52b1bceb0613dd2..7c63815e7afd0eb964a1848513dea5be14eb677e 100644 (file)
@@ -364,15 +364,20 @@ capability and it is cleared otherwise.</entry>
          <row>
            <entry><constant>V4L2_FBUF_FLAG_OVERLAY</constant></entry>
            <entry>0x0002</entry>
-           <entry>The frame buffer is an overlay surface the same
-size as the capture. [?]</entry>
-         </row>
-         <row>
-           <entry spanname="hspan">The purpose of
-<constant>V4L2_FBUF_FLAG_OVERLAY</constant> was never quite clear.
-Most drivers seem to ignore this flag. For compatibility with the
-<wordasword>bttv</wordasword> driver applications should set the
-<constant>V4L2_FBUF_FLAG_OVERLAY</constant> flag.</entry>
+           <entry>If this flag is set for a video capture device, then the
+driver will set the initial overlay size to cover the full framebuffer size,
+otherwise the existing overlay size (as set by &VIDIOC-S-FMT;) will be used.
+
+Only one video capture driver (bttv) supports this flag. The use of this flag
+for capture devices is deprecated. There is no way to detect which drivers
+support this flag, so the only reliable method of setting the overlay size is
+through &VIDIOC-S-FMT;.
+
+If this flag is set for a video output device, then the video output overlay
+window is relative to the top-left corner of the framebuffer and restricted
+to the size of the framebuffer. If it is cleared, then the video output
+overlay window is relative to the video output display.
+            </entry>
          </row>
          <row>
            <entry><constant>V4L2_FBUF_FLAG_CHROMAKEY</constant></entry>
index 16431813bebd253f87965029088ee733328c36e5..66e9a5257861ab1c5f65b197e3bc7e52304659e6 100644 (file)
@@ -98,8 +98,11 @@ the &v4l2-output; <structfield>modulator</structfield> field and the
            <entry>&v4l2-tuner-type;</entry>
            <entry><structfield>type</structfield></entry>
            <entry>The tuner type. This is the same value as in the
-&v4l2-tuner; <structfield>type</structfield> field. The field is not
-applicable to modulators, &ie; ignored by drivers.</entry>
+&v4l2-tuner; <structfield>type</structfield> field. The type must be set
+to <constant>V4L2_TUNER_RADIO</constant> for <filename>/dev/radioX</filename>
+device nodes, and to <constant>V4L2_TUNER_ANALOG_TV</constant>
+for all others. The field is not applicable to modulators, &ie; ignored
+by drivers.</entry>
          </row>
          <row>
            <entry>__u32</entry>
index 08ae82f131f2b952df2a0f5488b49d0747776153..1d43065090dd1087be1c26a8f54804ac8a4ee2c2 100644 (file)
@@ -61,8 +61,8 @@ desired input in an integer and call the
 <constant>VIDIOC_S_INPUT</constant> ioctl with a pointer to this
 integer. Side effects are possible. For example inputs may support
 different video standards, so the driver may implicitly switch the
-current standard. It is good practice to select an input before
-querying or negotiating any other parameters.</para>
+current standard. Because of these possible side effects applications
+must select an input before querying or negotiating any other parameters.</para>
 
     <para>Information about video inputs is available using the
 &VIDIOC-ENUMINPUT; ioctl.</para>
index fd45f1c13ccf445b89e582036b40c3a7a94ab86c..4533068ecb8ad5dd221512d5f6dc8a7266b66ecb 100644 (file)
@@ -61,8 +61,9 @@ desired output in an integer and call the
 <constant>VIDIOC_S_OUTPUT</constant> ioctl with a pointer to this integer.
 Side effects are possible. For example outputs may support different
 video standards, so the driver may implicitly switch the current
-standard. It is good practice to select an output before querying or
-negotiating any other parameters.</para>
+standard.
+standard. Because of these possible side effects applications
+must select an output before querying or negotiating any other parameters.</para>
 
     <para>Information about video outputs is available using the
 &VIDIOC-ENUMOUTPUT; ioctl.</para>
index 5cc699ba5453479ea13a028236f0d568063edb1e..e7cc363972173ca0177de6bfb7ce3f38de89bde2 100644 (file)
@@ -47,20 +47,53 @@ directory apei/einj. The following files are provided.
 
 - param1
   This file is used to set the first error parameter value. Effect of
-  parameter depends on error_type specified. For memory error, this is
-  physical memory address.  Only available if param_extension module
-  parameter is specified.
+  parameter depends on error_type specified.
 
 - param2
   This file is used to set the second error parameter value. Effect of
-  parameter depends on error_type specified. For memory error, this is
-  physical memory address mask.  Only available if param_extension
-  module parameter is specified.
+  parameter depends on error_type specified.
+
+BIOS versions based in the ACPI 4.0 specification have limited options
+to control where the errors are injected.  Your BIOS may support an
+extension (enabled with the param_extension=1 module parameter, or
+boot command line einj.param_extension=1). This allows the address
+and mask for memory injections to be specified by the param1 and
+param2 files in apei/einj.
+
+BIOS versions using the ACPI 5.0 specification have more control over
+the target of the injection. For processor related errors (type 0x1,
+0x2 and 0x4) the APICID of the target should be provided using the
+param1 file in apei/einj. For memory errors (type 0x8, 0x10 and 0x20)
+the address is set using param1 with a mask in param2 (0x0 is equivalent
+to all ones). For PCI express errors (type 0x40, 0x80 and 0x100) the
+segment, bus, device and function are specified using param1:
+
+         31     24 23    16 15    11 10      8  7        0
+       +-------------------------------------------------+
+       | segment |   bus  | device | function | reserved |
+       +-------------------------------------------------+
+
+An ACPI 5.0 BIOS may also allow vendor specific errors to be injected.
+In this case a file named vendor will contain identifying information
+from the BIOS that hopefully will allow an application wishing to use
+the vendor specific extension to tell that they are running on a BIOS
+that supports it. All vendor extensions have the 0x80000000 bit set in
+error_type. A file vendor_flags controls the interpretation of param1
+and param2 (1 = PROCESSOR, 2 = MEMORY, 4 = PCI). See your BIOS vendor
+documentation for details (and expect changes to this API if vendors
+creativity in using this feature expands beyond our expectations).
+
+Example:
+# cd /sys/kernel/debug/apei/einj
+# cat available_error_type             # See which errors can be injected
+0x00000002     Processor Uncorrectable non-fatal
+0x00000008     Memory Correctable
+0x00000010     Memory Uncorrectable non-fatal
+# echo 0x12345000 > param1             # Set memory address for injection
+# echo 0xfffffffffffff000 > param2     # Mask - anywhere in this page
+# echo 0x8 > error_type                        # Choose correctable memory error
+# echo 1 > error_inject                        # Inject now
 
-Injecting parameter support is a BIOS version specific extension, that
-is, it only works on some BIOS version.  If you want to use it, please
-make sure your BIOS version has the proper support and specify
-"param_extension=y" in module parameter.
 
 For more information about EINJ, please refer to ACPI specification
-version 4.0, section 17.5.
+version 4.0, section 17.5 and ACPI 5.0, section 18.6.
index cec8864ce4e8cbb4089b68279255c51645938554..00383186d8fb3e2c0fc4d5a12852844cb5b2721f 100644 (file)
@@ -447,6 +447,9 @@ Your cooperation is appreciated.
                234 = /dev/btrfs-control        Btrfs control device
                235 = /dev/autofs       Autofs control device
                236 = /dev/mapper/control       Device-Mapper control device
+               237 = /dev/loop-control Loopback control device
+               238 = /dev/vhost-net    Host kernel accelerator for virtio net
+
                240-254                 Reserved for local use
                255                     Reserved for MISC_DYNAMIC_MINOR
 
diff --git a/Documentation/devicetree/bindings/dma/atmel-dma.txt b/Documentation/devicetree/bindings/dma/atmel-dma.txt
new file mode 100644 (file)
index 0000000..3c046ee
--- /dev/null
@@ -0,0 +1,14 @@
+* Atmel Direct Memory Access Controller (DMA)
+
+Required properties:
+- compatible: Should be "atmel,<chip>-dma"
+- reg: Should contain DMA registers location and length
+- interrupts: Should contain DMA interrupt
+
+Examples:
+
+dma@ffffec00 {
+       compatible = "atmel,at91sam9g45-dma";
+       reg = <0xffffec00 0x200>;
+       interrupts = <21>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/omap-i2c.txt b/Documentation/devicetree/bindings/i2c/omap-i2c.txt
new file mode 100644 (file)
index 0000000..56564aa
--- /dev/null
@@ -0,0 +1,30 @@
+I2C for OMAP platforms
+
+Required properties :
+- compatible : Must be "ti,omap3-i2c" or "ti,omap4-i2c"
+- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Recommended properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. Otherwise
+  the default 100 kHz frequency will be used.
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
+
+Note: Current implementation will fetch base address, irq and dma
+from omap hwmod data base during device registration.
+Future plan is to migrate hwmod data base contents into device tree
+blob so that, all the required data will be used from device tree dts
+file.
+
+Examples :
+
+i2c1: i2c@0 {
+    compatible = "ti,omap3-i2c";
+    #address-cells = <1>;
+    #size-cells = <0>;
+    ti,hwmods = "i2c1";
+    clock-frequency = <400000>;
+};
index 94b7e0f96b38fa8086ea14f7cd88718b45e84d70..bbe6cb3d1856b8943dd04d3449af9d39d5c1e7dc 100644 (file)
@@ -75,6 +75,10 @@ The slave DMA usage consists of following steps:
    slave_sg    - DMA a list of scatter gather buffers from/to a peripheral
    dma_cyclic  - Perform a cyclic DMA operation from/to a peripheral till the
                  operation is explicitly stopped.
+   interleaved_dma - This is common to Slave as well as M2M clients. For slave
+                address of devices' fifo could be already known to the driver.
+                Various types of operations could be expressed by setting
+                appropriate values to the 'dma_interleaved_template' members.
 
    A non-NULL return of this transfer API represents a "descriptor" for
    the given transaction.
@@ -89,6 +93,10 @@ The slave DMA usage consists of following steps:
                struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
                size_t period_len, enum dma_data_direction direction);
 
+       struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
+               struct dma_chan *chan, struct dma_interleaved_template *xt,
+               unsigned long flags);
+
    The peripheral driver is expected to have mapped the scatterlist for
    the DMA operation prior to calling device_prep_slave_sg, and must
    keep the scatterlist mapped until the DMA operation has completed.
index 10c64c8a13d4f2aec7bebb0bd6a44ce401aa78cc..41c0c5d1ba145a392e17d42dc4ce8ac9c3c41a49 100644 (file)
@@ -233,6 +233,10 @@ certainly invest a bit more effort into libata core layer).
   6. List of managed interfaces
   -----------------------------
 
+MEM
+  devm_kzalloc()
+  devm_kfree()
+
 IO region
   devm_request_region()
   devm_request_mem_region()
index d725c0dfe032f0692ab9de9a4358dfdcdd711f39..a0ffac029a0dc703322d922f3ec59435e3315ef3 100644 (file)
@@ -439,17 +439,6 @@ Who:       Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
 
-What:  For VIDIOC_S_FREQUENCY the type field must match the device node's type.
-       If not, return -EINVAL.
-When:  3.2
-Why:   It makes no sense to switch the tuner to radio mode by calling
-       VIDIOC_S_FREQUENCY on a video node, or to switch the tuner to tv mode by
-       calling VIDIOC_S_FREQUENCY on a radio node. This is the first step of a
-       move to more consistent handling of tv and radio tuners.
-Who:   Hans Verkuil <hans.verkuil@cisco.com>
-
-----------------------------
-
 What:  Opening a radio device node will no longer automatically switch the
        tuner mode from tv to radio.
 When:  3.3
@@ -521,3 +510,17 @@ Why:       The pci_scan_bus_parented() interface creates a new root bus.  The
        convert to using pci_scan_root_bus() so they can supply a list of
        bus resources when the bus is created.
 Who:   Bjorn Helgaas <bhelgaas@google.com>
+
+----------------------------
+
+What:  The CAP9 SoC family will be removed
+When:  3.4
+Files: arch/arm/mach-at91/at91cap9.c
+       arch/arm/mach-at91/at91cap9_devices.c
+       arch/arm/mach-at91/include/mach/at91cap9.h
+       arch/arm/mach-at91/include/mach/at91cap9_matrix.h
+       arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
+       arch/arm/mach-at91/board-cap9adk.c
+Why:   The code is not actively maintained and platforms are now hard to find.
+Who:   Nicolas Ferre <nicolas.ferre@atmel.com>
+       Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
index 23fcb05175be70e0d140febdc153751763f38d04..53305bd08182dac8db030112ed9dadf1bf99efc9 100644 (file)
@@ -17,11 +17,11 @@ reports supported by a device are also provided by sysfs in
 class/input/event*/device/capabilities/, and the properties of a device are
 provided in class/input/event*/device/properties.
 
-Types:
-==========
-Types are groupings of codes under a logical input construct. Each type has a
-set of applicable codes to be used in generating events. See the Codes section
-for details on valid codes for each type.
+Event types:
+===========
+Event types are groupings of codes under a logical input construct. Each
+type has a set of applicable codes to be used in generating events. See the
+Codes section for details on valid codes for each type.
 
 * EV_SYN:
   - Used as markers to separate events. Events may be separated in time or in
@@ -63,9 +63,9 @@ for details on valid codes for each type.
 * EV_FF_STATUS:
   - Used to receive force feedback device status.
 
-Codes:
-==========
-Codes define the precise type of event.
+Event codes:
+===========
+Event codes define the precise type of event.
 
 EV_SYN:
 ----------
@@ -220,6 +220,56 @@ EV_PWR:
 EV_PWR events are a special type of event used specifically for power
 mangement. Its usage is not well defined. To be addressed later.
 
+Device properties:
+=================
+Normally, userspace sets up an input device based on the data it emits,
+i.e., the event types. In the case of two devices emitting the same event
+types, additional information can be provided in the form of device
+properties.
+
+INPUT_PROP_DIRECT + INPUT_PROP_POINTER:
+--------------------------------------
+The INPUT_PROP_DIRECT property indicates that device coordinates should be
+directly mapped to screen coordinates (not taking into account trivial
+transformations, such as scaling, flipping and rotating). Non-direct input
+devices require non-trivial transformation, such as absolute to relative
+transformation for touchpads. Typical direct input devices: touchscreens,
+drawing tablets; non-direct devices: touchpads, mice.
+
+The INPUT_PROP_POINTER property indicates that the device is not transposed
+on the screen and thus requires use of an on-screen pointer to trace user's
+movements.  Typical pointer devices: touchpads, tablets, mice; non-pointer
+device: touchscreen.
+
+If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is
+considered undefined and the device type should be deduced in the
+traditional way, using emitted event types.
+
+INPUT_PROP_BUTTONPAD:
+--------------------
+For touchpads where the button is placed beneath the surface, such that
+pressing down on the pad causes a button click, this property should be
+set. Common in clickpad notebooks and macbooks from 2009 and onwards.
+
+Originally, the buttonpad property was coded into the bcm5974 driver
+version field under the name integrated button. For backwards
+compatibility, both methods need to be checked in userspace.
+
+INPUT_PROP_SEMI_MT:
+------------------
+Some touchpads, most common between 2008 and 2011, can detect the presence
+of multiple contacts without resolving the individual positions; only the
+number of contacts and a rectangular shape is known. For such
+touchpads, the semi-mt property should be set.
+
+Depending on the device, the rectangle may enclose all touches, like a
+bounding box, or just some of them, for instance the two most recent
+touches. The diversity makes the rectangle of limited use, but some
+gestures can normally be extracted from it.
+
+If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT
+device.
+
 Guidelines:
 ==========
 The guidelines below ensure proper single-touch and multi-finger functionality.
@@ -240,6 +290,8 @@ used to report when a touch is active on the screen.
 BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
 contact. BTN_TOOL_<name> events should be reported where possible.
 
+For new hardware, INPUT_PROP_DIRECT should be set.
+
 Trackpads:
 ----------
 Legacy trackpads that only provide relative position information must report
@@ -250,6 +302,8 @@ location of the touch. BTN_TOUCH should be used to report when a touch is active
 on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should
 be used to report the number of touches active on the trackpad.
 
+For new hardware, INPUT_PROP_POINTER should be set.
+
 Tablets:
 ----------
 BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
@@ -260,3 +314,5 @@ button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}.
 BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use
 meaningful buttons, like BTN_FORWARD, unless the button is labeled for that
 purpose on the device.
+
+For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set.
index 54078ed96b3751724acaf0bd3fdab95df962480f..4840334ea97b30705df13a2c642e976a83621800 100644 (file)
@@ -149,6 +149,7 @@ Code  Seq#(hex)     Include File            Comments
 'M'    01-03   drivers/scsi/megaraid/megaraid_sas.h
 'M'    00-0F   drivers/video/fsl-diu-fb.h      conflict!
 'N'    00-1F   drivers/usb/scanner.h
+'N'    40-7F   drivers/block/nvme.c
 'O'     00-06   mtd/ubi-user.h         UBI
 'P'    all     linux/soundcard.h       conflict!
 'P'    60-6F   sound/sscape_ioctl.h    conflict!
index b29f3c416296ef880203a02c1d9b8c707f09206a..033d4e69b43b107d9780ec959105823e6cefd07c 100644 (file)
@@ -1059,6 +1059,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        By default, super page will be supported if Intel IOMMU
                        has the capability. With this option, super page will
                        not be supported.
+
+       intel_idle.max_cstate=  [KNL,HW,ACPI,X86]
+                       0       disables intel_idle and fall back on acpi_idle.
+                       1 to 6  specify maximum depth of C-state.
+
        intremap=       [X86-64, Intel-IOMMU]
                        on      enable Interrupt Remapping (default)
                        off     disable Interrupt Remapping
index 6727b92bc2fb9db3f700d3056c1360e0297c09b5..150fd3833d0bfa114e39ce8d8d6687425aace459 100644 (file)
@@ -857,42 +857,41 @@ case), we define a mapping like this:
 
 ...
 {
-       .name "2bit"
+       .name "2bit"
        .ctrl_dev_name = "pinctrl-foo",
        .function = "mmc0",
        .group = "mmc0_1_grp",
        .dev_name = "foo-mmc.0",
 },
 {
-       .name "4bit"
+       .name "4bit"
        .ctrl_dev_name = "pinctrl-foo",
        .function = "mmc0",
        .group = "mmc0_1_grp",
        .dev_name = "foo-mmc.0",
 },
 {
-       .name "4bit"
+       .name "4bit"
        .ctrl_dev_name = "pinctrl-foo",
        .function = "mmc0",
        .group = "mmc0_2_grp",
        .dev_name = "foo-mmc.0",
 },
 {
-       .name "8bit"
+       .name "8bit"
        .ctrl_dev_name = "pinctrl-foo",
-       .function = "mmc0",
        .group = "mmc0_1_grp",
        .dev_name = "foo-mmc.0",
 },
 {
-       .name "8bit"
+       .name "8bit"
        .ctrl_dev_name = "pinctrl-foo",
        .function = "mmc0",
        .group = "mmc0_2_grp",
        .dev_name = "foo-mmc.0",
 },
 {
-       .name "8bit"
+       .name "8bit"
        .ctrl_dev_name = "pinctrl-foo",
        .function = "mmc0",
        .group = "mmc0_3_grp",
@@ -995,7 +994,7 @@ This is enabled by simply setting the .hog_on_boot field in the map to true,
 like this:
 
 {
-       .name "POWERMAP"
+       .name "POWERMAP"
        .ctrl_dev_name = "pinctrl-foo",
        .function = "power_func",
        .hog_on_boot = true,
@@ -1025,7 +1024,7 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
 
 foo_switch()
 {
-       struct pinmux pmx;
+       struct pinmux *pmx;
 
        /* Enable on position A */
        pmx = pinmux_get(&device, "spi0-pos-A");
index 40a4c65f380a10479a7a805d58310be97b1a2ee1..262acf56fa79b6cb5973b5e408e6bcd8b437b33d 100644 (file)
@@ -15,7 +15,7 @@ test at least a couple of times in a row for confidence.  [This is necessary,
 because some problems only show up on a second attempt at suspending and
 resuming the system.]  Moreover, hibernating in the "reboot" and "shutdown"
 modes causes the PM core to skip some platform-related callbacks which on ACPI
-systems might be necessary to make hibernation work.  Thus, if you machine fails
+systems might be necessary to make hibernation work.  Thus, if your machine fails
 to hibernate or resume in the "reboot" mode, you should try the "platform" mode:
 
 # echo platform > /sys/power/disk
index 6ccb68f68da685a39cefc0c2bf0609924c292b38..ebd7490ef1df8eefdbaeb94ad656aeb091f9368f 100644 (file)
@@ -120,10 +120,10 @@ So in practice, the 'at all' may become a 'why freeze kernel threads?' and
 freezing user threads I don't find really objectionable."
 
 Still, there are kernel threads that may want to be freezable.  For example, if
-a kernel that belongs to a device driver accesses the device directly, it in
-principle needs to know when the device is suspended, so that it doesn't try to
-access it at that time.  However, if the kernel thread is freezable, it will be
-frozen before the driver's .suspend() callback is executed and it will be
+a kernel thread that belongs to a device driver accesses the device directly, it
+in principle needs to know when the device is suspended, so that it doesn't try
+to access it at that time.  However, if the kernel thread is freezable, it will
+be frozen before the driver's .suspend() callback is executed and it will be
 thawed after the driver's .resume() callback has run, so it won't be accessing
 the device while it's suspended.
 
index 64adb98b181c717f763bff24109bc8bf9aff104a..57566bacb4c56c8182f0e9b16bafe74c9b1233ab 100644 (file)
@@ -1,3 +1,13 @@
+Release Date    : Fri. Jan 6, 2012 17:00:00 PST 2010 -
+                       (emaild-id:megaraidlinux@lsi.com)
+                       Adam Radford
+Current Version : 00.00.06.14-rc1
+Old Version     : 00.00.06.12-rc1
+    1. Fix reglockFlags for degraded raid5/6 for MR 9360/9380.
+    2. Mask off flags in ioctl path to prevent memory scribble with older
+       MegaCLI versions.
+    3. Remove poll_mode_io module paramater, sysfs node, and associated code.
+-------------------------------------------------------------------------------
 Release Date    : Wed. Oct 5, 2011 17:00:00 PST 2010 -
                        (emaild-id:megaraidlinux@lsi.com)
                        Adam Radford
index 494980e404912a861a238423e9189708549eaa66..ab899591ecb7a93dfe6c8b936042c3b8f400bd42 100644 (file)
@@ -1,32 +1,11 @@
 Copyright (c) 2003-2011 QLogic Corporation
-QLogic Linux iSCSI HBA Driver
+QLogic Linux iSCSI Driver
 
 This program includes a device driver for Linux 3.x.
 You may modify and redistribute the device driver code under the
 GNU General Public License (a copy of which is attached hereto as
 Exhibit A) published by the Free Software Foundation (version 2).
 
-REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
-THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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.
-
-USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
-CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
-OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
-TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
-ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
-COMBINATION WITH THIS PROGRAM.
-
 
 EXHIBIT A
 
index 21fd05c28e738e146b313081bbd4294687ddabdf..f0ab5cf28fcae0a1ff0783bf8a4ddc477447f585 100644 (file)
@@ -25,7 +25,8 @@ Procedure for submitting patches to the -stable tree:
 
  - Send the patch, after verifying that it follows the above rules, to
    stable@vger.kernel.org.  You must note the upstream commit ID in the
-   changelog of your submission.
+   changelog of your submission, as well as the kernel version you wish
+   it to be applied to.
  - To have the patch automatically included in the stable tree, add the tag
      Cc: stable@vger.kernel.org
    in the sign-off area. Once the patch is merged it will be applied to
index 8c20fbd8b42dd922daa92f223bbefa9ffcc4f8e3..6d78841fd41677d4f81dbcb53eed7ab8602cddb4 100644 (file)
@@ -601,6 +601,8 @@ can be ORed together:
         instead of using the one provided by the hardware.
  512 - A kernel warning has occurred.
 1024 - A module from drivers/staging was loaded.
+2048 - The system is working around a severe firmware bug.
+4096 - An out-of-tree module has been loaded.
 
 ==============================================================
 
index 7ef9b843d529a5fadbe05eb19ad6c34fd8293cd5..6e21b8b52638a1f0ab014cd46b532d341ba17619 100755 (executable)
@@ -230,14 +230,9 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "#include <linux/ctype.h>\n"
        buf += "#include <asm/unaligned.h>\n\n"
        buf += "#include <target/target_core_base.h>\n"
-       buf += "#include <target/target_core_transport.h>\n"
-       buf += "#include <target/target_core_fabric_ops.h>\n"
+       buf += "#include <target/target_core_fabric.h>\n"
        buf += "#include <target/target_core_fabric_configfs.h>\n"
-       buf += "#include <target/target_core_fabric_lib.h>\n"
-       buf += "#include <target/target_core_device.h>\n"
-       buf += "#include <target/target_core_tpg.h>\n"
        buf += "#include <target/target_core_configfs.h>\n"
-       buf += "#include <target/target_core_base.h>\n"
        buf += "#include <target/configfs_macros.h>\n\n"
        buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
        buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
@@ -260,7 +255,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        /* " + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n"
        buf += "                return ERR_PTR(-EINVAL); */\n"
        buf += "        se_nacl_new = " + fabric_mod_name + "_alloc_fabric_acl(se_tpg);\n"
-       buf += "        if (!(se_nacl_new))\n"
+       buf += "        if (!se_nacl_new)\n"
        buf += "                return ERR_PTR(-ENOMEM);\n"
        buf += "//#warning FIXME: Hardcoded nexus depth in " + fabric_mod_name + "_make_nodeacl()\n"
        buf += "        nexus_depth = 1;\n"
@@ -308,7 +303,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        if (strict_strtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)\n"
        buf += "                return ERR_PTR(-EINVAL);\n\n"
        buf += "        tpg = kzalloc(sizeof(struct " + fabric_mod_name + "_tpg), GFP_KERNEL);\n"
-       buf += "        if (!(tpg)) {\n"
+       buf += "        if (!tpg) {\n"
        buf += "                printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_tpg\");\n"
        buf += "                return ERR_PTR(-ENOMEM);\n"
        buf += "        }\n"
@@ -344,7 +339,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        /* if (" + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n"
        buf += "                return ERR_PTR(-EINVAL); */\n\n"
        buf += "        " + fabric_mod_port + " = kzalloc(sizeof(struct " + fabric_mod_name + "_" + fabric_mod_port + "), GFP_KERNEL);\n"
-       buf += "        if (!(" + fabric_mod_port + ")) {\n"
+       buf += "        if (!" + fabric_mod_port + ") {\n"
        buf += "                printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_" + fabric_mod_port + "\");\n"
        buf += "                return ERR_PTR(-ENOMEM);\n"
        buf += "        }\n"
@@ -352,7 +347,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        if proto_ident == "FC" or proto_ident == "SAS":
                buf += "        " + fabric_mod_port + "->" + fabric_mod_port + "_wwpn = wwpn;\n"
 
-       buf += "        /* " + fabric_mod_name + "_format_wwn(&" + fabric_mod_port + "->" + fabric_mod_port + "_name[0], " + fabric_mod_name.upper() + "__NAMELEN, wwpn); */\n\n"
+       buf += "        /* " + fabric_mod_name + "_format_wwn(&" + fabric_mod_port + "->" + fabric_mod_port + "_name[0], " + fabric_mod_name.upper() + "_NAMELEN, wwpn); */\n\n"
        buf += "        return &" + fabric_mod_port + "->" + fabric_mod_port + "_wwn;\n"
        buf += "}\n\n"
        buf += "static void " + fabric_mod_name + "_drop_" + fabric_mod_port + "(struct se_wwn *wwn)\n"
@@ -391,8 +386,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        .tpg_alloc_fabric_acl           = " + fabric_mod_name + "_alloc_fabric_acl,\n"
        buf += "        .tpg_release_fabric_acl         = " + fabric_mod_name + "_release_fabric_acl,\n"
        buf += "        .tpg_get_inst_index             = " + fabric_mod_name + "_tpg_get_inst_index,\n"
-       buf += "        .release_cmd_to_pool            = " + fabric_mod_name + "_release_cmd,\n"
-       buf += "        .release_cmd_direct             = " + fabric_mod_name + "_release_cmd,\n"
+       buf += "        .release_cmd                    = " + fabric_mod_name + "_release_cmd,\n"
        buf += "        .shutdown_session               = " + fabric_mod_name + "_shutdown_session,\n"
        buf += "        .close_session                  = " + fabric_mod_name + "_close_session,\n"
        buf += "        .stop_session                   = " + fabric_mod_name + "_stop_session,\n"
@@ -405,14 +399,12 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        .set_default_node_attributes    = " + fabric_mod_name + "_set_default_node_attrs,\n"
        buf += "        .get_task_tag                   = " + fabric_mod_name + "_get_task_tag,\n"
        buf += "        .get_cmd_state                  = " + fabric_mod_name + "_get_cmd_state,\n"
-       buf += "        .new_cmd_failure                = " + fabric_mod_name + "_new_cmd_failure,\n"
        buf += "        .queue_data_in                  = " + fabric_mod_name + "_queue_data_in,\n"
        buf += "        .queue_status                   = " + fabric_mod_name + "_queue_status,\n"
        buf += "        .queue_tm_rsp                   = " + fabric_mod_name + "_queue_tm_rsp,\n"
        buf += "        .get_fabric_sense_len           = " + fabric_mod_name + "_get_fabric_sense_len,\n"
        buf += "        .set_fabric_sense_len           = " + fabric_mod_name + "_set_fabric_sense_len,\n"
        buf += "        .is_state_remove                = " + fabric_mod_name + "_is_state_remove,\n"
-       buf += "        .pack_lun                       = " + fabric_mod_name + "_pack_lun,\n"
        buf += "        /*\n"
        buf += "         * Setup function pointers for generic logic in target_core_fabric_configfs.c\n"
        buf += "         */\n"
@@ -439,9 +431,9 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "         * Register the top level struct config_item_type with TCM core\n"
        buf += "         */\n"
        buf += "        fabric = target_fabric_configfs_init(THIS_MODULE, \"" + fabric_mod_name[4:] + "\");\n"
-       buf += "        if (!(fabric)) {\n"
+       buf += "        if (IS_ERR(fabric)) {\n"
        buf += "                printk(KERN_ERR \"target_fabric_configfs_init() failed\\n\");\n"
-       buf += "                return -ENOMEM;\n"
+       buf += "                return PTR_ERR(fabric);\n"
        buf += "        }\n"
        buf += "        /*\n"
        buf += "         * Setup fabric->tf_ops from our local " + fabric_mod_name + "_ops\n"
@@ -475,9 +467,9 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Set fabric -> " + fabric_mod_name + "_fabric_configfs\\n\");\n"
        buf += "        return 0;\n"
        buf += "};\n\n"
-       buf += "static void " + fabric_mod_name + "_deregister_configfs(void)\n"
+       buf += "static void __exit " + fabric_mod_name + "_deregister_configfs(void)\n"
        buf += "{\n"
-       buf += "        if (!(" + fabric_mod_name + "_fabric_configfs))\n"
+       buf += "        if (!" + fabric_mod_name + "_fabric_configfs)\n"
        buf += "                return;\n\n"
        buf += "        target_fabric_configfs_deregister(" + fabric_mod_name + "_fabric_configfs);\n"
        buf += "        " + fabric_mod_name + "_fabric_configfs = NULL;\n"
@@ -492,17 +484,15 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "                return ret;\n\n"
        buf += "        return 0;\n"
        buf += "};\n\n"
-       buf += "static void " + fabric_mod_name + "_exit(void)\n"
+       buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
        buf += "{\n"
        buf += "        " + fabric_mod_name + "_deregister_configfs();\n"
        buf += "};\n\n"
 
-       buf += "#ifdef MODULE\n"
        buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
        buf += "MODULE_LICENSE(\"GPL\");\n"
        buf += "module_init(" + fabric_mod_name + "_init);\n"
        buf += "module_exit(" + fabric_mod_name + "_exit);\n"
-       buf += "#endif\n"
 
        ret = p.write(buf)
        if ret:
@@ -514,7 +504,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 
 def tcm_mod_scan_fabric_ops(tcm_dir):
 
-       fabric_ops_api = tcm_dir + "include/target/target_core_fabric_ops.h"
+       fabric_ops_api = tcm_dir + "include/target/target_core_fabric.h"
 
        print "Using tcm_mod_scan_fabric_ops: " + fabric_ops_api
        process_fo = 0;
@@ -579,11 +569,7 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "#include <scsi/scsi_cmnd.h>\n"
        buf += "#include <scsi/libfc.h>\n\n"
        buf += "#include <target/target_core_base.h>\n"
-       buf += "#include <target/target_core_transport.h>\n"
-       buf += "#include <target/target_core_fabric_ops.h>\n"
-       buf += "#include <target/target_core_fabric_lib.h>\n"
-       buf += "#include <target/target_core_device.h>\n"
-       buf += "#include <target/target_core_tpg.h>\n"
+       buf += "#include <target/target_core_fabric.h>\n"
        buf += "#include <target/target_core_configfs.h>\n\n"
        buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
        buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
@@ -788,7 +774,7 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
                        buf += "{\n"
                        buf += "        struct " + fabric_mod_name + "_nacl *nacl;\n\n"
                        buf += "        nacl = kzalloc(sizeof(struct " + fabric_mod_name + "_nacl), GFP_KERNEL);\n"
-                       buf += "        if (!(nacl)) {\n"
+                       buf += "        if (!nacl) {\n"
                        buf += "                printk(KERN_ERR \"Unable to alocate struct " + fabric_mod_name + "_nacl\\n\");\n"
                        buf += "                return NULL;\n"
                        buf += "        }\n\n"
@@ -815,7 +801,7 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
                        buf += "}\n\n"
                        bufi += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *);\n"
 
-               if re.search('release_cmd_to_pool', fo):
+               if re.search('\*release_cmd\)\(', fo):
                        buf += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *se_cmd)\n"
                        buf += "{\n"
                        buf += "        return;\n"
@@ -899,13 +885,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
                        buf += "}\n\n"
                        bufi += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *);\n"
 
-               if re.search('new_cmd_failure\)\(', fo):
-                       buf += "void " + fabric_mod_name + "_new_cmd_failure(struct se_cmd *se_cmd)\n"
-                       buf += "{\n"
-                       buf += "        return;\n"
-                       buf += "}\n\n"
-                       bufi += "void " + fabric_mod_name + "_new_cmd_failure(struct se_cmd *);\n"
-
                if re.search('queue_data_in\)\(', fo):
                        buf += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *se_cmd)\n"
                        buf += "{\n"
@@ -948,15 +927,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
                        buf += "}\n\n"
                        bufi += "int " + fabric_mod_name + "_is_state_remove(struct se_cmd *);\n"
 
-               if re.search('pack_lun\)\(', fo):
-                       buf += "u64 " + fabric_mod_name + "_pack_lun(unsigned int lun)\n"
-                       buf += "{\n"
-                       buf += "        WARN_ON(lun >= 256);\n"
-                       buf += "        /* Caller wants this byte-swapped */\n"
-                       buf += "        return cpu_to_le64((lun & 0xff) << 8);\n"
-                       buf += "}\n\n"
-                       bufi += "u64 " + fabric_mod_name + "_pack_lun(unsigned int);\n"
-
 
        ret = p.write(buf)
        if ret:
index b61e46f449aa1e0bf376de21ddf2eec55c196a39..1733ab947a95d3849ff650e7252cfb1d0cb99d11 100644 (file)
@@ -284,7 +284,7 @@ method, the sys I/F structure will be built like this:
 The framework includes a simple notification mechanism, in the form of a
 netlink event. Netlink socket initialization is done during the _init_
 of the framework. Drivers which intend to use the notification mechanism
-just need to call generate_netlink_event() with two arguments viz
+just need to call thermal_generate_netlink_event() with two arguments viz
 (originator, event). Typically the originator will be an integer assigned
 to a thermal_zone_device when it registers itself with the framework. The
 event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
index 26aa0573933e8f5f970f7f18b3f53f0afd37eb6d..e2492a9d1027b95be62b9fde675b043643a7f01c 100644 (file)
@@ -666,27 +666,6 @@ a control of this type whenever the first control belonging to a new control
 class is added.
 
 
-Differences from the Spec
-=========================
-
-There are a few places where the framework acts slightly differently from the
-V4L2 Specification. Those differences are described in this section. We will
-have to see whether we need to adjust the spec or not.
-
-1) It is no longer required to have all controls contained in a
-v4l2_ext_control array be from the same control class. The framework will be
-able to handle any type of control in the array. You need to set ctrl_class
-to 0 in order to enable this. If ctrl_class is non-zero, then it will still
-check that all controls belong to that control class.
-
-If you set ctrl_class to 0 and count to 0, then it will only return an error
-if there are no controls at all.
-
-2) Clarified the way error_idx works. For get and set it will be equal to
-count if nothing was done yet. If it is less than count then only the controls
-up to error_idx-1 were successfully applied.
-
-
 Proposals for Extensions
 ========================
 
index 8e601991d91c6b4e0247cd9b7a5735f3df7661b3..924bd462675e90ab222cc45d8824f734be72612c 100644 (file)
@@ -4,8 +4,6 @@ Virtualization support in the Linux kernel.
        - this file.
 kvm/
        - Kernel Virtual Machine.  See also http://linux-kvm.org
-lguest/
-       - Extremely simple hypervisor for experimental/educational use.
 uml/
        - User Mode Linux, builds/runs Linux kernel as a userspace program.
 virtio.txt
index 2a90101309d1b396a9f8417a52dd55256b333731..924fb0bb52e04878e7e7b5638c1cf9b69bc34cb5 100644 (file)
@@ -159,7 +159,7 @@ S:  Maintained
 F:     drivers/net/ethernet/realtek/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-serial@vger.kernel.org
 W:     http://serial.sourceforge.net
 S:     Maintained
@@ -745,6 +745,7 @@ M:  Barry Song <baohua.song@csr.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-prima2/
+F:     drivers/dma/sirf-dma*
 
 ARM/EBSA110 MACHINE SUPPORT
 M:     Russell King <linux@arm.linux.org.uk>
@@ -788,12 +789,6 @@ F: arch/arm/mach-mx*/
 F:     arch/arm/mach-imx/
 F:     arch/arm/plat-mxc/
 
-ARM/FREESCALE IMX51
-M:     Amit Kucheria <amit.kucheria@canonical.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm/mach-mx5/
-
 ARM/FREESCALE IMX6
 M:     Shawn Guo <shawn.guo@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1411,6 +1406,7 @@ F:        net/ax25/
 B43 WIRELESS DRIVER
 M:     Stefano Brivio <stefano.brivio@polimi.it>
 L:     linux-wireless@vger.kernel.org
+L:     b43-dev@lists.infradead.org (moderated for non-subscribers)
 W:     http://linuxwireless.org/en/users/Drivers/b43
 S:     Maintained
 F:     drivers/net/wireless/b43/
@@ -1587,6 +1583,13 @@ L:       linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/bnx2fc/
 
+BROADCOM SPECIFIC AMBA DRIVER (BCMA)
+M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
+L:     linux-wireless@vger.kernel.org
+S:     Maintained
+F:     drivers/bcma/
+F:     include/linux/bcma/
+
 BROCADE BFA FC SCSI DRIVER
 M:     Jing Huang <huangj@brocade.com>
 L:     linux-scsi@vger.kernel.org
@@ -1774,9 +1777,9 @@ X:        net/wireless/wext*
 
 CHAR and MISC DRIVERS
 M:     Arnd Bergmann <arnd@arndb.de>
-M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-S:     Maintained
+S:     Supported
 F:     drivers/char/*
 F:     drivers/misc/*
 
@@ -2237,6 +2240,17 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm.git
 S:     Supported
 F:     fs/dlm/
 
+DMA BUFFER SHARING FRAMEWORK
+M:     Sumit Semwal <sumit.semwal@linaro.org>
+S:     Maintained
+L:     linux-media@vger.kernel.org
+L:     dri-devel@lists.freedesktop.org
+L:     linaro-mm-sig@lists.linaro.org
+F:     drivers/base/dma-buf*
+F:     include/linux/dma-buf*
+F:     Documentation/dma-buf-sharing.txt
+T:     git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
+
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
 M:     Vinod Koul <vinod.koul@intel.com>
 M:     Dan Williams <dan.j.williams@intel.com>
@@ -2267,7 +2281,7 @@ F:        drivers/acpi/dock.c
 DOCUMENTATION
 M:     Randy Dunlap <rdunlap@xenotime.net>
 L:     linux-doc@vger.kernel.org
-T:     quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/
+T:     quilt http://xenotime.net/kernel-doc-patches/current/
 S:     Maintained
 F:     Documentation/
 
@@ -2300,7 +2314,7 @@ F:        lib/lru_cache.c
 F:     Documentation/blockdev/drbd/
 
 DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
 S:     Supported
 F:     Documentation/kobject.txt
@@ -2330,6 +2344,9 @@ F:        include/drm/i915*
 
 DRM DRIVERS FOR EXYNOS
 M:     Inki Dae <inki.dae@samsung.com>
+M:     Joonyoung Shim <jy0922.shim@samsung.com>
+M:     Seung-Woo Kim <sw0312.kim@samsung.com>
+M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
 F:     drivers/gpu/drm/exynos
@@ -2382,7 +2399,7 @@ F:        net/bridge/netfilter/ebt*.c
 
 ECRYPT FILE SYSTEM
 M:     Tyler Hicks <tyhicks@canonical.com>
-M:     Dustin Kirkland <kirkland@canonical.com>
+M:     Dustin Kirkland <dustin.kirkland@gazzang.com>
 L:     ecryptfs@vger.kernel.org
 W:     https://launchpad.net/ecryptfs
 S:     Supported
@@ -3301,6 +3318,12 @@ S:       Maintained
 F:     net/ieee802154/
 F:     drivers/ieee802154/
 
+IIO SUBSYSTEM AND DRIVERS
+M:     Jonathan Cameron <jic23@cam.ac.uk>
+L:     linux-iio@vger.kernel.org
+S:     Maintained
+F:     drivers/staging/iio/
+
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M:     Matthieu Castet <castet.matthieu@free.fr>
 M:     Stanislaw Gruszka <stf_xl@wp.pl>
@@ -3969,11 +3992,11 @@ M:      Rusty Russell <rusty@rustcorp.com.au>
 L:     lguest@lists.ozlabs.org
 W:     http://lguest.ozlabs.org/
 S:     Odd Fixes
-F:     Documentation/virtual/lguest/
+F:     arch/x86/include/asm/lguest*.h
 F:     arch/x86/lguest/
 F:     drivers/lguest/
 F:     include/linux/lguest*.h
-F:     arch/x86/include/asm/lguest*.h
+F:     tools/lguest/
 
 LINUX FOR IBM pSERIES (RS/6000)
 M:     Paul Mackerras <paulus@au.ibm.com>
@@ -4113,10 +4136,11 @@ L:      linux-ntfs-dev@lists.sourceforge.net
 W:     http://www.linux-ntfs.org/content/view/19/37/
 S:     Maintained
 F:     Documentation/ldm.txt
-F:     fs/partitions/ldm.*
+F:     block/partitions/ldm.*
 
 LogFS
 M:     Joern Engel <joern@logfs.org>
+M:     Prasad Joshi <prasadjoshi.linux@gmail.com>
 L:     logfs@logfs.org
 W:     logfs.org
 S:     Maintained
@@ -4258,13 +4282,6 @@ S:       Orphan
 F:     drivers/video/matrox/matroxfb_*
 F:     include/linux/matroxfb.h
 
-MAX1668 TEMPERATURE SENSOR DRIVER
-M:     "David George" <david.george@ska.ac.za>
-L:     lm-sensors@lm-sensors.org
-S:     Maintained
-F:     Documentation/hwmon/max1668
-F:     drivers/hwmon/max1668.c
-
 MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
 M:     "Hans J. Koch" <hjk@hansjkoch.de>
 L:     lm-sensors@lm-sensors.org
@@ -5616,7 +5633,7 @@ W:        http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 F:     arch/s390/
 F:     drivers/s390/
-F:     fs/partitions/ibm.c
+F:     block/partitions/ibm.c
 F:     Documentation/s390/
 F:     Documentation/DocBook/s390*
 
@@ -5844,9 +5861,9 @@ S:        Maintained
 F:     drivers/mmc/host/sdhci-spear.c
 
 SECURITY SUBSYSTEM
-M:     James Morris <jmorris@namei.org>
+M:     James Morris <james.l.morris@oracle.com>
 L:     linux-security-module@vger.kernel.org (suggested Cc:)
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
 W:     http://security.wiki.kernel.org/
 S:     Supported
 F:     security/
@@ -5857,7 +5874,7 @@ S:        Supported
 
 SELINUX SECURITY MODULE
 M:     Stephen Smalley <sds@tycho.nsa.gov>
-M:     James Morris <jmorris@namei.org>
+M:     James Morris <james.l.morris@oracle.com>
 M:     Eric Paris <eparis@parisplace.org>
 L:     selinux@tycho.nsa.gov (subscribers-only, general discussion)
 W:     http://selinuxproject.org
@@ -6116,13 +6133,6 @@ S:       Maintained
 F:     drivers/ssb/
 F:     include/linux/ssb/
 
-BROADCOM SPECIFIC AMBA DRIVER (BCMA)
-M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-L:     linux-wireless@vger.kernel.org
-S:     Maintained
-F:     drivers/bcma/
-F:     include/linux/bcma/
-
 SONY VAIO CONTROL DEVICE DRIVER
 M:     Mattia Dongili <malattia@linux.it>
 L:     platform-driver-x86@vger.kernel.org
@@ -6266,15 +6276,15 @@ S:      Maintained
 F:     arch/alpha/kernel/srm_env.c
 
 STABLE BRANCH
-M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     stable@vger.kernel.org
-S:     Maintained
+S:     Supported
 
 STAGING SUBSYSTEM
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
 L:     devel@driverdev.osuosl.org
-S:     Maintained
+S:     Supported
 F:     drivers/staging/
 
 STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
@@ -6386,11 +6396,6 @@ M:       Omar Ramirez Luna <omar.ramirez@ti.com>
 S:     Odd Fixes
 F:     drivers/staging/tidspbridge/
 
-STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS
-L:     linux-media@vger.kernel.org
-S:     Odd Fixes
-F:     drivers/staging/tm6000/
-
 STAGING - USB ENE SM/MS CARD READER DRIVER
 M:     Al Cho <acho@novell.com>
 S:     Odd Fixes
@@ -6659,10 +6664,10 @@ S:      Maintained
 K:     ^Subject:.*(?i)trivial
 
 TTY LAYER
-M:     Greg Kroah-Hartman <gregkh@suse.de>
-S:     Maintained
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
-F:     drivers/tty/*
+F:     drivers/tty/
 F:     drivers/tty/serial/serial_core.c
 F:     include/linux/serial_core.h
 F:     include/linux/serial.h
@@ -6948,7 +6953,7 @@ S:        Maintained
 F:     drivers/usb/serial/digi_acceleport.c
 
 USB SERIAL DRIVER
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     Documentation/usb/usb-serial.txt
@@ -6963,9 +6968,8 @@ S:        Maintained
 F:     drivers/usb/serial/empeg.c
 
 USB SERIAL KEYSPAN DRIVER
-M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
-W:     http://www.kroah.com/linux/
 S:     Maintained
 F:     drivers/usb/serial/*keyspan*
 
@@ -6993,7 +6997,7 @@ F:        Documentation/video4linux/sn9c102.txt
 F:     drivers/media/video/sn9c102/
 
 USB SUBSYSTEM
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
@@ -7080,7 +7084,7 @@ F:        fs/hppfs/
 
 USERSPACE I/O (UIO)
 M:     "Hans J. Koch" <hjk@hansjkoch.de>
-M:     Greg Kroah-Hartman <gregkh@suse.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 S:     Maintained
 F:     Documentation/DocBook/uio-howto.tmpl
 F:     drivers/uio/
@@ -7198,7 +7202,7 @@ S:        Maintained
 F:     drivers/net/vmxnet3/
 
 VMware PVSCSI driver
-M:     Alok Kataria <akataria@vmware.com>
+M:     Arvind Kumar <arvindkumar@vmware.com>
 M:     VMware PV-Drivers <pv-drivers@vmware.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
@@ -7355,6 +7359,7 @@ S:        Supported
 F:     Documentation/hwmon/wm83??
 F:     arch/arm/mach-s3c64xx/mach-crag6410*
 F:     drivers/leds/leds-wm83*.c
+F:     drivers/hwmon/wm83??-hwmon.c
 F:     drivers/input/misc/wm831x-on.c
 F:     drivers/input/touchscreen/wm831x-ts.c
 F:     drivers/input/touchscreen/wm97*.c
index 156ac69c961e8d0ec0b99649aae2d72a0e85c313..4ddd641ab615d9d8f591a765007b312204028bad 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
-PATCHLEVEL = 2
+PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc4
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index 24626b0419ee97e963e68329a8eb6769360b46ea..a48aecc17eacc2e3d3f5cf4b0ff4183f29b33440 100644 (file)
@@ -754,7 +754,7 @@ config ARCH_SA1100
        select ARCH_HAS_CPUFREQ
        select CPU_FREQ
        select GENERIC_CLOCKEVENTS
-       select CLKDEV_LOOKUP
+       select HAVE_CLK
        select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select ARCH_REQUIRE_GPIOLIB
@@ -825,7 +825,6 @@ config ARCH_S5PC100
        select HAVE_CLK
        select CLKDEV_LOOKUP
        select CPU_V7
-       select ARM_L1_CACHE_SHIFT_6
        select ARCH_USES_GETTIMEOFFSET
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C_RTC if RTC_CLASS
@@ -842,7 +841,6 @@ config ARCH_S5PV210
        select HAVE_CLK
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
-       select ARM_L1_CACHE_SHIFT_6
        select ARCH_HAS_CPUFREQ
        select GENERIC_CLOCKEVENTS
        select HAVE_SCHED_CLOCK
index 40319d91bb7fb7fd9381c8f60cc2423230d83c0b..1683bfb9166fa0d8d1124a2d23f5d5d347cdc4a0 100644 (file)
@@ -160,7 +160,6 @@ machine-$(CONFIG_ARCH_MSM)          := msm
 machine-$(CONFIG_ARCH_MV78XX0)         := mv78xx0
 machine-$(CONFIG_ARCH_IMX_V4_V5)       := imx
 machine-$(CONFIG_ARCH_IMX_V6_V7)       := imx
-machine-$(CONFIG_ARCH_MX5)             := mx5
 machine-$(CONFIG_ARCH_MXS)             := mxs
 machine-$(CONFIG_ARCH_NETX)            := netx
 machine-$(CONFIG_ARCH_NOMADIK)         := nomadik
index 63d7578856c13d987d234e648f1065ced58a5174..a1dd2ee83753d0740c4d774dd03b556b2614f309 100644 (file)
@@ -29,6 +29,7 @@
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                interrupt-controller;
+               cpu-offset = <0x8000>;
                reg = <0x10490000 0x1000>, <0x10480000 0x100>;
        };
 
index 1a1d7023b69b427bda55a11b0dff61e8849e001b..825d2957da0b819a8ac9204df02dff60fee9dbbc 100644 (file)
        };
 
        serial@70006200 {
-               status = "disable";
+               clock-frequency = <216000000>;
        };
 
        serial@70006300 {
-               clock-frequency = <216000000>;
+               status = "disable";
        };
 
        serial@70006400 {
@@ -60,7 +60,7 @@
        sdhci@c8000000 {
                cd-gpios = <&gpio 173 0>; /* gpio PV5 */
                wp-gpios = <&gpio 57 0>;  /* gpio PH1 */
-               power-gpios = <&gpio 155 0>; /* gpio PT3 */
+               power-gpios = <&gpio 169 0>; /* gpio PV1 */
        };
 
        sdhci@c8000200 {
index b2dc2dd7f1df6d25fbba306e0822563883b18859..c47d6199b784c1f7aa3c4838dc9aea2d5cf576a0 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <asm/irq.h>
 #include <asm/exception.h>
+#include <asm/smp_plat.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
@@ -352,11 +353,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
        unsigned int gic_irqs = gic->gic_irqs;
        struct irq_domain *domain = &gic->domain;
        void __iomem *base = gic_data_dist_base(gic);
-       u32 cpu = 0;
-
-#ifdef CONFIG_SMP
-       cpu = cpu_logical_map(smp_processor_id());
-#endif
+       u32 cpu = cpu_logical_map(smp_processor_id());
 
        cpumask = 1 << cpu;
        cpumask |= cpumask << 8;
index d1bcd7b13ebc963c195fc88064fed9191984b4fe..fb1f1cfce60c098f94966663e0b6d06dc88496cd 100644 (file)
@@ -320,13 +320,6 @@ err0:
        return -EBUSY;
 }
 
-/*
- * If we set up a device for bus mastering, we need to check the latency
- * timer as we don't have even crappy BIOSes to set it properly.
- * The implementation is from arch/i386/pci/i386.c
- */
-unsigned int pcibios_max_latency = 255;
-
 /* ITE bridge requires setting latency timer to avoid early bus access
    termination by PCI bus master devices
 */
index d8e44a43047ce5cce3a2db34b9368eafe157f579..ff3ad22448247bcc18bbc9c185563a0adf88ff18 100644 (file)
@@ -1502,12 +1502,13 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
        struct pl330_thread *thrd = ch_id;
        struct pl330_dmac *pl330;
        unsigned long flags;
-       int ret = 0, active = thrd->req_running;
+       int ret = 0, active;
 
        if (!thrd || thrd->free || thrd->dmac->state == DYING)
                return -EINVAL;
 
        pl330 = thrd->dmac;
+       active = thrd->req_running;
 
        spin_lock_irqsave(&pl330->lock, flags);
 
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
new file mode 100644 (file)
index 0000000..3a4fb2e
--- /dev/null
@@ -0,0 +1,193 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
+CONFIG_MACH_PCM037=y
+CONFIG_MACH_PCM037_EET=y
+CONFIG_MACH_MX31_3DS=y
+CONFIG_MACH_MX31MOBOARD=y
+CONFIG_MACH_QONG=y
+CONFIG_MACH_ARMADILLO5X0=y
+CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX35=y
+CONFIG_MACH_VPR200=y
+CONFIG_MACH_IMX51_DT=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_IMX53_DT=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_FEC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
deleted file mode 100644 (file)
index cb0717f..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_MACH_MX31ADS_WM1133_EV1=y
-CONFIG_MACH_MX31LILLY=y
-CONFIG_MACH_MX31LITE=y
-CONFIG_MACH_PCM037=y
-CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31_3DS=y
-CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_QONG=y
-CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_KZM_ARM11_01=y
-CONFIG_MACH_PCM043=y
-CONFIG_MACH_MX35_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX35=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
-CONFIG_ARM_ERRATA_411920=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_VFP=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=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_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_MTD_UBI=y
-# CONFIG_BLK_DEV is not set
-CONFIG_MISC_DEVICES=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMSC911X=y
-CONFIG_DNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_IMX=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_IMX2_WDT=y
-CONFIG_MFD_WM8350_I2C=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_WM8350=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_SOC_CAMERA=y
-CONFIG_SOC_CAMERA_MT9M001=y
-CONFIG_SOC_CAMERA_MT9M111=y
-CONFIG_SOC_CAMERA_MT9T031=y
-CONFIG_SOC_CAMERA_MT9V022=y
-CONFIG_SOC_CAMERA_TW9910=y
-CONFIG_SOC_CAMERA_OV772X=y
-CONFIG_VIDEO_MX3=y
-# CONFIG_RADIO_ADAPTERS is not set
-CONFIG_FB=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_IMX_SOC=y
-CONFIG_SND_MXC_SOC_WM1133_EV1=y
-CONFIG_SND_SOC_PHYCORE_AC97=y
-CONFIG_SND_SOC_EUKREA_TLV320=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_GADGET=m
-CONFIG_USB_FSL_USB2=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_USB_ULPI=y
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_MXC=y
-CONFIG_DMADEVICES=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_UBIFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx5_defconfig b/arch/arm/configs/mx5_defconfig
deleted file mode 100644 (file)
index d0d8dfe..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_KERNEL_LZO=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX5=y
-CONFIG_MACH_MX51_BABBAGE=y
-CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
-CONFIG_MACH_EUKREA_CPUIMX51SD=y
-CONFIG_MACH_MX51_EFIKAMX=y
-CONFIG_MACH_MX51_EFIKASB=y
-CONFIG_MACH_MX53_EVK=y
-CONFIG_MACH_MX53_SMD=y
-CONFIG_MACH_MX53_LOCO=y
-CONFIG_MACH_MX53_ARD=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_VMSPLIT_2G=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM_DEBUG=y
-CONFIG_PM_TEST_SUSPEND=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=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_WIRELESS is not set
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=y
-CONFIG_PATA_IMX=y
-CONFIG_NETDEVICES=y
-CONFIG_MII=m
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_ICPLUS_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_NATIONAL_PHY=y
-CONFIG_STE10XP=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=m
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_MMA8450=y
-CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_SPI_IMX=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_MC13892=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_ESDHC_IMX=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_RTC_MXC=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_LZO=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_CCITT=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
index b6e65dedfd716db5e336451868af811e34a684dc..23371b17b23ebfa3a5a987eeb0aa0065660a37e1 100644 (file)
        disable_irq
        .endm
 
+       .macro  save_and_disable_irqs_notrace, oldcpsr
+       mrs     \oldcpsr, cpsr
+       disable_irq_notrace
+       .endm
+
 /*
  * Restore interrupt state previously stored in a register.  We don't
  * guarantee that this will preserve the flags.
  */
 #ifdef CONFIG_THUMB2_KERNEL
 
-       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
+       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
 9999:
        .if     \inc == 1
        \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
 
 #else  /* !CONFIG_THUMB2_KERNEL */
 
-       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
+       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
        .rept   \rept
 9999:
        .if     \inc == 1
index af18ceaacf5d2ec2bafe51de722387fb3249ac4e..b5dc173d336f93f88d7fa63e0b0c91def5393255 100644 (file)
@@ -83,9 +83,9 @@
  * instructions (inline assembly)
  */
 #ifdef CONFIG_CPU_USE_DOMAINS
-#define T(instr)       #instr "t"
+#define TUSER(instr)   #instr "t"
 #else
-#define T(instr)       #instr
+#define TUSER(instr)   #instr
 #endif
 
 #else /* __ASSEMBLY__ */
@@ -95,9 +95,9 @@
  * instructions
  */
 #ifdef CONFIG_CPU_USE_DOMAINS
-#define T(instr)       instr ## t
+#define TUSER(instr)   instr ## t
 #else
-#define T(instr)       instr
+#define TUSER(instr)   instr
 #endif
 
 #endif /* __ASSEMBLY__ */
index 253cc86318bf84907e8f003bac9dc09ae72fab6b..7be54690aeec0f38be6bb2738a8a7df8a243021d 100644 (file)
@@ -75,9 +75,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 
 #define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)        \
        __asm__ __volatile__(                                   \
-       "1:     " T(ldr) "      %1, [%3]\n"                     \
+       "1:     " TUSER(ldr) "  %1, [%3]\n"                     \
        "       " insn "\n"                                     \
-       "2:     " T(str) "      %0, [%3]\n"                     \
+       "2:     " TUSER(str) "  %0, [%3]\n"                     \
        "       mov     %0, #0\n"                               \
        __futex_atomic_ex_table("%5")                           \
        : "=&r" (ret), "=&r" (oldval), "=&r" (tmp)              \
@@ -95,10 +95,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                return -EFAULT;
 
        __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-       "1:     " T(ldr) "      %1, [%4]\n"
+       "1:     " TUSER(ldr) "  %1, [%4]\n"
        "       teq     %1, %2\n"
        "       it      eq      @ explicit IT needed for the 2b label\n"
-       "2:     " T(streq) "    %3, [%4]\n"
+       "2:     " TUSER(streq) "        %3, [%4]\n"
        __futex_atomic_ex_table("%5")
        : "+r" (ret), "=&r" (val)
        : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
index 575fa8186ca0fcb47ce864ff564f13a69bed3660..c1821385abfacbcc1532a25ee1bd2b0307173c09 100644 (file)
@@ -41,7 +41,7 @@ enum pl330_dstcachectrl {
        DCCTRL1, /* Bufferable only */
        DCCTRL2, /* Cacheable, but do not allocate */
        DCCTRL3, /* Cacheable and bufferable, but do not allocate */
-       DINVALID1 = 8,
+       DINVALID1,              /* AWCACHE = 0x1000 */
        DINVALID2,
        DCCTRL6, /* Cacheable write-through, allocate on writes only */
        DCCTRL7, /* Cacheable write-back, allocate on writes only */
index feec86768f9c967c946a74ff23ed898d6207543c..f82ec22eeb1174a3ba0b431da119868cd8a1d36d 100644 (file)
@@ -24,7 +24,6 @@
 #define MAX_INSN_SIZE                  2
 #define MAX_STACK_SIZE                 64      /* 32 would probably be OK */
 
-#define regs_return_value(regs)                ((regs)->ARM_r0)
 #define flush_insn_slot(p)             do { } while (0)
 #define kretprobe_blacklist_size       0
 
index ce280b8d613cbc7821a2adedfa32186988caf1e0..cb8d638924fd3d6f0abfa1a6dc589a755b3bc79b 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
+#include <asm/system.h>
 
 #ifdef __KERNEL__
 #define STACK_TOP      ((current->personality & ADDR_LIMIT_32BIT) ? \
index 96187ff58c247cf61953ff8d06922412f0acaca2..451808ba1211f2a547af60b35545b220d69886a9 100644 (file)
@@ -189,6 +189,11 @@ static inline int valid_user_regs(struct pt_regs *regs)
        return 0;
 }
 
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       return regs->ARM_r0;
+}
+
 #define instruction_pointer(regs)      (regs)->ARM_pc
 
 #ifdef CONFIG_SMP
index 1e5717afc4ac007e94447cf91ab88bdee9f7f1ad..ae29293270a3d8c298f5359c17ff64443882729d 100644 (file)
@@ -70,12 +70,6 @@ extern void platform_secondary_init(unsigned int cpu);
  */
 extern void platform_smp_prepare_cpus(unsigned int);
 
-/*
- * Logical CPU mapping.
- */
-extern int __cpu_logical_map[NR_CPUS];
-#define cpu_logical_map(cpu)   __cpu_logical_map[cpu]
-
 /*
  * Initial data for bringing up a secondary CPU.
  */
index f24c1b9e211dd180a6caf548260110a33f75b33c..558d6c80aca9cc292c5d3d50e99ee705535fe868 100644 (file)
@@ -43,4 +43,10 @@ static inline int cache_ops_need_broadcast(void)
 }
 #endif
 
+/*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[];
+#define cpu_logical_map(cpu)   __cpu_logical_map[cpu]
+
 #endif
index 0f30c3a78fc10815668b56c2ae5789ea38b4fdd9..d4c24d412a8ddbdaba9f11a6217cd6a8b592c22c 100644 (file)
@@ -129,6 +129,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
 /*
  * thread information flags:
  *  TIF_SYSCALL_TRACE  - syscall trace active
+ *  TIF_SYSCAL_AUDIT   - syscall auditing active
  *  TIF_SIGPENDING     - signal pending
  *  TIF_NEED_RESCHED   - rescheduling necessary
  *  TIF_NOTIFY_RESUME  - callback before returning to user
@@ -139,6 +140,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
 #define TIF_NEED_RESCHED       1
 #define TIF_NOTIFY_RESUME      2       /* callback before returning to user */
 #define TIF_SYSCALL_TRACE      8
+#define TIF_SYSCALL_AUDIT      9
 #define TIF_POLLING_NRFLAG     16
 #define TIF_USING_IWMMXT       17
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
@@ -149,11 +151,15 @@ extern void vfp_flush_hwstate(struct thread_info *);
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
+#define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_USING_IWMMXT      (1 << TIF_USING_IWMMXT)
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 
+/* Checks for any syscall work in entry-common.S */
+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
+
 /*
  * Change these and you break ASM code in entry-common.S
  */
index 5d3ed7e38561dd43553d1d3bf1b2af07e0d2b747..314d4664eae7d9976a5fe656f74918cb8d15ab8b 100644 (file)
@@ -198,7 +198,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
        unsigned long addr)
 {
        pgtable_page_dtor(pte);
-       tlb_add_flush(tlb, addr);
+
+       /*
+        * With the classic ARM MMU, a pte page has two corresponding pmd
+        * entries, each covering 1MB.
+        */
+       addr &= PMD_MASK;
+       tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE);
+       tlb_add_flush(tlb, addr + SZ_1M);
+
        tlb_remove_page(tlb, pte);
 }
 
index b293616a1a1a8d6cf92a5ae1560994c7e3d66e46..2958976d867b4b9795a090cee9a6b9cacb646631 100644 (file)
@@ -227,7 +227,7 @@ do {                                                                        \
 
 #define __get_user_asm_byte(x,addr,err)                                \
        __asm__ __volatile__(                                   \
-       "1:     " T(ldrb) "     %1,[%2],#0\n"                   \
+       "1:     " TUSER(ldrb) " %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -263,7 +263,7 @@ do {                                                                        \
 
 #define __get_user_asm_word(x,addr,err)                                \
        __asm__ __volatile__(                                   \
-       "1:     " T(ldr) "      %1,[%2],#0\n"                   \
+       "1:     " TUSER(ldr) "  %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -308,7 +308,7 @@ do {                                                                        \
 
 #define __put_user_asm_byte(x,__pu_addr,err)                   \
        __asm__ __volatile__(                                   \
-       "1:     " T(strb) "     %1,[%2],#0\n"                   \
+       "1:     " TUSER(strb) " %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -341,7 +341,7 @@ do {                                                                        \
 
 #define __put_user_asm_word(x,__pu_addr,err)                   \
        __asm__ __volatile__(                                   \
-       "1:     " T(str) "      %1,[%2],#0\n"                   \
+       "1:     " TUSER(str) "  %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -366,10 +366,10 @@ do {                                                                      \
 
 #define __put_user_asm_dword(x,__pu_addr,err)                  \
        __asm__ __volatile__(                                   \
- ARM(  "1:     " T(str) "      " __reg_oper1 ", [%1], #4\n"    )       \
- ARM(  "2:     " T(str) "      " __reg_oper0 ", [%1]\n"        )       \
- THUMB(        "1:     " T(str) "      " __reg_oper1 ", [%1]\n"        )       \
- THUMB(        "2:     " T(str) "      " __reg_oper0 ", [%1, #4]\n"    )       \
+ ARM(  "1:     " TUSER(str) "  " __reg_oper1 ", [%1], #4\n"    ) \
+ ARM(  "2:     " TUSER(str) "  " __reg_oper0 ", [%1]\n"        ) \
+ THUMB(        "1:     " TUSER(str) "  " __reg_oper1 ", [%1]\n"        ) \
+ THUMB(        "2:     " TUSER(str) "  " __reg_oper0 ", [%1, #4]\n"    ) \
        "3:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
index bc631161e9c6d29eb0f9e73d408da4ae4c13da0e..f5989f46b4d2d450f18b24faa946de750394ec13 100644 (file)
@@ -37,8 +37,8 @@
 #define THUMB(x...)    x
 #ifdef __ASSEMBLY__
 #define W(instr)       instr.w
-#endif
 #define BSYM(sym)      sym + 1
+#endif
 
 #else  /* !CONFIG_THUMB2_KERNEL */
 
@@ -49,8 +49,8 @@
 #define THUMB(x...)
 #ifdef __ASSEMBLY__
 #define W(instr)       instr
-#endif
 #define BSYM(sym)      sym
+#endif
 
 #endif /* CONFIG_THUMB2_KERNEL */
 
index 3a456c6c70056f9267f592792193d2176c045802..be16a48007b4b79fc5db0d3e48b016242b68d760 100644 (file)
@@ -790,7 +790,7 @@ __kuser_cmpxchg64:                          @ 0xffff0f60
        smp_dmb arm
        rsbs    r0, r3, #0                      @ set returned val and C flag
        ldmfd   sp!, {r4, r5, r6, r7}
-       bx      lr
+       usr_ret lr
 
 #elif !defined(CONFIG_SMP)
 
index b2a27b6b0046ee6c1e0f0928c3269ab5f6c63cd2..9fd0ba90c1d29ff78ed04ca80580e1c8be89cd0a 100644 (file)
@@ -87,7 +87,7 @@ ENTRY(ret_from_fork)
        get_thread_info tsk
        ldr     r1, [tsk, #TI_FLAGS]            @ check for syscall tracing
        mov     why, #1
-       tst     r1, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
+       tst     r1, #_TIF_SYSCALL_WORK          @ are we tracing syscalls?
        beq     ret_slow_syscall
        mov     r1, sp
        mov     r0, #1                          @ trace exit [IP = 1]
@@ -149,6 +149,11 @@ ENDPROC(ret_from_fork)
 #endif
 #endif
 
+.macro mcount_adjust_addr rd, rn
+       bic     \rd, \rn, #1            @ clear the Thumb bit if present
+       sub     \rd, \rd, #MCOUNT_INSN_SIZE
+.endm
+
 .macro __mcount suffix
        mcount_enter
        ldr     r0, =ftrace_trace_function
@@ -173,8 +178,7 @@ ENDPROC(ret_from_fork)
        mcount_exit
 
 1:     mcount_get_lr   r1                      @ lr of instrumented func
-       mov     r0, lr                          @ instrumented function
-       sub     r0, r0, #MCOUNT_INSN_SIZE
+       mcount_adjust_addr      r0, lr          @ instrumented function
        adr     lr, BSYM(2f)
        mov     pc, r2
 2:     mcount_exit
@@ -184,8 +188,7 @@ ENDPROC(ret_from_fork)
        mcount_enter
 
        mcount_get_lr   r1                      @ lr of instrumented func
-       mov     r0, lr                          @ instrumented function
-       sub     r0, r0, #MCOUNT_INSN_SIZE
+       mcount_adjust_addr      r0, lr          @ instrumented function
 
        .globl ftrace_call\suffix
 ftrace_call\suffix:
@@ -205,11 +208,11 @@ ftrace_graph_call\suffix:
 #ifdef CONFIG_DYNAMIC_FTRACE
        @ called from __ftrace_caller, saved in mcount_enter
        ldr     r1, [sp, #16]           @ instrumented routine (func)
+       mcount_adjust_addr      r1, r1
 #else
        @ called from __mcount, untouched in lr
-       mov     r1, lr                  @ instrumented routine (func)
+       mcount_adjust_addr      r1, lr  @ instrumented routine (func)
 #endif
-       sub     r1, r1, #MCOUNT_INSN_SIZE
        mov     r2, fp                  @ frame pointer
        bl      prepare_ftrace_return
        mcount_exit
@@ -443,7 +446,7 @@ ENTRY(vector_swi)
 1:
 #endif
 
-       tst     r10, #_TIF_SYSCALL_TRACE                @ are we tracing syscalls?
+       tst     r10, #_TIF_SYSCALL_WORK         @ are we tracing syscalls?
        bne     __sys_trace
 
        cmp     scno, #NR_syscalls              @ check upper syscall limit
index 460bbbb6b88536ba18ded4983b6ee18baf1a4bf4..6933244c68f964ffed73f11cfbdaac1ca13b2f74 100644 (file)
@@ -469,6 +469,20 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
        },
+       [C(NODE)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
 };
 
 /*
@@ -579,6 +593,20 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
        },
+       [C(NODE)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
 };
 
 /*
index 483727ad68923a3e27af6d693c9132db0148af7f..ede6443c34d964670560f155aaf200ed6bf0949e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/regset.h>
+#include <linux/audit.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -699,10 +700,13 @@ static int vfp_set(struct task_struct *target,
 {
        int ret;
        struct thread_info *thread = task_thread_info(target);
-       struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
+       struct vfp_hard_struct new_vfp;
        const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
        const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
 
+       vfp_sync_hwstate(thread);
+       new_vfp = thread->vfpstate.hard;
+
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                  &new_vfp.fpregs,
                                  user_fpregs_offset,
@@ -723,9 +727,8 @@ static int vfp_set(struct task_struct *target,
        if (ret)
                return ret;
 
-       vfp_sync_hwstate(thread);
-       thread->vfpstate.hard = new_vfp;
        vfp_flush_hwstate(thread);
+       thread->vfpstate.hard = new_vfp;
 
        return 0;
 }
@@ -902,15 +905,16 @@ long arch_ptrace(struct task_struct *child, long request,
        return ret;
 }
 
+#ifdef __ARMEB__
+#define AUDIT_ARCH_NR AUDIT_ARCH_ARMEB
+#else
+#define AUDIT_ARCH_NR AUDIT_ARCH_ARM
+#endif
+
 asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 {
        unsigned long ip;
 
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return scno;
-       if (!(current->ptrace & PT_PTRACED))
-               return scno;
-
        /*
         * Save IP.  IP is used to denote syscall entry/exit:
         *  IP = 0 -> entry, = 1 -> exit
@@ -918,6 +922,17 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
        ip = regs->ARM_ip;
        regs->ARM_ip = why;
 
+       if (!ip)
+               audit_syscall_exit(regs);
+       else
+               audit_syscall_entry(AUDIT_ARCH_NR, scno, regs->ARM_r0,
+                                   regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+
+       if (!test_thread_flag(TIF_SYSCALL_TRACE))
+               return scno;
+       if (!(current->ptrace & PT_PTRACED))
+               return scno;
+
        current_thread_info()->syscall = scno;
 
        /* the 0x80 provides a way for the tracing parent to distinguish
index 129fbd55bde85612de3900035f05fd8bd85cfeee..a255c39612ca3cfa10bddb7c7728216efeeb04d5 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/kexec.h>
 #include <linux/of_fdt.h>
-#include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
@@ -160,7 +159,7 @@ static struct resource mem_res[] = {
                .flags = IORESOURCE_MEM
        },
        {
-               .name = "Kernel text",
+               .name = "Kernel code",
                .start = 0,
                .end = 0,
                .flags = IORESOURCE_MEM
@@ -427,6 +426,20 @@ void cpu_init(void)
            : "r14");
 }
 
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+       int i;
+       u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+       cpu_logical_map(0) = cpu;
+       for (i = 1; i < NR_CPUS; ++i)
+               cpu_logical_map(i) = i == cpu ? 0 : i;
+
+       printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
 static void __init setup_processor(void)
 {
        struct proc_info_list *list;
index 0340224cf73c5c9db2d16185bd698a6ba6518fb8..9e617bd4a146250d7d3f453d50a45431fa261e08 100644 (file)
@@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
        if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
                return -EINVAL;
 
+       vfp_flush_hwstate(thread);
+
        /*
         * Copy the floating point registers. There can be unused
         * registers see asm/hwcap.h for details.
@@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
        __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
        __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
 
-       if (!err)
-               vfp_flush_hwstate(thread);
-
        return err ? -EFAULT : 0;
 }
 
index 57db122a4f629bb53247fde4f2b15076838661c0..cdeb727527d39768587ffa3dd9946073aeaa6853 100644 (file)
@@ -233,20 +233,6 @@ void __ref cpu_die(void)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-int __cpu_logical_map[NR_CPUS];
-
-void __init smp_setup_processor_id(void)
-{
-       int i;
-       u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
-
-       cpu_logical_map(0) = cpu;
-       for (i = 1; i < NR_CPUS; ++i)
-               cpu_logical_map(i) = i == cpu ? 0 : i;
-
-       printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
-}
-
 /*
  * Called by both boot and secondaries to move global data into
  * per-processor storage.
@@ -443,9 +429,7 @@ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
 static void ipi_timer(void)
 {
        struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
-       irq_enter();
        evt->event_handler(evt);
-       irq_exit();
 }
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -548,7 +532,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 
        switch (ipinr) {
        case IPI_TIMER:
+               irq_enter();
                ipi_timer();
+               irq_exit();
                break;
 
        case IPI_RESCHEDULE:
@@ -556,15 +542,21 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
                break;
 
        case IPI_CALL_FUNC:
+               irq_enter();
                generic_smp_call_function_interrupt();
+               irq_exit();
                break;
 
        case IPI_CALL_FUNC_SINGLE:
+               irq_enter();
                generic_smp_call_function_single_interrupt();
+               irq_exit();
                break;
 
        case IPI_CPU_STOP:
+               irq_enter();
                ipi_cpu_stop(cpu);
+               irq_exit();
                break;
 
        default:
index c8e938553d478015d57d436ec43908b81b460d3a..7a79b24597b2d51953826338e13656803fe9c229 100644 (file)
@@ -129,7 +129,7 @@ static struct notifier_block twd_cpufreq_nb = {
 
 static int twd_cpufreq_init(void)
 {
-       if (!IS_ERR(twd_clk))
+       if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
                return cpufreq_register_notifier(&twd_cpufreq_nb,
                        CPUFREQ_TRANSITION_NOTIFIER);
 
@@ -252,6 +252,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
        else
                twd_calibrate_rate();
 
+       __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
+
        clk->name = "local_timer";
        clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
                        CLOCK_EVT_FEAT_C3STOP;
index 99a57270250936ae69e02abd57b27b8a1c3dd022..f84dfe67724fa6e81e7975abfa08ad23a2ba3788 100644 (file)
@@ -266,6 +266,7 @@ void die(const char *str, struct pt_regs *regs, int err)
 {
        struct thread_info *thread = current_thread_info();
        int ret;
+       enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;
 
        oops_enter();
 
@@ -273,7 +274,9 @@ void die(const char *str, struct pt_regs *regs, int err)
        console_verbose();
        bust_spinlocks(1);
        if (!user_mode(regs))
-               report_bug(regs->ARM_pc, regs);
+               bug_type = report_bug(regs->ARM_pc, regs);
+       if (bug_type != BUG_TRAP_TYPE_NONE)
+               str = "Oops - BUG";
        ret = __die(str, err, thread, regs);
 
        if (regs && kexec_should_crash(thread->task))
index f76e75548670e97eeac9112a8e48b53e37f9cc91..43a31fb06318dc0a1213827a5069b73cac19f5a6 100644 (file)
@@ -4,11 +4,13 @@
  */
 
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/page.h>
        
 #define PROC_INFO                                                      \
+       . = ALIGN(4);                                                   \
        VMLINUX_SYMBOL(__proc_info_begin) = .;                          \
        *(.proc.info.init)                                              \
        VMLINUX_SYMBOL(__proc_info_end) = .;
@@ -181,7 +183,7 @@ SECTIONS
        }
 #endif
 
-       PERCPU_SECTION(32)
+       PERCPU_SECTION(L1_CACHE_BYTES)
 
 #ifdef CONFIG_XIP_KERNEL
        __data_loc = ALIGN(4);          /* location in binary */
@@ -212,13 +214,13 @@ SECTIONS
 #endif
 
                NOSAVE_DATA
-               CACHELINE_ALIGNED_DATA(32)
-               READ_MOSTLY_DATA(32)
+               CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
+               READ_MOSTLY_DATA(L1_CACHE_BYTES)
 
                /*
                 * The exception fixup table (might need resorting at runtime)
                 */
-               . = ALIGN(32);
+               . = ALIGN(4);
                __start___ex_table = .;
 #ifdef CONFIG_MMU
                *(__ex_table)
index 1b049cd7a49a8badab511ed2b0532d1f7e76b733..11093a7c3e32289e95a8c100cc01ef2bbb8d7101 100644 (file)
 #include <asm/domain.h>
 
 ENTRY(__get_user_1)
-1:     T(ldrb) r2, [r0]
+1: TUSER(ldrb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
 #ifdef CONFIG_THUMB2_KERNEL
-2:     T(ldrb) r2, [r0]
-3:     T(ldrb) r3, [r0, #1]
+2: TUSER(ldrb) r2, [r0]
+3: TUSER(ldrb) r3, [r0, #1]
 #else
-2:     T(ldrb) r2, [r0], #1
-3:     T(ldrb) r3, [r0]
+2: TUSER(ldrb) r2, [r0], #1
+3: TUSER(ldrb) r3, [r0]
 #endif
 #ifndef __ARMEB__
        orr     r2, r2, r3, lsl #8
@@ -54,7 +54,7 @@ ENTRY(__get_user_2)
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
-4:     T(ldr)  r2, [r0]
+4: TUSER(ldr)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_4)
index c023fc11e86c7b603eaaa08270e7ea429ecfab5f..7db25990c589f3d98554d9aee47cf7b5c3c486fd 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/domain.h>
 
 ENTRY(__put_user_1)
-1:     T(strb) r2, [r0]
+1: TUSER(strb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_1)
@@ -40,19 +40,19 @@ ENTRY(__put_user_2)
        mov     ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
-2:     T(strb) r2, [r0]
-3:     T(strb) ip, [r0, #1]
+2: TUSER(strb) r2, [r0]
+3: TUSER(strb) ip, [r0, #1]
 #else
-2:     T(strb) ip, [r0]
-3:     T(strb) r2, [r0, #1]
+2: TUSER(strb) ip, [r0]
+3: TUSER(strb) r2, [r0, #1]
 #endif
 #else  /* !CONFIG_THUMB2_KERNEL */
 #ifndef __ARMEB__
-2:     T(strb) r2, [r0], #1
-3:     T(strb) ip, [r0]
+2: TUSER(strb) r2, [r0], #1
+3: TUSER(strb) ip, [r0]
 #else
-2:     T(strb) ip, [r0], #1
-3:     T(strb) r2, [r0]
+2: TUSER(strb) ip, [r0], #1
+3: TUSER(strb) r2, [r0]
 #endif
 #endif /* CONFIG_THUMB2_KERNEL */
        mov     r0, #0
@@ -60,18 +60,18 @@ ENTRY(__put_user_2)
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
-4:     T(str)  r2, [r0]
+4: TUSER(str)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
 #ifdef CONFIG_THUMB2_KERNEL
-5:     T(str)  r2, [r0]
-6:     T(str)  r3, [r0, #4]
+5: TUSER(str)  r2, [r0]
+6: TUSER(str)  r3, [r0, #4]
 #else
-5:     T(str)  r2, [r0], #4
-6:     T(str)  r3, [r0]
+5: TUSER(str)  r2, [r0], #4
+6: TUSER(str)  r3, [r0]
 #endif
        mov     r0, #0
        mov     pc, lr
index d0ece2aeb70dfc380d689a85a141a28a5917ec20..5c908b1cb8ed5db3eeabfb89f7f659f99d2d6f76 100644 (file)
                rsb     ip, ip, #4
                cmp     ip, #2
                ldrb    r3, [r1], #1
-USER(          T(strb) r3, [r0], #1)                   @ May fault
+USER(  TUSER(  strb)   r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          T(strgeb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgeb) r3, [r0], #1)                   @ May fault
                ldrgtb  r3, [r1], #1
-USER(          T(strgtb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgtb) r3, [r0], #1)                   @ May fault
                sub     r2, r2, ip
                b       .Lc2u_dest_aligned
 
@@ -59,7 +59,7 @@ ENTRY(__copy_to_user)
                addmi   ip, r2, #4
                bmi     .Lc2u_0nowords
                ldr     r3, [r1], #4
-USER(          T(str)  r3, [r0], #4)                   @ May fault
+USER(  TUSER(  str)    r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -88,18 +88,18 @@ USER(               T(str)  r3, [r0], #4)                   @ May fault
                stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                ldrne   r3, [r1], #4
-               T(strne) r3, [r0], #4                   @ Shouldnt fault
+       TUSER(  strne) r3, [r0], #4                     @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_0fupi
 .Lc2u_0nowords:        teq     ip, #0
                beq     .Lc2u_finished
 .Lc2u_nowords: cmp     ip, #2
                ldrb    r3, [r1], #1
-USER(          T(strb) r3, [r0], #1)                   @ May fault
+USER(  TUSER(  strb)   r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          T(strgeb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgeb) r3, [r0], #1)                   @ May fault
                ldrgtb  r3, [r1], #1
-USER(          T(strgtb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgtb) r3, [r0], #1)                   @ May fault
                b       .Lc2u_finished
 
 .Lc2u_not_enough:
@@ -120,7 +120,7 @@ USER(               T(strgtb) r3, [r0], #1)                 @ May fault
                mov     r3, r7, pull #8
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #24
-USER(          T(str)  r3, [r0], #4)                   @ May fault
+USER(  TUSER(  str)    r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -155,18 +155,18 @@ USER(             T(str)  r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #8
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #24
-               T(strne) r3, [r0], #4                   @ Shouldnt fault
+       TUSER(  strne) r3, [r0], #4                     @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_1fupi
 .Lc2u_1nowords:        mov     r3, r7, get_byte_1
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          T(strb) r3, [r0], #1)                   @ May fault
+USER(  TUSER(  strb)   r3, [r0], #1)                   @ May fault
                movge   r3, r7, get_byte_2
-USER(          T(strgeb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgeb) r3, [r0], #1)                   @ May fault
                movgt   r3, r7, get_byte_3
-USER(          T(strgtb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgtb) r3, [r0], #1)                   @ May fault
                b       .Lc2u_finished
 
 .Lc2u_2fupi:   subs    r2, r2, #4
@@ -175,7 +175,7 @@ USER(               T(strgtb) r3, [r0], #1)                 @ May fault
                mov     r3, r7, pull #16
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #16
-USER(          T(str)  r3, [r0], #4)                   @ May fault
+USER(  TUSER(  str)    r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -210,18 +210,18 @@ USER(             T(str)  r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #16
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #16
-               T(strne) r3, [r0], #4                   @ Shouldnt fault
+       TUSER(  strne) r3, [r0], #4                     @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_2fupi
 .Lc2u_2nowords:        mov     r3, r7, get_byte_2
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          T(strb) r3, [r0], #1)                   @ May fault
+USER(  TUSER(  strb)   r3, [r0], #1)                   @ May fault
                movge   r3, r7, get_byte_3
-USER(          T(strgeb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgeb) r3, [r0], #1)                   @ May fault
                ldrgtb  r3, [r1], #0
-USER(          T(strgtb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgtb) r3, [r0], #1)                   @ May fault
                b       .Lc2u_finished
 
 .Lc2u_3fupi:   subs    r2, r2, #4
@@ -230,7 +230,7 @@ USER(               T(strgtb) r3, [r0], #1)                 @ May fault
                mov     r3, r7, pull #24
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #8
-USER(          T(str)  r3, [r0], #4)                   @ May fault
+USER(  TUSER(  str)    r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -265,18 +265,18 @@ USER(             T(str)  r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #24
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #8
-               T(strne) r3, [r0], #4                   @ Shouldnt fault
+       TUSER(  strne) r3, [r0], #4                     @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_3fupi
 .Lc2u_3nowords:        mov     r3, r7, get_byte_3
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          T(strb) r3, [r0], #1)                   @ May fault
+USER(  TUSER(  strb)   r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          T(strgeb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgeb) r3, [r0], #1)                   @ May fault
                ldrgtb  r3, [r1], #0
-USER(          T(strgtb) r3, [r0], #1)                 @ May fault
+USER(  TUSER(  strgtb) r3, [r0], #1)                   @ May fault
                b       .Lc2u_finished
 ENDPROC(__copy_to_user)
 
@@ -295,11 +295,11 @@ ENDPROC(__copy_to_user)
 .Lcfu_dest_not_aligned:
                rsb     ip, ip, #4
                cmp     ip, #2
-USER(          T(ldrb) r3, [r1], #1)                   @ May fault
+USER(  TUSER(  ldrb)   r3, [r1], #1)                   @ May fault
                strb    r3, [r0], #1
-USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
+USER(  TUSER(  ldrgeb) r3, [r1], #1)                   @ May fault
                strgeb  r3, [r0], #1
-USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
+USER(  TUSER(  ldrgtb) r3, [r1], #1)                   @ May fault
                strgtb  r3, [r0], #1
                sub     r2, r2, ip
                b       .Lcfu_dest_aligned
@@ -322,7 +322,7 @@ ENTRY(__copy_from_user)
 .Lcfu_0fupi:   subs    r2, r2, #4
                addmi   ip, r2, #4
                bmi     .Lcfu_0nowords
-USER(          T(ldr)  r3, [r1], #4)
+USER(  TUSER(  ldr)    r3, [r1], #4)
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
                rsb     ip, ip, #0
@@ -351,18 +351,18 @@ USER(             T(ldr)  r3, [r1], #4)
                ldmneia r1!, {r3 - r4}                  @ Shouldnt fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
-               T(ldrne) r3, [r1], #4                   @ Shouldnt fault
+       TUSER(  ldrne) r3, [r1], #4                     @ Shouldnt fault
                strne   r3, [r0], #4
                ands    ip, ip, #3
                beq     .Lcfu_0fupi
 .Lcfu_0nowords:        teq     ip, #0
                beq     .Lcfu_finished
 .Lcfu_nowords: cmp     ip, #2
-USER(          T(ldrb) r3, [r1], #1)                   @ May fault
+USER(  TUSER(  ldrb)   r3, [r1], #1)                   @ May fault
                strb    r3, [r0], #1
-USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
+USER(  TUSER(  ldrgeb) r3, [r1], #1)                   @ May fault
                strgeb  r3, [r0], #1
-USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
+USER(  TUSER(  ldrgtb) r3, [r1], #1)                   @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 
@@ -375,7 +375,7 @@ USER(               T(ldrgtb) r3, [r1], #1)                 @ May fault
 
 .Lcfu_src_not_aligned:
                bic     r1, r1, #3
-USER(          T(ldr)  r7, [r1], #4)                   @ May fault
+USER(  TUSER(  ldr)    r7, [r1], #4)                   @ May fault
                cmp     ip, #2
                bgt     .Lcfu_3fupi
                beq     .Lcfu_2fupi
@@ -383,7 +383,7 @@ USER(               T(ldr)  r7, [r1], #4)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_1nowords
                mov     r3, r7, pull #8
-USER(          T(ldr)  r7, [r1], #4)                   @ May fault
+USER(  TUSER(  ldr)    r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #24
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -418,7 +418,7 @@ USER(               T(ldr)  r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #8
-USER(          T(ldrne) r7, [r1], #4)                  @ May fault
+USER(  TUSER(  ldrne) r7, [r1], #4)                    @ May fault
                orrne   r3, r3, r7, push #24
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -438,7 +438,7 @@ USER(               T(ldrne) r7, [r1], #4)                  @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_2nowords
                mov     r3, r7, pull #16
-USER(          T(ldr)  r7, [r1], #4)                   @ May fault
+USER(  TUSER(  ldr)    r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #16
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -474,7 +474,7 @@ USER(               T(ldr)  r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #16
-USER(          T(ldrne) r7, [r1], #4)                  @ May fault
+USER(  TUSER(  ldrne) r7, [r1], #4)                    @ May fault
                orrne   r3, r3, r7, push #16
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -486,7 +486,7 @@ USER(               T(ldrne) r7, [r1], #4)                  @ May fault
                strb    r3, [r0], #1
                movge   r3, r7, get_byte_3
                strgeb  r3, [r0], #1
-USER(          T(ldrgtb) r3, [r1], #0)                 @ May fault
+USER(  TUSER(  ldrgtb) r3, [r1], #0)                   @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 
@@ -494,7 +494,7 @@ USER(               T(ldrgtb) r3, [r1], #0)                 @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_3nowords
                mov     r3, r7, pull #24
-USER(          T(ldr)  r7, [r1], #4)                   @ May fault
+USER(  TUSER(  ldr)    r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #8
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -529,7 +529,7 @@ USER(               T(ldr)  r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #24
-USER(          T(ldrne) r7, [r1], #4)                  @ May fault
+USER(  TUSER(  ldrne) r7, [r1], #4)                    @ May fault
                orrne   r3, r3, r7, push #8
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -539,9 +539,9 @@ USER(               T(ldrne) r7, [r1], #4)                  @ May fault
                beq     .Lcfu_finished
                cmp     ip, #2
                strb    r3, [r0], #1
-USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
+USER(  TUSER(  ldrgeb) r3, [r1], #1)                   @ May fault
                strgeb  r3, [r0], #1
-USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
+USER(  TUSER(  ldrgtb) r3, [r1], #1)                   @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 ENDPROC(__copy_from_user)
index 4f991f2952846fb89d36be0758c255a4014b575a..71feb00a1e995de0991b54189569b04c1cf02f06 100644 (file)
@@ -18,6 +18,12 @@ config HAVE_AT91_USART4
 config HAVE_AT91_USART5
        bool
 
+config AT91_SAM9_ALT_RESET
+       bool
+
+config AT91_SAM9G45_RESET
+       bool
+
 menu "Atmel AT91 System-on-Chip"
 
 choice
@@ -39,6 +45,7 @@ config ARCH_AT91SAM9260
        select HAVE_AT91_USART4
        select HAVE_AT91_USART5
        select HAVE_NET_MACB
+       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9261
        bool "AT91SAM9261"
@@ -46,6 +53,7 @@ config ARCH_AT91SAM9261
        select GENERIC_CLOCKEVENTS
        select HAVE_FB_ATMEL
        select HAVE_AT91_DBGU0
+       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9G10
        bool "AT91SAM9G10"
@@ -53,6 +61,7 @@ config ARCH_AT91SAM9G10
        select GENERIC_CLOCKEVENTS
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
+       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9263
        bool "AT91SAM9263"
@@ -61,6 +70,7 @@ config ARCH_AT91SAM9263
        select HAVE_FB_ATMEL
        select HAVE_NET_MACB
        select HAVE_AT91_DBGU1
+       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9RL
        bool "AT91SAM9RL"
@@ -69,6 +79,7 @@ config ARCH_AT91SAM9RL
        select HAVE_AT91_USART3
        select HAVE_FB_ATMEL
        select HAVE_AT91_DBGU0
+       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9G20
        bool "AT91SAM9G20"
@@ -79,6 +90,7 @@ config ARCH_AT91SAM9G20
        select HAVE_AT91_USART4
        select HAVE_AT91_USART5
        select HAVE_NET_MACB
+       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9G45
        bool "AT91SAM9G45"
@@ -88,6 +100,7 @@ config ARCH_AT91SAM9G45
        select HAVE_FB_ATMEL
        select HAVE_NET_MACB
        select HAVE_AT91_DBGU1
+       select AT91_SAM9G45_RESET
 
 config ARCH_AT91CAP9
        bool "AT91CAP9"
@@ -96,6 +109,7 @@ config ARCH_AT91CAP9
        select HAVE_FB_ATMEL
        select HAVE_NET_MACB
        select HAVE_AT91_DBGU1
+       select AT91_SAM9G45_RESET
 
 config ARCH_AT91X40
        bool "AT91x40"
index 242174f9f3554c6323075229eceef94a9f759225..705e1fbded3919112efb5858ec921d49e05d1eaa 100644 (file)
@@ -8,15 +8,17 @@ obj-n         :=
 obj-           :=
 
 obj-$(CONFIG_AT91_PMC_UNIT)    += clock.o
+obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
+obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
 
 # CPU-specific support
 obj-$(CONFIG_ARCH_AT91RM9200)  += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9RL)  += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9RL)  += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91CAP9)    += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91X40)     += at91x40.o at91x40_time.o
index edb879ac04c8e30c3d2b814f24497ae86075e7be..a42edc25a87e693aea85b2b494515c14e4d32c42 100644 (file)
@@ -21,7 +21,6 @@
 #include <mach/cpu.h>
 #include <mach/at91cap9.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
 
 #include "soc.h"
 #include "generic.h"
@@ -314,11 +313,6 @@ static struct at91_gpio_bank at91cap9_gpio[] __initdata = {
        }
 };
 
-static void at91cap9_restart(char mode, const char *cmd)
-{
-       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 /* --------------------------------------------------------------------
  *  AT91CAP9 processor initialization
  * -------------------------------------------------------------------- */
@@ -331,13 +325,14 @@ static void __init at91cap9_map_io(void)
 static void __init at91cap9_ioremap_registers(void)
 {
        at91_ioremap_shdwc(AT91CAP9_BASE_SHDWC);
+       at91_ioremap_rstc(AT91CAP9_BASE_RSTC);
        at91sam926x_ioremap_pit(AT91CAP9_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91CAP9_BASE_SMC);
 }
 
 static void __init at91cap9_initialize(void)
 {
-       arm_pm_restart = at91cap9_restart;
+       arm_pm_restart = at91sam9g45_restart;
        at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
 
        /* Register GPIO subsystem */
index 18bacec2b094c202bc9dd60be5b69be0c56a683f..97676bdae9983c98b79f77cb85dd88e833756789 100644 (file)
@@ -83,7 +83,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
index 5e46e4a96430d90e793343115cbce42001e5cecc..d4036ba43612afe85f7b74ce58f55ae35e1882d0 100644 (file)
@@ -323,6 +323,7 @@ static void __init at91sam9260_map_io(void)
 static void __init at91sam9260_ioremap_registers(void)
 {
        at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC);
+       at91_ioremap_rstc(AT91SAM9260_BASE_RSTC);
        at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
 }
index 642ccb6d26b256f284388080f71b68e5494e8070..5a24f0b4554db2b7e4ea50e620b464e2e9b9363a 100644 (file)
@@ -84,7 +84,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -1215,8 +1215,7 @@ void __init at91_add_device_serial(void) {}
  *  CF/IDE
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE) || \
-       defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
+#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
        defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
 
 static struct at91_cf_data cf0_data;
@@ -1313,10 +1312,8 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
        if (data->flags & AT91_CF_TRUE_IDE)
 #if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE)
                pdev->name = "pata_at91";
-#elif defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
-               pdev->name = "at91_ide";
 #else
-#warning "board requires AT91_CF_TRUE_IDE: enable either at91_ide or pata_at91"
+#warning "board requires AT91_CF_TRUE_IDE: enable pata_at91"
 #endif
        else
                pdev->name = "at91_cf";
index b85b9ea6017071252a670fdb6e22cb222336055d..023c2ff138df8a9228b4cb45c514d6e02f938918 100644 (file)
@@ -281,6 +281,7 @@ static void __init at91sam9261_map_io(void)
 static void __init at91sam9261_ioremap_registers(void)
 {
        at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC);
+       at91_ioremap_rstc(AT91SAM9261_BASE_RSTC);
        at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
 }
index fc59cbdb0e3cfcc777e3fe231bf8c525c2457198..1e28bed8f425063e99af8ac417035e5e6d01900f 100644 (file)
@@ -87,7 +87,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
index 79e3669b1117cbdf7ae18fd685647625766da513..75e876c258afed33b87ba50ccdb8dafee2523d79 100644 (file)
@@ -301,6 +301,7 @@ static void __init at91sam9263_map_io(void)
 static void __init at91sam9263_ioremap_registers(void)
 {
        at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC);
+       at91_ioremap_rstc(AT91SAM9263_BASE_RSTC);
        at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0);
        at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1);
index 7b46b2787022e85729e4d39ade77d667c5110e66..366a7765635b380538c103e3c0027519550521d0 100644 (file)
@@ -92,7 +92,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -355,8 +355,8 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  *  Compact Flash (PCMCIA or IDE)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \
-    defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
+#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
+       defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
 
 static struct at91_cf_data cf0_data;
 
@@ -450,7 +450,7 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
        at91_set_A_periph(AT91_PIN_PD9, 0);  /* CFCE2 */
        at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */
 
-       pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "at91_ide" : "at91_cf";
+       pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "pata_at91" : "at91_cf";
        platform_device_register(pdev);
 }
 #else
index d3f931c5942e9078bcb31803e50a6fefed398c8b..518e42377171c8fb25e5888c8863f7b363721a99 100644 (file)
@@ -23,7 +23,8 @@
                        .globl  at91sam9_alt_restart
 
 at91sam9_alt_restart:  ldr     r0, .at91_va_base_sdramc        @ preload constants
-                       ldr     r1, .at91_va_base_rstc_cr
+                       ldr     r1, =at91_rstc_base
+                       ldr     r1, [r1]
 
                        mov     r2, #1
                        mov     r3, #AT91_SDRAMC_LPCB_POWER_DOWN
@@ -33,11 +34,9 @@ at91sam9_alt_restart:        ldr     r0, .at91_va_base_sdramc        @ preload constants
 
                        str     r2, [r0, #AT91_SDRAMC_TR]       @ disable SDRAM access
                        str     r3, [r0, #AT91_SDRAMC_LPR]      @ power down SDRAM
-                       str     r4, [r1]                        @ reset processor
+                       str     r4, [r1, #AT91_RSTC_CR]         @ reset processor
 
                        b       .
 
 .at91_va_base_sdramc:
        .word AT91_VA_BASE_SYS + AT91_SDRAMC0
-.at91_va_base_rstc_cr:
-       .word AT91_VA_BASE_SYS + AT91_RSTC_CR
index 7032dd32cdf0fbc207dc265958e70faeb1e32143..1cb6a96b1c1e3a7ec44cbde4129992b1f54da5eb 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/mach/map.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
 #include <mach/cpu.h>
 
 #include "soc.h"
@@ -318,11 +317,6 @@ static struct at91_gpio_bank at91sam9g45_gpio[] __initdata = {
        }
 };
 
-static void at91sam9g45_restart(char mode, const char *cmd)
-{
-       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 /* --------------------------------------------------------------------
  *  AT91SAM9G45 processor initialization
  * -------------------------------------------------------------------- */
@@ -336,6 +330,7 @@ static void __init at91sam9g45_map_io(void)
 static void __init at91sam9g45_ioremap_registers(void)
 {
        at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC);
+       at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC);
        at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC);
 }
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
new file mode 100644 (file)
index 0000000..0468be1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * reset AT91SAM9G45 as per errata
+ *
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com>
+ *
+ * unless the SDRAM is cleanly shutdown before we hit the
+ * reset register it can be left driving the data bus and
+ * killing the chance of a subsequent boot from NAND
+ *
+ * GPLv2 Only
+ */
+
+#include <linux/linkage.h>
+#include <mach/hardware.h>
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/at91_rstc.h>
+
+                       .arm
+
+                       .globl  at91sam9g45_restart
+
+at91sam9g45_restart:
+                       ldr     r0, .at91_va_base_sdramc0       @ preload constants
+                       ldr     r1, =at91_rstc_base
+                       ldr     r1, [r1]
+
+                       mov     r2, #1
+                       mov     r3, #AT91_DDRSDRC_LPCB_POWER_DOWN
+                       ldr     r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
+
+                       .balign 32                              @ align to cache line
+
+                       str     r2, [r0, #AT91_DDRSDRC_RTR]     @ disable DDR0 access
+                       str     r3, [r0, #AT91_DDRSDRC_LPR]     @ power down DDR0
+                       str     r4, [r1, #AT91_RSTC_CR]         @ reset processor
+
+                       b       .
+
+.at91_va_base_sdramc0:
+       .word AT91_VA_BASE_SYS + AT91_DDRSDRC0
index d6bcb1da11dfbc004d0c59890d60fef8d3dde27f..d2c91a841cb8c5fe73b1d5a6682e9d6626cb4f74 100644 (file)
@@ -286,6 +286,7 @@ static void __init at91sam9rl_map_io(void)
 static void __init at91sam9rl_ioremap_registers(void)
 {
        at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC);
+       at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC);
        at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
 }
index 4866b8180d66610d17d6a0576424e19a751995a0..594133451c0c88498d50d30b223f22341c132cb2 100644 (file)
@@ -58,7 +58,9 @@ extern void at91_irq_suspend(void);
 extern void at91_irq_resume(void);
 
 /* reset */
+extern void at91_ioremap_rstc(u32 base_addr);
 extern void at91sam9_alt_restart(char, const char *);
+extern void at91sam9g45_restart(char, const char *);
 
 /* shutdown */
 extern void at91_ioremap_shdwc(u32 base_addr);
index cbd2bf052c1f0e64937146e48ed5521f321d0c75..875fa336800ba3848b04362fe0db4caa73cb4865 100644 (file)
 #ifndef AT91_RSTC_H
 #define AT91_RSTC_H
 
-#define AT91_RSTC_CR           (AT91_RSTC + 0x00)      /* Reset Controller Control Register */
+#ifndef __ASSEMBLY__
+extern void __iomem *at91_rstc_base;
+
+#define at91_rstc_read(field) \
+       __raw_readl(at91_rstc_base + field)
+
+#define at91_rstc_write(field, value) \
+       __raw_writel(value, at91_rstc_base + field);
+#else
+.extern at91_rstc_base
+#endif
+
+#define AT91_RSTC_CR           0x00                    /* Reset Controller Control Register */
 #define                AT91_RSTC_PROCRST       (1 << 0)                /* Processor Reset */
 #define                AT91_RSTC_PERRST        (1 << 2)                /* Peripheral Reset */
 #define                AT91_RSTC_EXTRST        (1 << 3)                /* External Reset */
 #define                AT91_RSTC_KEY           (0xa5 << 24)            /* KEY Password */
 
-#define AT91_RSTC_SR           (AT91_RSTC + 0x04)      /* Reset Controller Status Register */
+#define AT91_RSTC_SR           0x04                    /* Reset Controller Status Register */
 #define                AT91_RSTC_URSTS         (1 << 0)                /* User Reset Status */
 #define                AT91_RSTC_RSTTYP        (7 << 8)                /* Reset Type */
 #define                        AT91_RSTC_RSTTYP_GENERAL        (0 << 8)
@@ -33,7 +45,7 @@
 #define                AT91_RSTC_NRSTL         (1 << 16)               /* NRST Pin Level */
 #define                AT91_RSTC_SRCMP         (1 << 17)               /* Software Reset Command in Progress */
 
-#define AT91_RSTC_MR           (AT91_RSTC + 0x08)      /* Reset Controller Mode Register */
+#define AT91_RSTC_MR           0x08                    /* Reset Controller Mode Register */
 #define                AT91_RSTC_URSTEN        (1 << 0)                /* User Reset Enable */
 #define                AT91_RSTC_URSTIEN       (1 << 4)                /* User Reset Interrupt Enable */
 #define                AT91_RSTC_ERSTL         (0xf << 8)              /* External Reset Length */
index 4c0e2f6011d70cc2ef93c349e70d02d9fc740065..61d952902f2b7ebe3a76ac3c1d40abe44c1f1282 100644 (file)
@@ -83,7 +83,6 @@
 #define AT91_DDRSDRC0  (0xffffe600 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffea00 - AT91_BASE_SYS)
 #define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
 #define AT91_GPBR      (cpu_is_at91cap9_revB() ?       \
                        (0xfffffd50 - AT91_BASE_SYS) :  \
                        (0xfffffd60 - AT91_BASE_SYS))
@@ -96,6 +95,7 @@
 #define AT91CAP9_BASE_PIOB     0xfffff400
 #define AT91CAP9_BASE_PIOC     0xfffff600
 #define AT91CAP9_BASE_PIOD     0xfffff800
+#define AT91CAP9_BASE_RSTC     0xfffffd00
 #define AT91CAP9_BASE_SHDWC    0xfffffd10
 #define AT91CAP9_BASE_RTT      0xfffffd20
 #define AT91CAP9_BASE_PIT      0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
deleted file mode 100644 (file)
index 976f4a6..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
- *
- *  (C) 2008 Andrew Victor
- *
- * DDR/SDR Controller (DDRSDRC) - System peripherals registers.
- * Based on AT91CAP9 datasheet revision B.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91CAP9_DDRSDR_H
-#define AT91CAP9_DDRSDR_H
-
-#define AT91_DDRSDRC_MR                0x00    /* Mode Register */
-#define                AT91_DDRSDRC_MODE       (0xf << 0)              /* Command Mode */
-#define                        AT91_DDRSDRC_MODE_NORMAL                0
-#define                        AT91_DDRSDRC_MODE_NOP           1
-#define                        AT91_DDRSDRC_MODE_PRECHARGE     2
-#define                        AT91_DDRSDRC_MODE_LMR           3
-#define                        AT91_DDRSDRC_MODE_REFRESH       4
-#define                        AT91_DDRSDRC_MODE_EXT_LMR       5
-#define                        AT91_DDRSDRC_MODE_DEEP          6
-
-#define AT91_DDRSDRC_RTR       0x04    /* Refresh Timer Register */
-#define                AT91_DDRSDRC_COUNT      (0xfff << 0)            /* Refresh Timer Counter */
-
-#define AT91_DDRSDRC_CR                0x08    /* Configuration Register */
-#define                AT91_DDRSDRC_NC         (3 << 0)                /* Number of Column Bits */
-#define                        AT91_DDRSDRC_NC_SDR8    (0 << 0)
-#define                        AT91_DDRSDRC_NC_SDR9    (1 << 0)
-#define                        AT91_DDRSDRC_NC_SDR10   (2 << 0)
-#define                        AT91_DDRSDRC_NC_SDR11   (3 << 0)
-#define                        AT91_DDRSDRC_NC_DDR9    (0 << 0)
-#define                        AT91_DDRSDRC_NC_DDR10   (1 << 0)
-#define                        AT91_DDRSDRC_NC_DDR11   (2 << 0)
-#define                        AT91_DDRSDRC_NC_DDR12   (3 << 0)
-#define                AT91_DDRSDRC_NR         (3 << 2)                /* Number of Row Bits */
-#define                        AT91_DDRSDRC_NR_11      (0 << 2)
-#define                        AT91_DDRSDRC_NR_12      (1 << 2)
-#define                        AT91_DDRSDRC_NR_13      (2 << 2)
-#define                AT91_DDRSDRC_CAS        (7 << 4)                /* CAS Latency */
-#define                        AT91_DDRSDRC_CAS_2      (2 << 4)
-#define                        AT91_DDRSDRC_CAS_3      (3 << 4)
-#define                        AT91_DDRSDRC_CAS_25     (6 << 4)
-#define                AT91_DDRSDRC_DLL        (1 << 7)                /* Reset DLL */
-#define                AT91_DDRSDRC_DICDS      (1 << 8)                /* Output impedance control */
-
-#define AT91_DDRSDRC_T0PR      0x0C    /* Timing 0 Register */
-#define                AT91_DDRSDRC_TRAS       (0xf <<  0)             /* Active to Precharge delay */
-#define                AT91_DDRSDRC_TRCD       (0xf <<  4)             /* Row to Column delay */
-#define                AT91_DDRSDRC_TWR        (0xf <<  8)             /* Write recovery delay */
-#define                AT91_DDRSDRC_TRC        (0xf << 12)             /* Row cycle delay */
-#define                AT91_DDRSDRC_TRP        (0xf << 16)             /* Row precharge delay */
-#define                AT91_DDRSDRC_TRRD       (0xf << 20)             /* Active BankA to BankB */
-#define                AT91_DDRSDRC_TWTR       (1   << 24)             /* Internal Write to Read delay */
-#define                AT91_DDRSDRC_TMRD       (0xf << 28)             /* Load mode to active/refresh delay */
-
-#define AT91_DDRSDRC_T1PR      0x10    /* Timing 1 Register */
-#define                AT91_DDRSDRC_TRFC       (0x1f << 0)             /* Row Cycle Delay */
-#define                AT91_DDRSDRC_TXSNR      (0xff << 8)             /* Exit self-refresh to non-read */
-#define                AT91_DDRSDRC_TXSRD      (0xff << 16)            /* Exit self-refresh to read */
-#define                AT91_DDRSDRC_TXP        (0xf  << 24)            /* Exit power-down delay */
-
-#define AT91_DDRSDRC_LPR       0x18    /* Low Power Register */
-#define                AT91_DDRSDRC_LPCB               (3 << 0)        /* Low-power Configurations */
-#define                        AT91_DDRSDRC_LPCB_DISABLE               0
-#define                        AT91_DDRSDRC_LPCB_SELF_REFRESH          1
-#define                        AT91_DDRSDRC_LPCB_POWER_DOWN            2
-#define                        AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN       3
-#define                AT91_DDRSDRC_CLKFR              (1 << 2)        /* Clock Frozen */
-#define                AT91_DDRSDRC_PASR               (7 << 4)        /* Partial Array Self Refresh */
-#define                AT91_DDRSDRC_TCSR               (3 << 8)        /* Temperature Compensated Self Refresh */
-#define                AT91_DDRSDRC_DS                 (3 << 10)       /* Drive Strength */
-#define                AT91_DDRSDRC_TIMEOUT            (3 << 12)       /* Time to define when Low Power Mode is enabled */
-#define                        AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES       (0 << 12)
-#define                        AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES      (1 << 12)
-#define                        AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES     (2 << 12)
-
-#define AT91_DDRSDRC_MDR       0x1C    /* Memory Device Register */
-#define                AT91_DDRSDRC_MD         (3 << 0)                /* Memory Device Type */
-#define                        AT91_DDRSDRC_MD_SDR             0
-#define                        AT91_DDRSDRC_MD_LOW_POWER_SDR   1
-#define                        AT91_DDRSDRC_MD_DDR             2
-#define                        AT91_DDRSDRC_MD_LOW_POWER_DDR   3
-
-#define AT91_DDRSDRC_DLLR      0x20    /* DLL Information Register */
-#define                AT91_DDRSDRC_MDINC      (1 << 0)                /* Master Delay increment */
-#define                AT91_DDRSDRC_MDDEC      (1 << 1)                /* Master Delay decrement */
-#define                AT91_DDRSDRC_MDOVF      (1 << 2)                /* Master Delay Overflow */
-#define                AT91_DDRSDRC_SDCOVF     (1 << 3)                /* Slave Delay Correction Overflow */
-#define                AT91_DDRSDRC_SDCUDF     (1 << 4)                /* Slave Delay Correction Underflow */
-#define                AT91_DDRSDRC_SDERF      (1 << 5)                /* Slave Delay Correction error */
-#define                AT91_DDRSDRC_MDVAL      (0xff <<  8)            /* Master Delay value */
-#define                AT91_DDRSDRC_SDVAL      (0xff << 16)            /* Slave Delay value */
-#define                AT91_DDRSDRC_SDCVAL     (0xff << 24)            /* Slave Delay Correction value */
-
-/* Register access macros */
-#define at91_ramc_read(num, reg) \
-       at91_sys_read(AT91_DDRSDRC##num + reg)
-#define at91_ramc_write(num, reg, value) \
-       at91_sys_write(AT91_DDRSDRC##num + reg, value)
-
-
-#endif
index f937c476bb67d6a584b08b122178caa0979cb405..fa5ca278adebf726a2cf849e162e33a82bc101b6 100644 (file)
@@ -83,7 +83,6 @@
 #define AT91_SDRAMC0   (0xffffea00 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffee00 - AT91_BASE_SYS)
 #define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
 #define AT91_GPBR      (0xfffffd50 - AT91_BASE_SYS)
 
 #define AT91SAM9260_BASE_ECC   0xffffe800
@@ -92,6 +91,7 @@
 #define AT91SAM9260_BASE_PIOA  0xfffff400
 #define AT91SAM9260_BASE_PIOB  0xfffff600
 #define AT91SAM9260_BASE_PIOC  0xfffff800
+#define AT91SAM9260_BASE_RSTC  0xfffffd00
 #define AT91SAM9260_BASE_SHDWC 0xfffffd10
 #define AT91SAM9260_BASE_RTT   0xfffffd20
 #define AT91SAM9260_BASE_PIT   0xfffffd30
index 175604e261becd42ba06aa5b7dc9150cf3eb7fb1..7cde2d36570eeee50049e54ff4a2f61ac853a69c 100644 (file)
@@ -68,7 +68,6 @@
 #define AT91_SDRAMC0   (0xffffea00 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffee00 - AT91_BASE_SYS)
 #define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
 #define AT91_GPBR      (0xfffffd50 - AT91_BASE_SYS)
 
 #define AT91SAM9261_BASE_SMC   0xffffec00
@@ -76,6 +75,7 @@
 #define AT91SAM9261_BASE_PIOA  0xfffff400
 #define AT91SAM9261_BASE_PIOB  0xfffff600
 #define AT91SAM9261_BASE_PIOC  0xfffff800
+#define AT91SAM9261_BASE_RSTC  0xfffffd00
 #define AT91SAM9261_BASE_SHDWC 0xfffffd10
 #define AT91SAM9261_BASE_RTT   0xfffffd20
 #define AT91SAM9261_BASE_PIT   0xfffffd30
index 80c915002d835a91e87d420efdb1c2ac422a8803..5949abda962b2affffaa44c59bfbf4e7138e610f 100644 (file)
@@ -78,7 +78,6 @@
 #define AT91_SDRAMC1   (0xffffe800 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffec00 - AT91_BASE_SYS)
 #define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
 #define AT91_GPBR      (0xfffffd60 - AT91_BASE_SYS)
 
 #define AT91SAM9263_BASE_ECC0  0xffffe000
@@ -91,6 +90,7 @@
 #define AT91SAM9263_BASE_PIOC  0xfffff600
 #define AT91SAM9263_BASE_PIOD  0xfffff800
 #define AT91SAM9263_BASE_PIOE  0xfffffa00
+#define AT91SAM9263_BASE_RSTC  0xfffffd00
 #define AT91SAM9263_BASE_SHDWC 0xfffffd10
 #define AT91SAM9263_BASE_RTT0  0xfffffd20
 #define AT91SAM9263_BASE_PIT   0xfffffd30
index d27b15ba8ebf81c74792c6b0cd2f5a12f33cb664..e2f8da8ce5bc81f8b0447b0529c5b9338d5c447f 100644 (file)
 #define                        AT91_DDRSDRC_CAS_25     (6 << 4)
 #define                AT91_DDRSDRC_RST_DLL    (1 << 7)                /* Reset DLL */
 #define                AT91_DDRSDRC_DICDS      (1 << 8)                /* Output impedance control */
-#define                AT91_DDRSDRC_DIS_DLL    (1 << 9)                /* Disable DLL */
-#define                AT91_DDRSDRC_OCD        (1 << 12)               /* Off-Chip Driver */
-#define                AT91_DDRSDRC_DQMS       (1 << 16)               /* Mask Data is Shared */
-#define                AT91_DDRSDRC_ACTBST     (1 << 18)               /* Active Bank X to Burst Stop Read Access Bank Y */
+#define                AT91_DDRSDRC_DIS_DLL    (1 << 9)                /* Disable DLL [SAM9 Only] */
+#define                AT91_DDRSDRC_OCD        (1 << 12)               /* Off-Chip Driver [SAM9 Only] */
+#define                AT91_DDRSDRC_DQMS       (1 << 16)               /* Mask Data is Shared [SAM9 Only] */
+#define                AT91_DDRSDRC_ACTBST     (1 << 18)               /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */
 
 #define AT91_DDRSDRC_T0PR      0x0C    /* Timing 0 Register */
 #define                AT91_DDRSDRC_TRAS       (0xf <<  0)             /* Active to Precharge delay */
@@ -59,7 +59,8 @@
 #define                AT91_DDRSDRC_TRP        (0xf << 16)             /* Row precharge delay */
 #define                AT91_DDRSDRC_TRRD       (0xf << 20)             /* Active BankA to BankB */
 #define                AT91_DDRSDRC_TWTR       (0x7 << 24)             /* Internal Write to Read delay */
-#define                AT91_DDRSDRC_RED_WRRD   (0x1 << 27)             /* Reduce Write to Read Delay */
+#define                AT91CAP9_DDRSDRC_TWTR   (1   << 24)             /* Internal Write to Read delay */
+#define                AT91_DDRSDRC_RED_WRRD   (0x1 << 27)             /* Reduce Write to Read Delay [SAM9 Only] */
 #define                AT91_DDRSDRC_TMRD       (0xf << 28)             /* Load mode to active/refresh delay */
 
 #define AT91_DDRSDRC_T1PR      0x10    /* Timing 1 Register */
 #define                AT91_DDRSDRC_TXSRD      (0xff << 16)            /* Exit self-refresh to read */
 #define                AT91_DDRSDRC_TXP        (0xf  << 24)            /* Exit power-down delay */
 
-#define AT91_DDRSDRC_T2PR      0x14    /* Timing 2 Register */
+#define AT91_DDRSDRC_T2PR      0x14    /* Timing 2 Register [SAM9 Only] */
 #define                AT91_DDRSDRC_TXARD      (0xf  << 0)             /* Exit active power down delay to read command in mode "Fast Exit" */
 #define                AT91_DDRSDRC_TXARDS     (0xf  << 4)             /* Exit active power down delay to read command in mode "Slow Exit" */
 #define                AT91_DDRSDRC_TRPA       (0xf  << 8)             /* Row Precharge All delay */
 #define                AT91_DDRSDRC_TRTP       (0x7  << 12)            /* Read to Precharge delay */
 
 #define AT91_DDRSDRC_LPR       0x1C    /* Low Power Register */
+#define AT91CAP9_DDRSDRC_LPR   0x18    /* Low Power Register */
 #define                AT91_DDRSDRC_LPCB       (3 << 0)                /* Low-power Configurations */
 #define                        AT91_DDRSDRC_LPCB_DISABLE               0
 #define                        AT91_DDRSDRC_LPCB_SELF_REFRESH          1
 #define                AT91_DDRSDRC_UPD_MR     (3 << 20)        /* Update load mode register and extended mode register */
 
 #define AT91_DDRSDRC_MDR       0x20    /* Memory Device Register */
+#define AT91CAP9_DDRSDRC_MDR   0x1C    /* Memory Device Register */
 #define                AT91_DDRSDRC_MD         (3 << 0)                /* Memory Device Type */
 #define                        AT91_DDRSDRC_MD_SDR             0
 #define                        AT91_DDRSDRC_MD_LOW_POWER_SDR   1
+#define                        AT91CAP9_DDRSDRC_MD_DDR         2
 #define                        AT91_DDRSDRC_MD_LOW_POWER_DDR   3
-#define                        AT91_DDRSDRC_MD_DDR2            6
+#define                        AT91_DDRSDRC_MD_DDR2            6       /* [SAM9 Only] */
 #define                AT91_DDRSDRC_DBW        (1 << 4)                /* Data Bus Width */
 #define                        AT91_DDRSDRC_DBW_32BITS         (0 <<  4)
 #define                        AT91_DDRSDRC_DBW_16BITS         (1 <<  4)
 
 #define AT91_DDRSDRC_DLL       0x24    /* DLL Information Register */
+#define AT91CAP9_DDRSDRC_DLL   0x20    /* DLL Information Register */
 #define                AT91_DDRSDRC_MDINC      (1 << 0)                /* Master Delay increment */
 #define                AT91_DDRSDRC_MDDEC      (1 << 1)                /* Master Delay decrement */
 #define                AT91_DDRSDRC_MDOVF      (1 << 2)                /* Master Delay Overflow */
+#define                AT91CAP9_DDRSDRC_SDCOVF (1 << 3)                /* Slave Delay Correction Overflow */
+#define                AT91CAP9_DDRSDRC_SDCUDF (1 << 4)                /* Slave Delay Correction Underflow */
+#define                AT91CAP9_DDRSDRC_SDERF  (1 << 5)                /* Slave Delay Correction error */
 #define                AT91_DDRSDRC_MDVAL      (0xff <<  8)            /* Master Delay value */
+#define                AT91CAP9_DDRSDRC_SDVAL  (0xff << 16)            /* Slave Delay value */
+#define                AT91CAP9_DDRSDRC_SDCVAL (0xff << 24)            /* Slave Delay Correction value */
 
-#define AT91_DDRSDRC_HS                0x2C    /* High Speed Register */
+#define AT91_DDRSDRC_HS                0x2C    /* High Speed Register [SAM9 Only] */
 #define                AT91_DDRSDRC_DIS_ATCP_RD        (1 << 2)        /* Anticip read access is disabled */
 
 #define AT91_DDRSDRC_DELAY(n)  (0x30 + (0x4 * (n)))    /* Delay I/O Register n */
 
-#define AT91_DDRSDRC_WPMR      0xE4    /* Write Protect Mode Register */
+#define AT91_DDRSDRC_WPMR      0xE4    /* Write Protect Mode Register [SAM9 Only] */
 #define                AT91_DDRSDRC_WP         (1 << 0)                /* Write protect enable */
 #define                AT91_DDRSDRC_WPKEY      (0xffffff << 8)         /* Write protect key */
 #define                AT91_DDRSDRC_KEY        (0x444452 << 8)         /* Write protect key = "DDR" */
 
-#define AT91_DDRSDRC_WPSR      0xE8    /* Write Protect Status Register */
+#define AT91_DDRSDRC_WPSR      0xE8    /* Write Protect Status Register [SAM9 Only] */
 #define                AT91_DDRSDRC_WPVS       (1 << 0)                /* Write protect violation status */
 #define                AT91_DDRSDRC_WPVSRC     (0xffff << 8)           /* Write protect violation source */
 
index eb18a70fa6472d32881af288909d144d988f39ce..175e1fdd9fe8ade33846f2ff42441d61053bc928 100644 (file)
 
 #include <mach/cpu.h>
 
+#ifndef __ASSEMBLY__
+struct sam9_smc_config {
+       /* Setup register */
+       u8 ncs_read_setup;
+       u8 nrd_setup;
+       u8 ncs_write_setup;
+       u8 nwe_setup;
+
+       /* Pulse register */
+       u8 ncs_read_pulse;
+       u8 nrd_pulse;
+       u8 ncs_write_pulse;
+       u8 nwe_pulse;
+
+       /* Cycle register */
+       u16 read_cycle;
+       u16 write_cycle;
+
+       /* Mode register */
+       u32 mode;
+       u8 tdf_cycles:4;
+};
+
+extern void sam9_smc_configure(int id, int cs, struct sam9_smc_config *config);
+extern void sam9_smc_read(int id, int cs, struct sam9_smc_config *config);
+extern void sam9_smc_read_mode(int id, int cs, struct sam9_smc_config *config);
+extern void sam9_smc_write_mode(int id, int cs, struct sam9_smc_config *config);
+#endif
+
 #define AT91_SMC_SETUP         0x00                            /* Setup Register for CS n */
 #define                AT91_SMC_NWESETUP       (0x3f << 0)                     /* NWE Setup Length */
 #define                        AT91_SMC_NWESETUP_(x)   ((x) << 0)
index f0c23c960dece748b5453e735c66e710c205a54d..dd9c95ea0862d7233c4d669b2262c05cd6d3021d 100644 (file)
@@ -90,7 +90,6 @@
 #define AT91_DDRSDRC0  (0xffffe600 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffea00 - AT91_BASE_SYS)
 #define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
 #define AT91_GPBR      (0xfffffd60 - AT91_BASE_SYS)
 
 #define AT91SAM9G45_BASE_ECC   0xffffe200
 #define AT91SAM9G45_BASE_PIOC  0xfffff600
 #define AT91SAM9G45_BASE_PIOD  0xfffff800
 #define AT91SAM9G45_BASE_PIOE  0xfffffa00
+#define AT91SAM9G45_BASE_RSTC  0xfffffd00
 #define AT91SAM9G45_BASE_SHDWC 0xfffffd10
 #define AT91SAM9G45_BASE_RTT   0xfffffd20
 #define AT91SAM9G45_BASE_PIT   0xfffffd30
index 2bb359e60b97f5b71367ac3ffe832b255f90be3d..d7bead7118da85873c4ef43388432ce80f24a9f1 100644 (file)
@@ -72,7 +72,6 @@
 #define AT91_SDRAMC0   (0xffffea00 - AT91_BASE_SYS)
 #define AT91_MATRIX    (0xffffee00 - AT91_BASE_SYS)
 #define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SCKCR     (0xfffffd50 - AT91_BASE_SYS)
 #define AT91_GPBR      (0xfffffd60 - AT91_BASE_SYS)
 
@@ -84,6 +83,7 @@
 #define AT91SAM9RL_BASE_PIOB   0xfffff600
 #define AT91SAM9RL_BASE_PIOC   0xfffff800
 #define AT91SAM9RL_BASE_PIOD   0xfffffa00
+#define AT91SAM9RL_BASE_RSTC   0xfffffd00
 #define AT91SAM9RL_BASE_SHDWC  0xfffffd10
 #define AT91SAM9RL_BASE_RTT    0xfffffd20
 #define AT91SAM9RL_BASE_PIT    0xfffffd30
index d0b377b21bd7d76da84a19db3c05c6d7304e62c0..3b33f07b1e1189ab4a49644741715731b095461f 100644 (file)
@@ -88,7 +88,7 @@ extern void __init at91_add_device_eth(struct macb_platform_data *data);
 struct at91_usbh_data {
        u8              ports;          /* number of ports on root hub */
        int             vbus_pin[2];    /* port power-control pin */
-       u8              vbus_pin_inverted;
+       u8              vbus_pin_active_low[2];
        u8              overcurrent_supported;
        int             overcurrent_pin[2];
        u8              overcurrent_status[2];
index 62ad95556c367f7ab7f0311428b6475070aeab02..1606379ac28462dd33f31ba8e0756a9d6ec4d21a 100644 (file)
@@ -34,7 +34,6 @@
 /*
  * Show the reason for the previous system reset.
  */
-#if defined(AT91_RSTC)
 
 #include <mach/at91_rstc.h>
 #include <mach/at91_shdwc.h>
@@ -58,10 +57,10 @@ static void __init show_reset_status(void)
        char *reason, *r2 = reset;
        u32 reset_type, wake_type;
 
-       if (!at91_shdwc_base)
+       if (!at91_shdwc_base || !at91_rstc_base)
                return;
 
-       reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
+       reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
        wake_type = at91_shdwc_read(AT91_SHDW_SR);
 
        switch (reset_type) {
@@ -102,10 +101,6 @@ static void __init show_reset_status(void)
        }
        pr_info("AT91: Starting after %s %s\n", reason, r2);
 }
-#else
-static void __init show_reset_status(void) {}
-#endif
-
 
 static int at91_pm_valid_state(suspend_state_t state)
 {
index ce9a206991111672d6d1a0a235855c8849adf842..7eb40d24242f2ae54fbd9ab8197d6166f98381eb 100644 (file)
@@ -25,21 +25,21 @@ static inline u32 sdram_selfrefresh_enable(void)
                                                                : : "r" (0))
 
 #elif defined(CONFIG_ARCH_AT91CAP9)
-#include <mach/at91cap9_ddrsdr.h>
+#include <mach/at91sam9_ddrsdr.h>
 
 
 static inline u32 sdram_selfrefresh_enable(void)
 {
        u32 saved_lpr, lpr;
 
-       saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+       saved_lpr = at91_ramc_read(0, AT91CAP9_DDRSDRC_LPR);
 
        lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
-       at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
+       at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
        return saved_lpr;
 }
 
-#define sdram_selfrefresh_disable(saved_lpr)   at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr)
+#define sdram_selfrefresh_disable(saved_lpr)   at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, saved_lpr)
 #define wait_for_interrupt_enable()            cpu_do_idle()
 
 #elif defined(CONFIG_ARCH_AT91SAM9G45)
index f7922a436172a063bf188af5fc2b24cad4ab148e..92dfb8461392a66541a1370de2c7dce11c03a039 100644 (file)
@@ -18,9 +18,8 @@
 
 #if defined(CONFIG_ARCH_AT91RM9200)
 #include <mach/at91rm9200_mc.h>
-#elif defined(CONFIG_ARCH_AT91CAP9)
-#include <mach/at91cap9_ddrsdr.h>
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
+#elif defined(CONFIG_ARCH_AT91CAP9) \
+       || defined(CONFIG_ARCH_AT91SAM9G45)
 #include <mach/at91sam9_ddrsdr.h>
 #else
 #include <mach/at91sam9_sdramc.h>
index 8294783b679d8aa58579a9d0a149a1a79bb1af6a..99a0a1d2b7dce8503d303c7af2dc022f06738d74 100644 (file)
@@ -2,6 +2,7 @@
  * linux/arch/arm/mach-at91/sam9_smc.c
  *
  * Copyright (C) 2008 Andrew Victor
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 
 static void __iomem *smc_base_addr[2];
 
-static void __init sam9_smc_cs_configure(void __iomem *base, struct sam9_smc_config* config)
+static void sam9_smc_cs_write_mode(void __iomem *base,
+                                       struct sam9_smc_config *config)
+{
+       __raw_writel(config->mode
+                  | AT91_SMC_TDF_(config->tdf_cycles),
+                  base + AT91_SMC_MODE);
+}
+
+void sam9_smc_write_mode(int id, int cs,
+                                       struct sam9_smc_config *config)
+{
+       sam9_smc_cs_write_mode(AT91_SMC_CS(id, cs), config);
+}
+
+static void sam9_smc_cs_configure(void __iomem *base,
+                                       struct sam9_smc_config *config)
 {
 
        /* Setup register */
@@ -45,16 +61,66 @@ static void __init sam9_smc_cs_configure(void __iomem *base, struct sam9_smc_con
                   base + AT91_SMC_CYCLE);
 
        /* Mode register */
-       __raw_writel(config->mode
-                  | AT91_SMC_TDF_(config->tdf_cycles),
-                  base + AT91_SMC_MODE);
+       sam9_smc_cs_write_mode(base, config);
 }
 
-void __init sam9_smc_configure(int id, int cs, struct sam9_smc_config* config)
+void sam9_smc_configure(int id, int cs,
+                                       struct sam9_smc_config *config)
 {
        sam9_smc_cs_configure(AT91_SMC_CS(id, cs), config);
 }
 
+static void sam9_smc_cs_read_mode(void __iomem *base,
+                                       struct sam9_smc_config *config)
+{
+       u32 val = __raw_readl(base + AT91_SMC_MODE);
+
+       config->mode = (val & ~AT91_SMC_NWECYCLE);
+       config->tdf_cycles = (val & AT91_SMC_NWECYCLE) >> 16 ;
+}
+
+void sam9_smc_read_mode(int id, int cs,
+                                       struct sam9_smc_config *config)
+{
+       sam9_smc_cs_read_mode(AT91_SMC_CS(id, cs), config);
+}
+
+static void sam9_smc_cs_read(void __iomem *base,
+                                       struct sam9_smc_config *config)
+{
+       u32 val;
+
+       /* Setup register */
+       val = __raw_readl(base + AT91_SMC_SETUP);
+
+       config->nwe_setup = val & AT91_SMC_NWESETUP;
+       config->ncs_write_setup = (val & AT91_SMC_NCS_WRSETUP) >> 8;
+       config->nrd_setup = (val & AT91_SMC_NRDSETUP) >> 16;
+       config->ncs_read_setup = (val & AT91_SMC_NCS_RDSETUP) >> 24;
+
+       /* Pulse register */
+       val = __raw_readl(base + AT91_SMC_PULSE);
+
+       config->nwe_setup = val & AT91_SMC_NWEPULSE;
+       config->ncs_write_pulse = (val & AT91_SMC_NCS_WRPULSE) >> 8;
+       config->nrd_pulse = (val & AT91_SMC_NRDPULSE) >> 16;
+       config->ncs_read_pulse = (val & AT91_SMC_NCS_RDPULSE) >> 24;
+
+       /* Cycle register */
+       val = __raw_readl(base + AT91_SMC_CYCLE);
+
+       config->write_cycle = val & AT91_SMC_NWECYCLE;
+       config->read_cycle = (val & AT91_SMC_NRDCYCLE) >> 16;
+
+       /* Mode register */
+       sam9_smc_cs_read_mode(base, config);
+}
+
+void sam9_smc_read(int id, int cs, struct sam9_smc_config *config)
+{
+       sam9_smc_cs_read(AT91_SMC_CS(id, cs), config);
+}
+
 void __init at91sam9_ioremap_smc(int id, u32 addr)
 {
        if (id > 1) {
index 039c5ce17aec5cb2c8b01625041b7924f5bc7e3c..3e52dcd4a59febc19418194892f8ed4b5ec58c01 100644 (file)
@@ -8,27 +8,4 @@
  * published by the Free Software Foundation.
  */
 
-struct sam9_smc_config {
-       /* Setup register */
-       u8 ncs_read_setup;
-       u8 nrd_setup;
-       u8 ncs_write_setup;
-       u8 nwe_setup;
-
-       /* Pulse register */
-       u8 ncs_read_pulse;
-       u8 nrd_pulse;
-       u8 ncs_write_pulse;
-       u8 nwe_pulse;
-
-       /* Cycle register */
-       u16 read_cycle;
-       u16 write_cycle;
-
-       /* Mode register */
-       u32 mode;
-       u8 tdf_cycles:4;
-};
-
-extern void __init sam9_smc_configure(int id, int cs, struct sam9_smc_config* config);
 extern void __init at91sam9_ioremap_smc(int id, u32 addr);
index 8bdcc3cb6012bf723ab46c27ca44f63d81d22da9..69d3fc4c46f372ff99c2468f5e8eda6cc110bfd5 100644 (file)
@@ -29,9 +29,12 @@ EXPORT_SYMBOL(at91_soc_initdata);
 void __init at91rm9200_set_type(int type)
 {
        if (type == ARCH_REVISON_9200_PQFP)
-               at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
-       else
                at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP;
+       else
+               at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
+
+       pr_info("AT91: filled in soc subtype: %s\n",
+               at91_get_soc_subtype(&at91_soc_initdata));
 }
 
 void __init at91_init_irq_default(void)
@@ -281,6 +284,15 @@ void __init at91_ioremap_shdwc(u32 base_addr)
        pm_power_off = at91sam9_poweroff;
 }
 
+void __iomem *at91_rstc_base;
+
+void __init at91_ioremap_rstc(u32 base_addr)
+{
+       at91_rstc_base = ioremap(base_addr, 16);
+       if (!at91_rstc_base)
+               panic("Impossible to ioremap at91_rstc_base\n");
+}
+
 void __init at91_initialize(unsigned long main_clock)
 {
        at91_boot_soc.ioremap_registers();
index 9e5e7552498c362c7880b76d3e820640cddfc555..45c97b1ee9b1d59ba923a69b50e94337b48da993 100644 (file)
@@ -194,6 +194,6 @@ MACHINE_START(BCMRING, "BCMRING")
        .init_early = bcmring_init_early,
        .init_irq = bcmring_init_irq,
        .timer = &bcmring_timer,
-       .init_machine = bcmring_init_machine
+       .init_machine = bcmring_init_machine,
        .restart = bcmring_restart,
 MACHINE_END
index 1a1a27dd56544d0684bebc29d40b69bdff2d190f..1024396797e16f6c839383da409731bfaef494d3 100644 (file)
 
 #include <mach/timer.h>
 
-#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 */
-/* especially since dc4 doesn't use kmalloc'd memory. */
-
-#define ALLOW_MAP_OF_KMALLOC_MEMORY 0
-
 /* ---- Public Variables ------------------------------------------------- */
 
 /* ---- Private Constants and Types -------------------------------------- */
 #define CONTROLLER_FROM_HANDLE(handle)    (((handle) >> 4) & 0x0f)
 #define CHANNEL_FROM_HANDLE(handle)       ((handle) & 0x0f)
 
-#define DMA_MAP_DEBUG   0
-
-#if DMA_MAP_DEBUG
-#   define  DMA_MAP_PRINT(fmt, args...)   printk("%s: " fmt, __func__,  ## args)
-#else
-#   define  DMA_MAP_PRINT(fmt, args...)
-#endif
 
 /* ---- Private Variables ------------------------------------------------ */
 
 static DMA_Global_t gDMA;
 static struct proc_dir_entry *gDmaDir;
 
-static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);
-
 #include "dma_device.c"
 
 /* ---- Private Function Prototypes -------------------------------------- */
 
 /* ---- Functions  ------------------------------------------------------- */
 
-/****************************************************************************/
-/**
-*   Displays information for /proc/dma/mem-type
-*/
-/****************************************************************************/
-
-static int dma_proc_read_mem_type(char *buf, char **start, off_t offset,
-                                 int count, int *eof, void *data)
-{
-       int len = 0;
-
-       len += sprintf(buf + len, "dma_map_mem statistics\n");
-       len +=
-           sprintf(buf + len, "coherent: %d\n",
-                   atomic_read(&gDmaStatMemTypeCoherent));
-       len +=
-           sprintf(buf + len, "kmalloc:  %d\n",
-                   atomic_read(&gDmaStatMemTypeKmalloc));
-       len +=
-           sprintf(buf + len, "vmalloc:  %d\n",
-                   atomic_read(&gDmaStatMemTypeVmalloc));
-       len +=
-           sprintf(buf + len, "user:     %d\n",
-                   atomic_read(&gDmaStatMemTypeUser));
-
-       return len;
-}
-
 /****************************************************************************/
 /**
 *   Displays information for /proc/dma/channels
@@ -846,8 +800,6 @@ int dma_init(void)
                                       dma_proc_read_channels, NULL);
                create_proc_read_entry("devices", 0, gDmaDir,
                                       dma_proc_read_devices, NULL);
-               create_proc_read_entry("mem-type", 0, gDmaDir,
-                                      dma_proc_read_mem_type, NULL);
        }
 
 out:
@@ -1565,767 +1517,3 @@ int dma_set_device_handler(DMA_Device_t dev,    /* Device to set the callback for.
 }
 
 EXPORT_SYMBOL(dma_set_device_handler);
-
-/****************************************************************************/
-/**
-*   Initializes a memory mapping structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap)
-{
-       memset(memMap, 0, sizeof(*memMap));
-
-       sema_init(&memMap->lock, 1);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_init_mem_map);
-
-/****************************************************************************/
-/**
-*   Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap)
-{
-       down(&memMap->lock);    /* Just being paranoid */
-
-       /* Free up any allocated memory */
-
-       up(&memMap->lock);
-       memset(memMap, 0, sizeof(*memMap));
-
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_term_mem_map);
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and categorizes it.
-*
-*   @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr)
-{
-       unsigned long addrVal = (unsigned long)addr;
-
-       if (addrVal >= CONSISTENT_BASE) {
-               /* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */
-
-               /* dma_alloc_xxx pages are physically and virtually contiguous */
-
-               return DMA_MEM_TYPE_DMA;
-       }
-
-       /* Technically, we could add one more classification. Addresses between VMALLOC_END */
-       /* and the beginning of the DMA virtual address could be considered to be I/O space. */
-       /* Right now, nobody cares about this particular classification, so we ignore it. */
-
-       if (is_vmalloc_addr(addr)) {
-               /* Address comes from the vmalloc'd region. Pages are virtually */
-               /* contiguous but NOT physically contiguous */
-
-               return DMA_MEM_TYPE_VMALLOC;
-       }
-
-       if (addrVal >= PAGE_OFFSET) {
-               /* PAGE_OFFSET is typically 0xC0000000 */
-
-               /* kmalloc'd pages are physically contiguous */
-
-               return DMA_MEM_TYPE_KMALLOC;
-       }
-
-       return DMA_MEM_TYPE_USER;
-}
-
-EXPORT_SYMBOL(dma_mem_type);
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and determines if we support DMA'ing to/from
-*   that type of memory.
-*
-*   @return boolean -
-*               return value != 0 means dma supported
-*               return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr)
-{
-       DMA_MemType_t memType = dma_mem_type(addr);
-
-       return (memType == DMA_MEM_TYPE_DMA)
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
-           || (memType == DMA_MEM_TYPE_KMALLOC)
-#endif
-           || (memType == DMA_MEM_TYPE_USER);
-}
-
-EXPORT_SYMBOL(dma_mem_supports_dma);
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap,        /* Stores state information about the map */
-                 enum dma_data_direction dir   /* Direction that the mapping will be going */
-    ) {
-       int rc;
-
-       down(&memMap->lock);
-
-       DMA_MAP_PRINT("memMap: %p\n", memMap);
-
-       if (memMap->inUse) {
-               printk(KERN_ERR "%s: memory map %p is already being used\n",
-                      __func__, memMap);
-               rc = -EBUSY;
-               goto out;
-       }
-
-       memMap->inUse = 1;
-       memMap->dir = dir;
-       memMap->numRegionsUsed = 0;
-
-       rc = 0;
-
-out:
-
-       DMA_MAP_PRINT("returning %d", rc);
-
-       up(&memMap->lock);
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_start);
-
-/****************************************************************************/
-/**
-*   Adds a segment of memory to a memory map. Each segment is both
-*   physically and virtually contiguous.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-static int dma_map_add_segment(DMA_MemMap_t *memMap,   /* Stores state information about the map */
-                              DMA_Region_t *region,    /* Region that the segment belongs to */
-                              void *virtAddr,  /* Virtual address of the segment being added */
-                              dma_addr_t physAddr,     /* Physical address of the segment being added */
-                              size_t numBytes  /* Number of bytes of the segment being added */
-    ) {
-       DMA_Segment_t *segment;
-
-       DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr,
-                     physAddr, numBytes);
-
-       /* Sanity check */
-
-       if (((unsigned long)virtAddr < (unsigned long)region->virtAddr)
-           || (((unsigned long)virtAddr + numBytes)) >
-           ((unsigned long)region->virtAddr + region->numBytes)) {
-               printk(KERN_ERR
-                      "%s: virtAddr %p is outside region @ %p len: %d\n",
-                      __func__, virtAddr, region->virtAddr, region->numBytes);
-               return -EINVAL;
-       }
-
-       if (region->numSegmentsUsed > 0) {
-               /* Check to see if this segment is physically contiguous with the previous one */
-
-               segment = &region->segment[region->numSegmentsUsed - 1];
-
-               if ((segment->physAddr + segment->numBytes) == physAddr) {
-                       /* It is - just add on to the end */
-
-                       DMA_MAP_PRINT("appending %d bytes to last segment\n",
-                                     numBytes);
-
-                       segment->numBytes += numBytes;
-
-                       return 0;
-               }
-       }
-
-       /* Reallocate to hold more segments, if required. */
-
-       if (region->numSegmentsUsed >= region->numSegmentsAllocated) {
-               DMA_Segment_t *newSegment;
-               size_t oldSize =
-                   region->numSegmentsAllocated * sizeof(*newSegment);
-               int newAlloc = region->numSegmentsAllocated + 4;
-               size_t newSize = newAlloc * sizeof(*newSegment);
-
-               newSegment = kmalloc(newSize, GFP_KERNEL);
-               if (newSegment == NULL) {
-                       return -ENOMEM;
-               }
-               memcpy(newSegment, region->segment, oldSize);
-               memset(&((uint8_t *) newSegment)[oldSize], 0,
-                      newSize - oldSize);
-               kfree(region->segment);
-
-               region->numSegmentsAllocated = newAlloc;
-               region->segment = newSegment;
-       }
-
-       segment = &region->segment[region->numSegmentsUsed];
-       region->numSegmentsUsed++;
-
-       segment->virtAddr = virtAddr;
-       segment->physAddr = physAddr;
-       segment->numBytes = numBytes;
-
-       DMA_MAP_PRINT("returning success\n");
-
-       return 0;
-}
-
-/****************************************************************************/
-/**
-*   Adds a region of memory to a memory map. Each region is virtually
-*   contiguous, but not necessarily physically contiguous.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap,   /* Stores state information about the map */
-                      void *mem,       /* Virtual address that we want to get a map of */
-                      size_t numBytes  /* Number of bytes being mapped */
-    ) {
-       unsigned long addr = (unsigned long)mem;
-       unsigned int offset;
-       int rc = 0;
-       DMA_Region_t *region;
-       dma_addr_t physAddr;
-
-       down(&memMap->lock);
-
-       DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes);
-
-       if (!memMap->inUse) {
-               printk(KERN_ERR "%s: Make sure you call dma_map_start first\n",
-                      __func__);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       /* Reallocate to hold more regions. */
-
-       if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) {
-               DMA_Region_t *newRegion;
-               size_t oldSize =
-                   memMap->numRegionsAllocated * sizeof(*newRegion);
-               int newAlloc = memMap->numRegionsAllocated + 4;
-               size_t newSize = newAlloc * sizeof(*newRegion);
-
-               newRegion = kmalloc(newSize, GFP_KERNEL);
-               if (newRegion == NULL) {
-                       rc = -ENOMEM;
-                       goto out;
-               }
-               memcpy(newRegion, memMap->region, oldSize);
-               memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize);
-
-               kfree(memMap->region);
-
-               memMap->numRegionsAllocated = newAlloc;
-               memMap->region = newRegion;
-       }
-
-       region = &memMap->region[memMap->numRegionsUsed];
-       memMap->numRegionsUsed++;
-
-       offset = addr & ~PAGE_MASK;
-
-       region->memType = dma_mem_type(mem);
-       region->virtAddr = mem;
-       region->numBytes = numBytes;
-       region->numSegmentsUsed = 0;
-       region->numLockedPages = 0;
-       region->lockedPages = NULL;
-
-       switch (region->memType) {
-       case DMA_MEM_TYPE_VMALLOC:
-               {
-                       atomic_inc(&gDmaStatMemTypeVmalloc);
-
-                       /* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */
-
-                       /* vmalloc'd pages are not physically contiguous */
-
-                       rc = -EINVAL;
-                       break;
-               }
-
-       case DMA_MEM_TYPE_KMALLOC:
-               {
-                       atomic_inc(&gDmaStatMemTypeKmalloc);
-
-                       /* kmalloc'd pages are physically contiguous, so they'll have exactly */
-                       /* one segment */
-
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
-                       physAddr =
-                           dma_map_single(NULL, mem, numBytes, memMap->dir);
-                       rc = dma_map_add_segment(memMap, region, mem, physAddr,
-                                                numBytes);
-#else
-                       rc = -EINVAL;
-#endif
-                       break;
-               }
-
-       case DMA_MEM_TYPE_DMA:
-               {
-                       /* dma_alloc_xxx pages are physically contiguous */
-
-                       atomic_inc(&gDmaStatMemTypeCoherent);
-
-                       physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset;
-
-                       dma_sync_single_for_cpu(NULL, physAddr, numBytes,
-                                               memMap->dir);
-                       rc = dma_map_add_segment(memMap, region, mem, physAddr,
-                                                numBytes);
-                       break;
-               }
-
-       case DMA_MEM_TYPE_USER:
-               {
-                       size_t firstPageOffset;
-                       size_t firstPageSize;
-                       struct page **pages;
-                       struct task_struct *userTask;
-
-                       atomic_inc(&gDmaStatMemTypeUser);
-
-#if 1
-                       /* If the pages are user pages, then the dma_mem_map_set_user_task function */
-                       /* must have been previously called. */
-
-                       if (memMap->userTask == NULL) {
-                               printk(KERN_ERR
-                                      "%s: must call dma_mem_map_set_user_task when using user-mode memory\n",
-                                      __func__);
-                               return -EINVAL;
-                       }
-
-                       /* User pages need to be locked. */
-
-                       firstPageOffset =
-                           (unsigned long)region->virtAddr & (PAGE_SIZE - 1);
-                       firstPageSize = PAGE_SIZE - firstPageOffset;
-
-                       region->numLockedPages = (firstPageOffset
-                                                 + region->numBytes +
-                                                 PAGE_SIZE - 1) / PAGE_SIZE;
-                       pages =
-                           kmalloc(region->numLockedPages *
-                                   sizeof(struct page *), GFP_KERNEL);
-
-                       if (pages == NULL) {
-                               region->numLockedPages = 0;
-                               return -ENOMEM;
-                       }
-
-                       userTask = memMap->userTask;
-
-                       down_read(&userTask->mm->mmap_sem);
-                       rc = get_user_pages(userTask,   /* task */
-                                           userTask->mm,       /* mm */
-                                           (unsigned long)region->virtAddr,    /* start */
-                                           region->numLockedPages,     /* len */
-                                           memMap->dir == DMA_FROM_DEVICE,     /* write */
-                                           0,  /* force */
-                                           pages,      /* pages (array of pointers to page) */
-                                           NULL);      /* vmas */
-                       up_read(&userTask->mm->mmap_sem);
-
-                       if (rc != region->numLockedPages) {
-                               kfree(pages);
-                               region->numLockedPages = 0;
-
-                               if (rc >= 0) {
-                                       rc = -EINVAL;
-                               }
-                       } else {
-                               uint8_t *virtAddr = region->virtAddr;
-                               size_t bytesRemaining;
-                               int pageIdx;
-
-                               rc = 0; /* Since get_user_pages returns +ve number */
-
-                               region->lockedPages = pages;
-
-                               /* We've locked the user pages. Now we need to walk them and figure */
-                               /* out the physical addresses. */
-
-                               /* The first page may be partial */
-
-                               dma_map_add_segment(memMap,
-                                                   region,
-                                                   virtAddr,
-                                                   PFN_PHYS(page_to_pfn
-                                                            (pages[0])) +
-                                                   firstPageOffset,
-                                                   firstPageSize);
-
-                               virtAddr += firstPageSize;
-                               bytesRemaining =
-                                   region->numBytes - firstPageSize;
-
-                               for (pageIdx = 1;
-                                    pageIdx < region->numLockedPages;
-                                    pageIdx++) {
-                                       size_t bytesThisPage =
-                                           (bytesRemaining >
-                                            PAGE_SIZE ? PAGE_SIZE :
-                                            bytesRemaining);
-
-                                       DMA_MAP_PRINT
-                                           ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n",
-                                            pageIdx, pages[pageIdx],
-                                            page_to_pfn(pages[pageIdx]),
-                                            PFN_PHYS(page_to_pfn
-                                                     (pages[pageIdx])));
-
-                                       dma_map_add_segment(memMap,
-                                                           region,
-                                                           virtAddr,
-                                                           PFN_PHYS(page_to_pfn
-                                                                    (pages
-                                                                     [pageIdx])),
-                                                           bytesThisPage);
-
-                                       virtAddr += bytesThisPage;
-                                       bytesRemaining -= bytesThisPage;
-                               }
-                       }
-#else
-                       printk(KERN_ERR
-                              "%s: User mode pages are not yet supported\n",
-                              __func__);
-
-                       /* user pages are not physically contiguous */
-
-                       rc = -EINVAL;
-#endif
-                       break;
-               }
-
-       default:
-               {
-                       printk(KERN_ERR "%s: Unsupported memory type: %d\n",
-                              __func__, region->memType);
-
-                       rc = -EINVAL;
-                       break;
-               }
-       }
-
-       if (rc != 0) {
-               memMap->numRegionsUsed--;
-       }
-
-out:
-
-       DMA_MAP_PRINT("returning %d\n", rc);
-
-       up(&memMap->lock);
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_add_segment);
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap,  /* Stores state information about the map */
-               void *mem,      /* Virtual address that we want to get a map of */
-               size_t numBytes,        /* Number of bytes being mapped */
-               enum dma_data_direction dir     /* Direction that the mapping will be going */
-    ) {
-       int rc;
-
-       rc = dma_map_start(memMap, dir);
-       if (rc == 0) {
-               rc = dma_map_add_region(memMap, mem, numBytes);
-               if (rc < 0) {
-                       /* Since the add fails, this function will fail, and the caller won't */
-                       /* call unmap, so we need to do it here. */
-
-                       dma_unmap(memMap, 0);
-               }
-       }
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_mem);
-
-/****************************************************************************/
-/**
-*   Setup a descriptor ring for a given memory map.
-*
-*   It is assumed that the descriptor ring has already been initialized, and
-*   this routine will only reallocate a new descriptor ring if the existing
-*   one is too small.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev,   /* DMA device (where the ring is stored) */
-                                  DMA_MemMap_t *memMap,        /* Memory map that will be used */
-                                  dma_addr_t devPhysAddr       /* Physical address of device */
-    ) {
-       int rc;
-       int numDescriptors;
-       DMA_DeviceAttribute_t *devAttr;
-       DMA_Region_t *region;
-       DMA_Segment_t *segment;
-       dma_addr_t srcPhysAddr;
-       dma_addr_t dstPhysAddr;
-       int regionIdx;
-       int segmentIdx;
-
-       devAttr = &DMA_gDeviceAttribute[dev];
-
-       down(&memMap->lock);
-
-       /* Figure out how many descriptors we need */
-
-       numDescriptors = 0;
-       for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
-               region = &memMap->region[regionIdx];
-
-               for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
-                    segmentIdx++) {
-                       segment = &region->segment[segmentIdx];
-
-                       if (memMap->dir == DMA_TO_DEVICE) {
-                               srcPhysAddr = segment->physAddr;
-                               dstPhysAddr = devPhysAddr;
-                       } else {
-                               srcPhysAddr = devPhysAddr;
-                               dstPhysAddr = segment->physAddr;
-                       }
-
-                       rc =
-                            dma_calculate_descriptor_count(dev, srcPhysAddr,
-                                                           dstPhysAddr,
-                                                           segment->
-                                                           numBytes);
-                       if (rc < 0) {
-                               printk(KERN_ERR
-                                      "%s: dma_calculate_descriptor_count failed: %d\n",
-                                      __func__, rc);
-                               goto out;
-                       }
-                       numDescriptors += rc;
-               }
-       }
-
-       /* Adjust the size of the ring, if it isn't big enough */
-
-       if (numDescriptors > devAttr->ring.descriptorsAllocated) {
-               dma_free_descriptor_ring(&devAttr->ring);
-               rc =
-                    dma_alloc_descriptor_ring(&devAttr->ring,
-                                              numDescriptors);
-               if (rc < 0) {
-                       printk(KERN_ERR
-                              "%s: dma_alloc_descriptor_ring failed: %d\n",
-                              __func__, rc);
-                       goto out;
-               }
-       } else {
-               rc =
-                    dma_init_descriptor_ring(&devAttr->ring,
-                                             numDescriptors);
-               if (rc < 0) {
-                       printk(KERN_ERR
-                              "%s: dma_init_descriptor_ring failed: %d\n",
-                              __func__, rc);
-                       goto out;
-               }
-       }
-
-       /* Populate the descriptors */
-
-       for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
-               region = &memMap->region[regionIdx];
-
-               for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
-                    segmentIdx++) {
-                       segment = &region->segment[segmentIdx];
-
-                       if (memMap->dir == DMA_TO_DEVICE) {
-                               srcPhysAddr = segment->physAddr;
-                               dstPhysAddr = devPhysAddr;
-                       } else {
-                               srcPhysAddr = devPhysAddr;
-                               dstPhysAddr = segment->physAddr;
-                       }
-
-                       rc =
-                            dma_add_descriptors(&devAttr->ring, dev,
-                                                srcPhysAddr, dstPhysAddr,
-                                                segment->numBytes);
-                       if (rc < 0) {
-                               printk(KERN_ERR
-                                      "%s: dma_add_descriptors failed: %d\n",
-                                      __func__, rc);
-                               goto out;
-                       }
-               }
-       }
-
-       rc = 0;
-
-out:
-
-       up(&memMap->lock);
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_map_create_descriptor_ring);
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap,    /* Stores state information about the map */
-             int dirtied       /* non-zero if any of the pages were modified */
-    ) {
-
-       int rc = 0;
-       int regionIdx;
-       int segmentIdx;
-       DMA_Region_t *region;
-       DMA_Segment_t *segment;
-
-       down(&memMap->lock);
-
-       for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
-               region = &memMap->region[regionIdx];
-
-               for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
-                    segmentIdx++) {
-                       segment = &region->segment[segmentIdx];
-
-                       switch (region->memType) {
-                       case DMA_MEM_TYPE_VMALLOC:
-                               {
-                                       printk(KERN_ERR
-                                              "%s: vmalloc'd pages are not yet supported\n",
-                                              __func__);
-                                       rc = -EINVAL;
-                                       goto out;
-                               }
-
-                       case DMA_MEM_TYPE_KMALLOC:
-                               {
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
-                                       dma_unmap_single(NULL,
-                                                        segment->physAddr,
-                                                        segment->numBytes,
-                                                        memMap->dir);
-#endif
-                                       break;
-                               }
-
-                       case DMA_MEM_TYPE_DMA:
-                               {
-                                       dma_sync_single_for_cpu(NULL,
-                                                               segment->
-                                                               physAddr,
-                                                               segment->
-                                                               numBytes,
-                                                               memMap->dir);
-                                       break;
-                               }
-
-                       case DMA_MEM_TYPE_USER:
-                               {
-                                       /* Nothing to do here. */
-
-                                       break;
-                               }
-
-                       default:
-                               {
-                                       printk(KERN_ERR
-                                              "%s: Unsupported memory type: %d\n",
-                                              __func__, region->memType);
-                                       rc = -EINVAL;
-                                       goto out;
-                               }
-                       }
-
-                       segment->virtAddr = NULL;
-                       segment->physAddr = 0;
-                       segment->numBytes = 0;
-               }
-
-               if (region->numLockedPages > 0) {
-                       int pageIdx;
-
-                       /* Some user pages were locked. We need to go and unlock them now. */
-
-                       for (pageIdx = 0; pageIdx < region->numLockedPages;
-                            pageIdx++) {
-                               struct page *page =
-                                   region->lockedPages[pageIdx];
-
-                               if (memMap->dir == DMA_FROM_DEVICE) {
-                                       SetPageDirty(page);
-                               }
-                               page_cache_release(page);
-                       }
-                       kfree(region->lockedPages);
-                       region->numLockedPages = 0;
-                       region->lockedPages = NULL;
-               }
-
-               region->memType = DMA_MEM_TYPE_NONE;
-               region->virtAddr = NULL;
-               region->numBytes = 0;
-               region->numSegmentsUsed = 0;
-       }
-       memMap->userTask = NULL;
-       memMap->numRegionsUsed = 0;
-       memMap->inUse = 0;
-
-out:
-       up(&memMap->lock);
-
-       return rc;
-}
-
-EXPORT_SYMBOL(dma_unmap);
index 1f2c5319c05656294170621f0653778115441e25..72543781207b2f2a70e5bfbe5d84f44bec3239a7 100644 (file)
 /* ---- Include Files ---------------------------------------------------- */
 
 #include <linux/kernel.h>
-#include <linux/wait.h>
 #include <linux/semaphore.h>
 #include <csp/dmacHw.h>
 #include <mach/timer.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
 
 /* ---- Constants and Types ---------------------------------------------- */
 
@@ -111,78 +105,6 @@ typedef struct {
 
 } DMA_DescriptorRing_t;
 
-/****************************************************************************
-*
-*   The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup
-*   DMA chains from a variety of memory sources.
-*
-*****************************************************************************/
-
-#define DMA_MEM_MAP_MIN_SIZE    4096   /* Pages less than this size are better */
-                                       /* off not being DMA'd. */
-
-typedef enum {
-       DMA_MEM_TYPE_NONE,      /* Not a valid setting */
-       DMA_MEM_TYPE_VMALLOC,   /* Memory came from vmalloc call */
-       DMA_MEM_TYPE_KMALLOC,   /* Memory came from kmalloc call */
-       DMA_MEM_TYPE_DMA,       /* Memory came from dma_alloc_xxx call */
-       DMA_MEM_TYPE_USER,      /* Memory came from user space. */
-
-} DMA_MemType_t;
-
-/* A segment represents a physically and virtually contiguous chunk of memory. */
-/* i.e. each segment can be DMA'd */
-/* A user of the DMA code will add memory regions. Each region may need to be */
-/* represented by one or more segments. */
-
-typedef struct {
-       void *virtAddr;         /* Virtual address used for this segment */
-       dma_addr_t physAddr;    /* Physical address this segment maps to */
-       size_t numBytes;        /* Size of the segment, in bytes */
-
-} DMA_Segment_t;
-
-/* A region represents a virtually contiguous chunk of memory, which may be */
-/* made up of multiple segments. */
-
-typedef struct {
-       DMA_MemType_t memType;
-       void *virtAddr;
-       size_t numBytes;
-
-       /* Each region (virtually contiguous) consists of one or more segments. Each */
-       /* segment is virtually and physically contiguous. */
-
-       int numSegmentsUsed;
-       int numSegmentsAllocated;
-       DMA_Segment_t *segment;
-
-       /* When a region corresponds to user memory, we need to lock all of the pages */
-       /* down before we can figure out the physical addresses. The lockedPage array contains */
-       /* the pages that were locked, and which subsequently need to be unlocked once the */
-       /* memory is unmapped. */
-
-       unsigned numLockedPages;
-       struct page **lockedPages;
-
-} DMA_Region_t;
-
-typedef struct {
-       int inUse;              /* Is this mapping currently being used? */
-       struct semaphore lock;  /* Acquired when using this structure */
-       enum dma_data_direction dir;    /* Direction this transfer is intended for */
-
-       /* In the event that we're mapping user memory, we need to know which task */
-       /* the memory is for, so that we can obtain the correct mm locks. */
-
-       struct task_struct *userTask;
-
-       int numRegionsUsed;
-       int numRegionsAllocated;
-       DMA_Region_t *region;
-
-} DMA_MemMap_t;
-
 /****************************************************************************
 *
 *   The DMA_DeviceAttribute_t contains information which describes a
@@ -568,124 +490,6 @@ int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */
                                     size_t numBytes    /* Number of bytes in each destination buffer */
     );
 
-/****************************************************************************/
-/**
-*   Initializes a DMA_MemMap_t data structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap      /* Stores state information about the map */
-    );
-
-/****************************************************************************/
-/**
-*   Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap      /* Stores state information about the map */
-    );
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and categorizes it.
-*
-*   @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr);
-
-/****************************************************************************/
-/**
-*   Sets the process (aka userTask) associated with a mem map. This is
-*   required if user-mode segments will be added to the mapping.
-*/
-/****************************************************************************/
-
-static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap,
-                                            struct task_struct *task)
-{
-       memMap->userTask = task;
-}
-
-/****************************************************************************/
-/**
-*   Looks at a memory address and determines if we support DMA'ing to/from
-*   that type of memory.
-*
-*   @return boolean -
-*               return value != 0 means dma supported
-*               return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr);
-
-/****************************************************************************/
-/**
-*   Initializes a memory map for use. Since this function acquires a
-*   sempaphore within the memory map, it is VERY important that dma_unmap
-*   be called when you're finished using the map.
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap,        /* Stores state information about the map */
-                 enum dma_data_direction dir   /* Direction that the mapping will be going */
-    );
-
-/****************************************************************************/
-/**
-*   Adds a segment of memory to a memory map.
-*
-*   @return     0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap,   /* Stores state information about the map */
-                      void *mem,       /* Virtual address that we want to get a map of */
-                      size_t numBytes  /* Number of bytes being mapped */
-    );
-
-/****************************************************************************/
-/**
-*   Creates a descriptor ring from a memory mapping.
-*
-*   @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev,   /* DMA device (where the ring is stored) */
-                                  DMA_MemMap_t *memMap,        /* Memory map that will be used */
-                                  dma_addr_t devPhysAddr       /* Physical address of device */
-    );
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap,  /* Stores state information about the map */
-               void *addr,     /* Virtual address that we want to get a map of */
-               size_t count,   /* Number of bytes being mapped */
-               enum dma_data_direction dir     /* Direction that the mapping will be going */
-    );
-
-/****************************************************************************/
-/**
-*   Maps in a memory region such that it can be used for performing a DMA.
-*
-*   @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap,    /* Stores state information about the map */
-             int dirtied       /* non-zero if any of the pages were modified */
-    );
-
 /****************************************************************************/
 /**
 *   Initiates a transfer when the descriptors have already been setup.
index 6b22b543a83f0f6f393a2fbf9e23324c2bc7b9d1..d5088900af6c89a41eae892fb80be4d88fc8a73d 100644 (file)
@@ -44,7 +44,7 @@
 #include <mach/aemif.h>
 #include <mach/spi.h>
 
-#define DA850_EVM_PHY_ID               "0:00"
+#define DA850_EVM_PHY_ID               "davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN               GPIO_TO_PIN(2, 15)
 
index 346e1de2f5a857ac16fb9c2ecb5b85af9c4537d9..849311d3cb7c184f59adb7df85fe36876b4e3cb3 100644 (file)
@@ -54,7 +54,7 @@ static inline int have_tvp7002(void)
        return 0;
 }
 
-#define DM365_EVM_PHY_ID               "0:01"
+#define DM365_EVM_PHY_ID               "davinci_mdio-0:01"
 /*
  * A MAX-II CPLD is used for various board control functions.
  */
index a64b49cfedcad5f495ac2e360751e045036ca2cd..1247ecdcf752d57c7d6aa476a699b34c158a4324 100644 (file)
@@ -40,7 +40,7 @@
 #include <mach/usb.h>
 #include <mach/aemif.h>
 
-#define DM644X_EVM_PHY_ID              "0:01"
+#define DM644X_EVM_PHY_ID              "davinci_mdio-0:01"
 #define LXT971_PHY_ID  (0x001378e2)
 #define LXT971_PHY_MASK        (0xfffffff0)
 
index 64017558860bd0c127a9c5178d8aacd47229a62f..872ac69fa0490af84501ac13d73a792bf5f6aea7 100644 (file)
@@ -736,7 +736,7 @@ static struct davinci_uart_config uart_config __initdata = {
        .enabled_uarts = (1 << 0),
 };
 
-#define DM646X_EVM_PHY_ID              "0:01"
+#define DM646X_EVM_PHY_ID              "davinci_mdio-0:01"
 /*
  * The following EDMA channels/slots are not being used by drivers (for
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
index 6c4a16415d476f58fbdadb88308cb803a9019956..8d34f513d41507b7bf2562739d8f824cc1e40c35 100644 (file)
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 
-#define NEUROS_OSD2_PHY_ID             "0:01"
+#define NEUROS_OSD2_PHY_ID             "davinci_mdio-0:01"
 #define LXT971_PHY_ID                  0x001378e2
 #define LXT971_PHY_MASK                        0xfffffff0
 
index e7c0c7c534937132929cf4cdd760fb4c63f4118b..45e815760a27fd0cfc0f2965590eb90a1779b240 100644 (file)
@@ -21,7 +21,7 @@
 #include <mach/da8xx.h>
 #include <mach/mux.h>
 
-#define HAWKBOARD_PHY_ID               "0:07"
+#define HAWKBOARD_PHY_ID               "davinci_mdio-0:07"
 #define DA850_HAWK_MMCSD_CD_PIN                GPIO_TO_PIN(3, 12)
 #define DA850_HAWK_MMCSD_WP_PIN                GPIO_TO_PIN(3, 13)
 
index 0b136a831c59563100312646d0b1b1324e8c4e20..31da3c5b2ba37f4934c09fa50bc2aa1cad775631 100644 (file)
@@ -42,7 +42,7 @@
 #include <mach/mux.h>
 #include <mach/usb.h>
 
-#define SFFSDR_PHY_ID          "0:01"
+#define SFFSDR_PHY_ID          "davinci_mdio-0:01"
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
        /* U-Boot Environment: Block 0
         * UBL:                Block 1
index 0ed7fdb64efbf5211a8e5b8fc19bc5cf56fc3b97..992c4c4101856db5f8f503cdd34aa5fbd5196806 100644 (file)
@@ -153,34 +153,6 @@ static struct clk pll1_sysclk3 = {
        .div_reg        = PLLDIV3,
 };
 
-static struct clk pll1_sysclk4 = {
-       .name           = "pll1_sysclk4",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV4,
-};
-
-static struct clk pll1_sysclk5 = {
-       .name           = "pll1_sysclk5",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV5,
-};
-
-static struct clk pll1_sysclk6 = {
-       .name           = "pll0_sysclk6",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV6,
-};
-
-static struct clk pll1_sysclk7 = {
-       .name           = "pll1_sysclk7",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV7,
-};
-
 static struct clk i2c0_clk = {
        .name           = "i2c0",
        .parent         = &pll0_aux_clk,
@@ -397,10 +369,6 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "pll1_aux",     &pll1_aux_clk),
        CLK(NULL,               "pll1_sysclk2", &pll1_sysclk2),
        CLK(NULL,               "pll1_sysclk3", &pll1_sysclk3),
-       CLK(NULL,               "pll1_sysclk4", &pll1_sysclk4),
-       CLK(NULL,               "pll1_sysclk5", &pll1_sysclk5),
-       CLK(NULL,               "pll1_sysclk6", &pll1_sysclk6),
-       CLK(NULL,               "pll1_sysclk7", &pll1_sysclk7),
        CLK("i2c_davinci.1",    NULL,           &i2c0_clk),
        CLK(NULL,               "timer0",       &timerp64_0_clk),
        CLK("watchdog",         NULL,           &timerp64_1_clk),
index dd1429ae6405e3e3c7f48280df66b6992d916b31..bda7aca04ca0dbc504643b30f5b2082bee58420c 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach/arch.h>
 #include <linux/irq.h>
 #include <plat/time.h>
+#include <plat/ehci-orion.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
 #include "common.h"
@@ -71,7 +72,7 @@ void __init dove_map_io(void)
  ****************************************************************************/
 void __init dove_ehci0_init(void)
 {
-       orion_ehci_init(DOVE_USB0_PHYS_BASE, IRQ_DOVE_USB0);
+       orion_ehci_init(DOVE_USB0_PHYS_BASE, IRQ_DOVE_USB0, EHCI_PHY_NA);
 }
 
 /*****************************************************************************
index 46d4d876e6fb853e9cf051ed3f88edc852c8a57d..e82c642fa53cd49ac88afc412b4194319fc3303f 100644 (file)
@@ -37,7 +37,7 @@
  */
 struct ep93xx_dma_data {
        int                             port;
-       enum dma_data_direction         direction;
+       enum dma_transfer_direction     direction;
        const char                      *name;
 };
 
@@ -80,14 +80,14 @@ static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
  * channel supports given DMA direction. Only M2P channels have such
  * limitation, for M2M channels the direction is configurable.
  */
-static inline enum dma_data_direction
+static inline enum dma_transfer_direction
 ep93xx_dma_chan_direction(struct dma_chan *chan)
 {
        if (!ep93xx_dma_chan_is_m2p(chan))
                return DMA_NONE;
 
        /* even channels are for TX, odd for RX */
-       return (chan->chan_id % 2 == 0) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
 }
 
 #endif /* __ASM_ARCH_DMA_H */
index 03dd4012043eb29a39b7abcf9e0d8bee92c77562..d5fb44f16d317e4796e9c2c08fae5cd16344f4d3 100644 (file)
@@ -32,6 +32,7 @@
 #include <mach/hardware.h>
 #include <mach/fb.h>
 #include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -153,7 +154,6 @@ static struct i2c_board_info vision_i2c_info[] __initdata = {
        }, {
                I2C_BOARD_INFO("pca9539", 0x74),
                .platform_data  = &pca953x_74_gpio_data,
-               .irq            = gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
        }, {
                I2C_BOARD_INFO("pca9539", 0x75),
                .platform_data  = &pca953x_75_gpio_data,
@@ -348,6 +348,8 @@ static void __init vision_init_machine(void)
                                "pca9539:74"))
                pr_warn("cannot request interrupt gpio for pca9539:74\n");
 
+       vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
+
        ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
                                ARRAY_SIZE(vision_i2c_info));
        ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
index a5823a7f249e0b06f1e1ba3b7a43ec0a7e95aaec..13312ccb2d9366f30e1295d403e0212c4f6b3e24 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "common.h"
 
+#ifdef CONFIG_PM_SLEEP
 static struct sleep_save exynos4210_clock_save[] = {
        SAVE_ITEM(S5P_CLKSRC_IMAGE),
        SAVE_ITEM(S5P_CLKSRC_LCD1),
@@ -42,6 +43,7 @@ static struct sleep_save exynos4210_clock_save[] = {
        SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
        SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210),
 };
+#endif
 
 static struct clksrc_clk *sysclks[] = {
        /* nothing here yet */
index 26a668b0d101becc1ea09ab11c6edc7dc23719e1..48af28566fa168703083ed900c7fc8a2a9701998 100644 (file)
 
 #include "common.h"
 
+#ifdef CONFIG_PM_SLEEP
 static struct sleep_save exynos4212_clock_save[] = {
        SAVE_ITEM(S5P_CLKSRC_IMAGE),
        SAVE_ITEM(S5P_CLKDIV_IMAGE),
        SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212),
        SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212),
 };
+#endif
 
 static struct clk *clk_src_mpll_user_list[] = {
        [0] = &clk_fin_mpll,
index 5a8c42e90005c6fb3a92599671afefed6909fda3..187287aa57ab9154fbe7808bbd26ec895348ddd8 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "common.h"
 
+#ifdef CONFIG_PM_SLEEP
 static struct sleep_save exynos4_clock_save[] = {
        SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
        SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
@@ -93,6 +94,7 @@ static struct sleep_save exynos4_clock_save[] = {
        SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
        SAVE_ITEM(S5P_CLKGATE_IP_CPU),
 };
+#endif
 
 struct clk clk_sclk_hdmi27m = {
        .name           = "sclk_hdmi27m",
index 3cdeb3647542592a4a62f98e0c6b647da358b0d4..5364d4bfa8bc79efe6d51b27ff361811d98b8227 100644 (file)
@@ -36,6 +36,8 @@ pen:  ldr     r7, [r6]
         * should now contain the SVC stack for this core
         */
        b       secondary_startup
+ENDPROC(exynos4_secondary_startup)
 
+       .align 2
 1:     .long   .
        .long   pen_release
index da70e7e3993740e88f1bb473bfc593d8f809b287..dd1ad55524c97e0d28f270e93e10f00dab7327b8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 
 #include <mach/regs-pmu.h>
 
index 85fa02767d67d7acc4cbed6a0b05dea0998060d0..e6b02fdf1b090ea75f7c5b9c2f14d13fc4c4ebcb 100644 (file)
 #include <linux/serial_core.h>
 
 #include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
 #include <mach/map.h>
 
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
-#include <plat/exynos4.h>
+
+#include "common.h"
 
 /*
  * The following lookup table is used to override device names when devices
@@ -60,7 +62,7 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
 
 static void __init exynos4210_dt_map_io(void)
 {
-       s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+       exynos_init_io(NULL, 0);
        s3c24xx_init_clocks(24000000);
 }
 
@@ -79,7 +81,9 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
        .init_irq       = exynos4_init_irq,
        .map_io         = exynos4210_dt_map_io,
+       .handle_irq     = gic_handle_irq,
        .init_machine   = exynos4210_dt_machine_init,
        .timer          = &exynos4_timer,
        .dt_compat      = exynos4210_dt_compat,
+       .restart        = exynos4_restart,
 MACHINE_END
index b895ec0311057698dab4883c4d77099971af7a14..435261f83f46d5d8ada440e17bdc65a0b1e19a1f 100644 (file)
@@ -220,14 +220,14 @@ static struct s3c_fb_pd_win nuri_fb_win0 = {
                .lower_margin   = 1,
                .hsync_len      = 48,
                .vsync_len      = 3,
-               .xres           = 1280,
-               .yres           = 800,
+               .xres           = 1024,
+               .yres           = 600,
                .refresh        = 60,
        },
        .max_bpp        = 24,
        .default_bpp    = 16,
-       .virtual_x      = 1280,
-       .virtual_y      = 800,
+       .virtual_x      = 1024,
+       .virtual_y      = 2 * 600,
 };
 
 static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
index 2b11e046d3919dc393a2875b528abf34e3664d85..0679b8ad2d1e1a4263521f805d7afd246334a037 100644 (file)
@@ -597,7 +597,8 @@ static struct s3c_fb_pd_win origen_fb_win0 = {
 static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
        .win[0]         = &origen_fb_win0,
        .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
+                               VIDCON1_INV_VCLK,
        .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
 };
 
index 37ac93e8d6d9ef44940dabb5f1d916301012ee54..0fc65ffde8ff7526f0f9362c8e18e3e27e3c6539 100644 (file)
@@ -910,7 +910,7 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
                .bus_type       = FIMC_MIPI_CSI2,
                .board_info     = &m5mols_board_info,
                .i2c_bus_num    = 0,
-               .clk_frequency  = 21600000UL,
+               .clk_frequency  = 24000000UL,
                .csi_data_align = 32,
        },
 };
index 60bc45e3e7099045560f71bf4aaf29664341e488..0f2035a1eb6e5f31cf7bdbd16270af5efd4abee4 100644 (file)
@@ -23,8 +23,8 @@
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/gic.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
-#include <asm/unified.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-clock.h>
@@ -137,7 +137,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
        while (time_before(jiffies, timeout)) {
                smp_rmb();
 
-               __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+               __raw_writel(virt_to_phys(exynos4_secondary_startup),
                        CPU1_BOOT_REG);
                gic_raise_softirq(cpumask_of(cpu), 1);
 
@@ -192,6 +192,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
         * until it receives a soft interrupt, and then the
         * secondary CPU branches to this address.
         */
-       __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+       __raw_writel(virt_to_phys(exynos4_secondary_startup),
                        CPU1_BOOT_REG);
 }
index a4f61a43c7bae9a9f3141ef6ecd396c0ee3ed7c5..e190130517727ea9bcdfb9541496922093a9d672 100644 (file)
@@ -206,7 +206,7 @@ static void exynos4_pm_prepare(void)
 
 }
 
-static int exynos4_pm_add(struct device *dev)
+static int exynos4_pm_add(struct device *dev, struct subsys_interface *sif)
 {
        pm_cpu_prep = exynos4_pm_prepare;
        pm_cpu_sleep = exynos4_cpu_suspend;
@@ -384,7 +384,9 @@ static void exynos4_pm_resume(void)
 
        exynos4_restore_pll();
 
+#ifdef CONFIG_SMP
        scu_enable(S5P_VA_SCU);
+#endif
 
 #ifdef CONFIG_CACHE_L2X0
        s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
index 804c4a55f8038c75cbf0731168ee6d0d36de004a..8394d512a40227e0d5526fd6cc731137f1d108d6 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
-#include <asm/unified.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/timer-sp.h>
@@ -73,10 +73,8 @@ 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));
+       writel(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),
                          HB_JUMP_TABLE_PHYS(cpu) + 15);
index 0e6de366c6482026157656ad3ea9f8866299ba50..4defb97bbfc866400fe57fe4c5178a778c30a91f 100644 (file)
@@ -22,6 +22,18 @@ config ARCH_MX25
 config MACH_MX27
        bool
 
+config ARCH_MX5
+       bool
+
+config ARCH_MX50
+       bool
+
+config ARCH_MX51
+       bool
+
+config ARCH_MX53
+       bool
+
 config SOC_IMX1
        bool
        select ARCH_MX1
@@ -73,6 +85,31 @@ config SOC_IMX35
        select MXC_AVIC
        select SMP_ON_UP if SMP
 
+config SOC_IMX5
+       select CPU_V7
+       select MXC_TZIC
+       select ARCH_MXC_IOMUX_V3
+       select ARCH_MXC_AUDMUX_V2
+       select ARCH_HAS_CPUFREQ
+       select ARCH_MX5
+       bool
+
+config SOC_IMX50
+       bool
+       select SOC_IMX5
+       select ARCH_MX50
+
+config SOC_IMX51
+       bool
+       select SOC_IMX5
+       select ARCH_MX5
+       select ARCH_MX51
+
+config SOC_IMX53
+       bool
+       select SOC_IMX5
+       select ARCH_MX5
+       select ARCH_MX53
 
 if ARCH_IMX_V4_V5
 
@@ -592,6 +629,207 @@ config MACH_VPR200
          Include support for VPR200 platform. This includes specific
          configurations for the board and its peripherals.
 
+comment "i.MX5 platforms:"
+
+config MACH_MX50_RDP
+       bool "Support MX50 reference design platform"
+       depends on BROKEN
+       select SOC_IMX50
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       help
+         Include support for MX50 reference design platform (RDP) board. This
+         includes specific configurations for the board and its peripherals.
+
+comment "i.MX51 machines:"
+
+config MACH_IMX51_DT
+       bool "Support i.MX51 platforms from device tree"
+       select SOC_IMX51
+       select USE_OF
+       select MACH_MX51_BABBAGE
+       help
+         Include support for Freescale i.MX51 based platforms
+         using the device tree for discovery
+
+config MACH_MX51_BABBAGE
+       bool "Support MX51 BABBAGE platforms"
+       select SOC_IMX51
+       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_EHCI
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       help
+         Include support for MX51 Babbage platform, also known as MX51EVK in
+         u-boot. This includes specific configurations for the board and its
+         peripherals.
+
+config MACH_MX51_3DS
+       bool "Support MX51PDK (3DS)"
+       select SOC_IMX51
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_KEYPAD
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       select MXC_DEBUG_BOARD
+       help
+         Include support for MX51PDK (3DS) platform. This includes specific
+         configurations for the board and its peripherals.
+
+config MACH_EUKREA_CPUIMX51
+       bool "Support Eukrea CPUIMX51 module"
+       select SOC_IMX51
+       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_EHCI
+       select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       help
+         Include support for Eukrea CPUIMX51 platform. This includes
+         specific configurations for the module and its peripherals.
+
+choice
+       prompt "Baseboard"
+       depends on MACH_EUKREA_CPUIMX51
+       default MACH_EUKREA_MBIMX51_BASEBOARD
+
+config MACH_EUKREA_MBIMX51_BASEBOARD
+       prompt "Eukrea MBIMX51 development board"
+       bool
+       select IMX_HAVE_PLATFORM_IMX_KEYPAD
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select LEDS_GPIO_REGISTER
+       help
+         This adds board specific devices that can be found on Eukrea's
+         MBIMX51 evaluation board.
+
+endchoice
+
+config MACH_EUKREA_CPUIMX51SD
+       bool "Support Eukrea CPUIMX51SD module"
+       select SOC_IMX51
+       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_EHCI
+       select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       help
+         Include support for Eukrea CPUIMX51SD platform. This includes
+         specific configurations for the module and its peripherals.
+
+choice
+       prompt "Baseboard"
+       depends on MACH_EUKREA_CPUIMX51SD
+       default MACH_EUKREA_MBIMXSD51_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD51_BASEBOARD
+       prompt "Eukrea MBIMXSD development board"
+       bool
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select LEDS_GPIO_REGISTER
+       help
+         This adds board specific devices that can be found on Eukrea's
+         MBIMXSD evaluation board.
+
+endchoice
+
+config MX51_EFIKA_COMMON
+       bool
+       select SOC_IMX51
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_MXC_EHCI
+       select IMX_HAVE_PLATFORM_PATA_IMX
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       select MXC_ULPI if USB_ULPI
+
+config MACH_MX51_EFIKAMX
+       bool "Support MX51 Genesi Efika MX nettop"
+       select LEDS_GPIO_REGISTER
+       select MX51_EFIKA_COMMON
+       help
+         Include support for Genesi Efika MX nettop. This includes specific
+         configurations for the board and its peripherals.
+
+config MACH_MX51_EFIKASB
+       bool "Support MX51 Genesi Efika Smartbook"
+       select LEDS_GPIO_REGISTER
+       select MX51_EFIKA_COMMON
+       help
+         Include support for Genesi Efika Smartbook. This includes specific
+         configurations for the board and its peripherals.
+
+comment "i.MX53 machines:"
+
+config MACH_IMX53_DT
+       bool "Support i.MX53 platforms from device tree"
+       select SOC_IMX53
+       select USE_OF
+       select MACH_MX53_ARD
+       select MACH_MX53_EVK
+       select MACH_MX53_LOCO
+       select MACH_MX53_SMD
+       help
+         Include support for Freescale i.MX53 based platforms
+         using the device tree for discovery
+
+config MACH_MX53_EVK
+       bool "Support MX53 EVK platforms"
+       select SOC_IMX53
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_SPI_IMX
+       select LEDS_GPIO_REGISTER
+       help
+         Include support for MX53 EVK platform. This includes specific
+         configurations for the board and its peripherals.
+
+config MACH_MX53_SMD
+       bool "Support MX53 SMD platforms"
+       select SOC_IMX53
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       help
+         Include support for MX53 SMD platform. This includes specific
+         configurations for the board and its peripherals.
+
+config MACH_MX53_LOCO
+       bool "Support MX53 LOCO platforms"
+       select SOC_IMX53
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_GPIO_KEYS
+       select LEDS_GPIO_REGISTER
+       help
+         Include support for MX53 LOCO platform. This includes specific
+         configurations for the board and its peripherals.
+
+config MACH_MX53_ARD
+       bool "Support MX53 ARD platforms"
+       select SOC_IMX53
+       select IMX_HAVE_PLATFORM_IMX2_WDT
+       select IMX_HAVE_PLATFORM_IMX_I2C
+       select IMX_HAVE_PLATFORM_IMX_UART
+       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+       select IMX_HAVE_PLATFORM_GPIO_KEYS
+       help
+         Include support for MX53 ARD platform. This includes specific
+         configurations for the board and its peripherals.
+
 comment "i.MX6 family:"
 
 config SOC_IMX6Q
index f5920c24f7d7eab486a8a340e4e6b6b785038483..55db9c488f2b408162e4bcca36f44d7cdb444ac0 100644 (file)
@@ -11,6 +11,8 @@ obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
 
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
@@ -75,3 +77,22 @@ obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
 endif
+
+# i.MX5 based machines
+obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
+obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o
+obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o
+obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o
+obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o
+obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += mach-cpuimx51.o
+obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
+obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o
+obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o
+obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
index 5f4d06af491262a6ac6d75d7bcdeaee74684a16b..6dfdbcc83afd7d4fb9e8245dfceed489e0c6970e 100644 (file)
@@ -22,6 +22,18 @@ zreladdr-$(CONFIG_SOC_IMX35) += 0x80008000
 params_phys-$(CONFIG_SOC_IMX35)        := 0x80000100
 initrd_phys-$(CONFIG_SOC_IMX35)        := 0x80800000
 
+zreladdr-$(CONFIG_SOC_IMX50)   += 0x70008000
+params_phys-$(CONFIG_SOC_IMX50)        := 0x70000100
+initrd_phys-$(CONFIG_SOC_IMX50)        := 0x70800000
+
+zreladdr-$(CONFIG_SOC_IMX51)   += 0x90008000
+params_phys-$(CONFIG_SOC_IMX51)        := 0x90000100
+initrd_phys-$(CONFIG_SOC_IMX51)        := 0x90800000
+
+zreladdr-$(CONFIG_SOC_IMX53)   += 0x70008000
+params_phys-$(CONFIG_SOC_IMX53)        := 0x70000100
+initrd_phys-$(CONFIG_SOC_IMX53)        := 0x70800000
+
 zreladdr-$(CONFIG_SOC_IMX6Q)   += 0x10008000
 params_phys-$(CONFIG_SOC_IMX6Q)        := 0x10000100
 initrd_phys-$(CONFIG_SOC_IMX6Q)        := 0x10800000
index 9273c2a24b540a12646c406ac82dedb6c27ca28b..2d88f8b9a454994bee6841cda4828d81286bac5e 100644 (file)
@@ -814,6 +814,16 @@ DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
 DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
 DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
 
+static unsigned long twd_clk_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk twd_clk = {
+       .parent = &arm_clk,
+       .get_rate = twd_clk_get_rate,
+};
+
 static unsigned long pll2_200m_get_rate(struct clk *clk)
 {
        return clk_get_rate(clk->parent) / 2;
@@ -1894,6 +1904,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
        _REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
        _REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+       _REGISTER_CLOCK("smp_twd", NULL, twd_clk),
        _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
        _REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
        _REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
diff --git a/arch/arm/mach-imx/clock-mx51-mx53.c b/arch/arm/mach-imx/clock-mx51-mx53.c
new file mode 100644 (file)
index 0000000..0847050
--- /dev/null
@@ -0,0 +1,1675 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+
+#include <asm/div64.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "crm-regs-imx5.h"
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+
+static struct clk osc_clk;
+static struct clk pll1_main_clk;
+static struct clk pll1_sw_clk;
+static struct clk pll2_sw_clk;
+static struct clk pll3_sw_clk;
+static struct clk mx53_pll4_sw_clk;
+static struct clk lp_apm_clk;
+static struct clk periph_apm_clk;
+static struct clk ahb_clk;
+static struct clk ipg_clk;
+static struct clk usboh3_clk;
+static struct clk emi_fast_clk;
+static struct clk ipu_clk;
+static struct clk mipi_hsc1_clk;
+static struct clk esdhc1_clk;
+static struct clk esdhc2_clk;
+static struct clk esdhc3_mx53_clk;
+
+#define MAX_DPLL_WAIT_TRIES    1000 /* 1000 * udelay(1) = 1ms */
+
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+       u32 max_pre, u32 max_post)
+{
+       if (div >= max_pre * max_post) {
+               *pre = max_pre;
+               *post = max_post;
+       } else if (div >= max_pre) {
+               u32 min_pre, temp_pre, old_err, err;
+               min_pre = DIV_ROUND_UP(div, max_post);
+               old_err = max_pre;
+               for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+                       err = div % temp_pre;
+                       if (err == 0) {
+                               *pre = temp_pre;
+                               break;
+                       }
+                       err = temp_pre - err;
+                       if (err < old_err) {
+                               old_err = err;
+                               *pre = temp_pre;
+                       }
+               }
+               *post = DIV_ROUND_UP(div, *pre);
+       } else {
+               *pre = div;
+               *post = 1;
+       }
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+       u32 reg = __raw_readl(clk->enable_reg);
+
+       reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+       reg |= mode << clk->enable_shift;
+
+       __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_ccgr_enable(struct clk *clk)
+{
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
+       return 0;
+}
+
+static void _clk_ccgr_disable(struct clk *clk)
+{
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
+
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+       return 0;
+}
+
+static void _clk_ccgr_disable_inwait(struct clk *clk)
+{
+       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+                          struct clk *m1, struct clk *m2, struct clk *m3)
+{
+       if (parent == m0)
+               return 0;
+       else if (parent == m1)
+               return 1;
+       else if (parent == m2)
+               return 2;
+       else if (parent == m3)
+               return 3;
+       else
+               BUG();
+
+       return -EINVAL;
+}
+
+static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
+{
+       if (pll == &pll1_main_clk)
+               return MX51_DPLL1_BASE;
+       else if (pll == &pll2_sw_clk)
+               return MX51_DPLL2_BASE;
+       else if (pll == &pll3_sw_clk)
+               return MX51_DPLL3_BASE;
+       else
+               BUG();
+
+       return NULL;
+}
+
+static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
+{
+       if (pll == &pll1_main_clk)
+               return MX53_DPLL1_BASE;
+       else if (pll == &pll2_sw_clk)
+               return MX53_DPLL2_BASE;
+       else if (pll == &pll3_sw_clk)
+               return MX53_DPLL3_BASE;
+       else if (pll == &mx53_pll4_sw_clk)
+               return MX53_DPLL4_BASE;
+       else
+               BUG();
+
+       return NULL;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+       if (cpu_is_mx51())
+               return _mx51_get_pll_base(pll);
+       else
+               return _mx53_get_pll_base(pll);
+}
+
+static unsigned long clk_pll_get_rate(struct clk *clk)
+{
+       long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+       unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+       void __iomem *pllbase;
+       s64 temp;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       pllbase = _get_pll_base(clk);
+
+       dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+       pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+       dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+       if (pll_hfsm == 0) {
+               dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+               dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+               dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+       } else {
+               dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+               dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+               dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+       }
+       pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+       mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+       mfi = (mfi <= 5) ? 5 : mfi;
+       mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+       mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+       /* Sign extend to 32-bits */
+       if (mfn >= 0x04000000) {
+               mfn |= 0xFC000000;
+               mfn_abs = -mfn;
+       }
+
+       ref_clk = 2 * parent_rate;
+       if (dbl != 0)
+               ref_clk *= 2;
+
+       ref_clk /= (pdf + 1);
+       temp = (u64) ref_clk * mfn_abs;
+       do_div(temp, mfd + 1);
+       if (mfn < 0)
+               temp = -temp;
+       temp = (ref_clk * mfi) + temp;
+
+       return temp;
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg;
+       void __iomem *pllbase;
+
+       long mfi, pdf, mfn, mfd = 999999;
+       s64 temp64;
+       unsigned long quad_parent_rate;
+       unsigned long pll_hfsm, dp_ctl;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       pllbase = _get_pll_base(clk);
+
+       quad_parent_rate = 4 * parent_rate;
+       pdf = mfi = -1;
+       while (++pdf < 16 && mfi < 5)
+               mfi = rate * (pdf+1) / quad_parent_rate;
+       if (mfi > 15)
+               return -EINVAL;
+       pdf--;
+
+       temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
+       do_div(temp64, quad_parent_rate/1000000);
+       mfn = (long)temp64;
+
+       dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+       /* use dpdck0_2 */
+       __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+       pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+       if (pll_hfsm == 0) {
+               reg = mfi << 4 | pdf;
+               __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+               __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+               __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+       } else {
+               reg = mfi << 4 | pdf;
+               __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+               __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+               __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+       }
+
+       return 0;
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+       u32 reg;
+       void __iomem *pllbase;
+       int i = 0;
+
+       pllbase = _get_pll_base(clk);
+       reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+       if (reg & MXC_PLL_DP_CTL_UPEN)
+               return 0;
+
+       reg |= MXC_PLL_DP_CTL_UPEN;
+       __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+       /* Wait for lock */
+       do {
+               reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+               if (reg & MXC_PLL_DP_CTL_LRF)
+                       break;
+
+               udelay(1);
+       } while (++i < MAX_DPLL_WAIT_TRIES);
+
+       if (i == MAX_DPLL_WAIT_TRIES) {
+               pr_err("MX5: pll locking failed\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+       u32 reg;
+       void __iomem *pllbase;
+
+       pllbase = _get_pll_base(clk);
+       reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+       __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, step;
+
+       reg = __raw_readl(MXC_CCM_CCSR);
+
+       /* When switching from pll_main_clk to a bypass clock, first select a
+        * multiplexed clock in 'step_sel', then shift the glitchless mux
+        * 'pll1_sw_clk_sel'.
+        *
+        * When switching back, do it in reverse order
+        */
+       if (parent == &pll1_main_clk) {
+               /* Switch to pll1_main_clk */
+               reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+               __raw_writel(reg, MXC_CCM_CCSR);
+               /* step_clk mux switched to lp_apm, to save power. */
+               reg = __raw_readl(MXC_CCM_CCSR);
+               reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+               reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
+                               MXC_CCM_CCSR_STEP_SEL_OFFSET);
+       } else {
+               if (parent == &lp_apm_clk) {
+                       step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
+               } else  if (parent == &pll2_sw_clk) {
+                       step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
+               } else  if (parent == &pll3_sw_clk) {
+                       step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
+               } else
+                       return -EINVAL;
+
+               reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+               reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+
+               __raw_writel(reg, MXC_CCM_CCSR);
+               /* Switch to step_clk */
+               reg = __raw_readl(MXC_CCM_CCSR);
+               reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+       }
+       __raw_writel(reg, MXC_CCM_CCSR);
+       return 0;
+}
+
+static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       reg = __raw_readl(MXC_CCM_CCSR);
+
+       if (clk->parent == &pll2_sw_clk) {
+               div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+                      MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+       } else if (clk->parent == &pll3_sw_clk) {
+               div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+                      MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+       } else
+               div = 1;
+       return parent_rate / div;
+}
+
+static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CCSR);
+
+       if (parent == &pll2_sw_clk)
+               reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+       else
+               reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+
+       __raw_writel(reg, MXC_CCM_CCSR);
+       return 0;
+}
+
+static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       if (parent == &osc_clk)
+               reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+       else
+               return -EINVAL;
+
+       __raw_writel(reg, MXC_CCM_CCSR);
+
+       return 0;
+}
+
+static unsigned long clk_cpu_get_rate(struct clk *clk)
+{
+       u32 cacrr, div;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+       cacrr = __raw_readl(MXC_CCM_CACRR);
+       div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+
+       return parent_rate / div;
+}
+
+static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, cpu_podf;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+       cpu_podf = parent_rate / rate - 1;
+       /* use post divider to change freq */
+       reg = __raw_readl(MXC_CCM_CACRR);
+       reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
+       reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CACRR);
+
+       return 0;
+}
+
+static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+       int i = 0;
+
+       mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+
+       reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
+       reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCMR);
+
+       /* Wait for lock */
+       do {
+               reg = __raw_readl(MXC_CCM_CDHIPR);
+               if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
+                       break;
+
+               udelay(1);
+       } while (++i < MAX_DPLL_WAIT_TRIES);
+
+       if (i == MAX_DPLL_WAIT_TRIES) {
+               pr_err("MX5: Set parent for periph_apm clock failed\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+
+       if (parent == &pll2_sw_clk)
+               reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+       else if (parent == &periph_apm_clk)
+               reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+       else
+               return -EINVAL;
+
+       __raw_writel(reg, MXC_CCM_CBCDR);
+
+       return 0;
+}
+
+static struct clk main_bus_clk = {
+       .parent = &pll2_sw_clk,
+       .set_parent = _clk_main_bus_set_parent,
+};
+
+static unsigned long clk_ahb_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+              MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+       return parent_rate / div;
+}
+
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       unsigned long parent_rate;
+       int i = 0;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div > 8 || div < 1 || ((parent_rate / div) != rate))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCDR);
+
+       /* Wait for lock */
+       do {
+               reg = __raw_readl(MXC_CCM_CDHIPR);
+               if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
+                       break;
+
+               udelay(1);
+       } while (++i < MAX_DPLL_WAIT_TRIES);
+
+       if (i == MAX_DPLL_WAIT_TRIES) {
+               pr_err("MX5: clk_ahb_set_rate failed\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div > 8)
+               div = 8;
+       else if (div == 0)
+               div++;
+       return parent_rate / div;
+}
+
+
+static int _clk_max_enable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_enable(clk);
+
+       /* Handshake with MAX when LPM is entered. */
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       if (cpu_is_mx51())
+               reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       else if (cpu_is_mx53())
+               reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+
+       return 0;
+}
+
+static void _clk_max_disable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_disable_inwait(clk);
+
+       /* No Handshake with MAX when LPM is entered as its disabled. */
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       if (cpu_is_mx51())
+               reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       else if (cpu_is_mx53())
+               reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static unsigned long clk_ipg_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+              MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+       return parent_rate / div;
+}
+
+static unsigned long clk_ipg_per_get_rate(struct clk *clk)
+{
+       u32 reg, prediv1, prediv2, podf;
+       unsigned long parent_rate;
+
+       parent_rate = clk_get_rate(clk->parent);
+
+       if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+               /* the main_bus_clk is the one before the DVFS engine */
+               reg = __raw_readl(MXC_CCM_CBCDR);
+               prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
+                          MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
+               prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
+                          MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
+               podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
+                       MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
+               return parent_rate / (prediv1 * prediv2 * podf);
+       } else if (clk->parent == &ipg_clk)
+               return parent_rate;
+       else
+               BUG();
+}
+
+static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CBCMR);
+
+       reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+       reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+
+       if (parent == &ipg_clk)
+               reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+       else if (parent == &lp_apm_clk)
+               reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+       else if (parent != &main_bus_clk)
+               return -EINVAL;
+
+       __raw_writel(reg, MXC_CCM_CBCMR);
+
+       return 0;
+}
+
+#define clk_nfc_set_parent     NULL
+
+static unsigned long clk_nfc_get_rate(struct clk *clk)
+{
+       unsigned long rate;
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+              MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+       rate = clk_get_rate(clk->parent) / div;
+       WARN_ON(rate == 0);
+       return rate;
+}
+
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+
+       if (!rate)
+               return -EINVAL;
+
+       div = parent_rate / rate;
+
+       if (parent_rate % rate)
+               div++;
+
+       if (div > 8)
+               return -EINVAL;
+
+       return parent_rate / div;
+
+}
+
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+
+       div = clk_get_rate(clk->parent) / rate;
+       if (div == 0)
+               div++;
+       if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCDR);
+
+       while (__raw_readl(MXC_CCM_CDHIPR) &
+                       MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+       }
+
+       return 0;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+       return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+       return external_low_reference;
+}
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+       return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+       return ckih2_reference;
+}
+
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+              MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
+{
+       unsigned long rate;
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
+               MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
+       rate = clk_get_rate(clk->parent) / div;
+
+       return rate;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+       .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+       .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+       .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+       .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk pll1_main_clk = {
+       .parent = &osc_clk,
+       .get_rate = clk_pll_get_rate,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+/* Clock tree block diagram (WIP):
+ *     CCM: Clock Controller Module
+ *
+ * PLL output -> |
+ *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
+ * PLL bypass -> |
+ *
+ */
+
+/* PLL1 SW supplies to ARM core */
+static struct clk pll1_sw_clk = {
+       .parent = &pll1_main_clk,
+       .set_parent = _clk_pll1_sw_set_parent,
+       .get_rate = clk_pll1_sw_get_rate,
+};
+
+/* PLL2 SW supplies to AXI/AHB/IP buses */
+static struct clk pll2_sw_clk = {
+       .parent = &osc_clk,
+       .get_rate = clk_pll_get_rate,
+       .set_rate = _clk_pll_set_rate,
+       .set_parent = _clk_pll2_sw_set_parent,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
+static struct clk pll3_sw_clk = {
+       .parent = &osc_clk,
+       .set_rate = _clk_pll_set_rate,
+       .get_rate = clk_pll_get_rate,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
+static struct clk mx53_pll4_sw_clk = {
+       .parent = &osc_clk,
+       .set_rate = _clk_pll_set_rate,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+/* Low-power Audio Playback Mode clock */
+static struct clk lp_apm_clk = {
+       .parent = &osc_clk,
+       .set_parent = _clk_lp_apm_set_parent,
+};
+
+static struct clk periph_apm_clk = {
+       .parent = &pll1_sw_clk,
+       .set_parent = _clk_periph_apm_set_parent,
+};
+
+static struct clk cpu_clk = {
+       .parent = &pll1_sw_clk,
+       .get_rate = clk_cpu_get_rate,
+       .set_rate = clk_cpu_set_rate,
+};
+
+static struct clk ahb_clk = {
+       .parent = &main_bus_clk,
+       .get_rate = clk_ahb_get_rate,
+       .set_rate = _clk_ahb_set_rate,
+       .round_rate = _clk_ahb_round_rate,
+};
+
+static struct clk iim_clk = {
+       .parent = &ipg_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+};
+
+/* Main IP interface clock for access to registers */
+static struct clk ipg_clk = {
+       .parent = &ahb_clk,
+       .get_rate = clk_ipg_get_rate,
+};
+
+static struct clk ipg_perclk = {
+       .parent = &lp_apm_clk,
+       .get_rate = clk_ipg_per_get_rate,
+       .set_parent = _clk_ipg_per_set_parent,
+};
+
+static struct clk ahb_max_clk = {
+       .parent = &ahb_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+       .enable = _clk_max_enable,
+       .disable = _clk_max_disable,
+};
+
+static struct clk aips_tz1_clk = {
+       .parent = &ahb_clk,
+       .secondary = &ahb_max_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk aips_tz2_clk = {
+       .parent = &ahb_clk,
+       .secondary = &ahb_max_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk gpc_dvfs_clk = {
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable,
+};
+
+static struct clk gpt_32k_clk = {
+       .id = 0,
+       .parent = &ckil_clk,
+};
+
+static struct clk dummy_clk = {
+       .id = 0,
+};
+
+static struct clk emi_slow_clk = {
+       .parent = &pll2_sw_clk,
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable_inwait,
+       .get_rate = clk_emi_slow_get_rate,
+};
+
+static int clk_ipu_enable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_enable(clk);
+
+       /* Enable handshake with IPU when certain clock rates are changed */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       /* Enable handshake with IPU when LPM is entered */
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+
+       return 0;
+}
+
+static void clk_ipu_disable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_disable(clk);
+
+       /* Disable handshake with IPU whe dividers are changed */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg |= MXC_CCM_CCDR_IPU_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       /* Disable handshake with IPU when LPM is entered */
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk ahbmux1_clk = {
+       .parent = &ahb_clk,
+       .secondary = &ahb_max_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk ipu_sec_clk = {
+       .parent = &emi_fast_clk,
+       .secondary = &ahbmux1_clk,
+};
+
+static struct clk ddr_hf_clk = {
+       .parent = &pll1_sw_clk,
+       .get_rate = _clk_ddr_hf_get_rate,
+};
+
+static struct clk ddr_clk = {
+       .parent = &ddr_hf_clk,
+};
+
+/* clock definitions for MIPI HSC unit which has been removed
+ * from documentation, but not from hardware
+ */
+static int _clk_hsc_enable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_enable(clk);
+       /* Handshake with IPU when certain clock rates are changed. */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+
+       return 0;
+}
+
+static void _clk_hsc_disable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_disable(clk);
+       /* No handshake with HSC as its not enabled. */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk mipi_hsp_clk = {
+       .parent = &ipu_clk,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+       .enable = _clk_hsc_enable,
+       .disable = _clk_hsc_disable,
+       .secondary = &mipi_hsc1_clk,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)  \
+       static struct clk name = {                      \
+               .id             = i,                    \
+               .enable_reg     = er,                   \
+               .enable_shift   = es,                   \
+               .get_rate       = pfx##_get_rate,       \
+               .set_rate       = pfx##_set_rate,       \
+               .round_rate     = pfx##_round_rate,     \
+               .set_parent     = pfx##_set_parent,     \
+               .enable         = _clk_ccgr_enable,     \
+               .disable        = _clk_ccgr_disable,    \
+               .parent         = p,                    \
+               .secondary      = s,                    \
+       }
+
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)   \
+       static struct clk name = {                      \
+               .id             = i,                    \
+               .enable_reg     = er,                   \
+               .enable_shift   = es,                   \
+               .get_rate       = pfx##_get_rate,       \
+               .set_rate       = pfx##_set_rate,       \
+               .set_parent     = pfx##_set_parent,     \
+               .enable         = _clk_max_enable,      \
+               .disable        = _clk_max_disable,     \
+               .parent         = p,                    \
+               .secondary      = s,                    \
+       }
+
+#define CLK_GET_RATE(name, nr, bitsname)                               \
+static unsigned long clk_##name##_get_rate(struct clk *clk)            \
+{                                                                      \
+       u32 reg, pred, podf;                                            \
+                                                                       \
+       reg = __raw_readl(MXC_CCM_CSCDR##nr);                           \
+       pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)   \
+               >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;    \
+       podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)   \
+               >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;    \
+                                                                       \
+       return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),             \
+                       (pred + 1) * (podf + 1));                       \
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname)                             \
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)        \
+{                                                                      \
+       u32 reg, mux;                                                   \
+                                                                       \
+       mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,              \
+                       &pll3_sw_clk, &lp_apm_clk);                     \
+       reg = __raw_readl(MXC_CCM_CSCMR##nr) &                          \
+               ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;         \
+       reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;  \
+       __raw_writel(reg, MXC_CCM_CSCMR##nr);                           \
+                                                                       \
+       return 0;                                                       \
+}
+
+#define CLK_SET_RATE(name, nr, bitsname)                               \
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)  \
+{                                                                      \
+       u32 reg, div, parent_rate;                                      \
+       u32 pre = 0, post = 0;                                          \
+                                                                       \
+       parent_rate = clk_get_rate(clk->parent);                        \
+       div = parent_rate / rate;                                       \
+                                                                       \
+       if ((parent_rate / div) != rate)                                \
+               return -EINVAL;                                         \
+                                                                       \
+       __calc_pre_post_dividers(div, &pre, &post,                      \
+               (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>      \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,  \
+               (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>      \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+                                                                       \
+       /* Set sdhc1 clock divider */                                   \
+       reg = __raw_readl(MXC_CCM_CSCDR##nr) &                          \
+               ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK        \
+               | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);      \
+       reg |= (post - 1) <<                                            \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;       \
+       reg |= (pre - 1) <<                                             \
+               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;       \
+       __raw_writel(reg, MXC_CCM_CSCDR##nr);                           \
+                                                                       \
+       return 0;                                                       \
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+       .parent = &pll2_sw_clk,
+       .get_rate = clk_uart_get_rate,
+       .set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+       .parent = &pll2_sw_clk,
+       .get_rate = clk_usboh3_get_rate,
+       .set_parent = clk_usboh3_set_parent,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+};
+
+static struct clk usb_ahb_clk = {
+       .parent = &ipg_clk,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+};
+
+static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+
+       if (parent == &pll3_sw_clk)
+               reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static struct clk usb_phy1_clk = {
+       .parent = &pll3_sw_clk,
+       .set_parent = clk_usb_phy1_set_parent,
+       .enable = _clk_ccgr_enable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+       .disable = _clk_ccgr_disable,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+       .parent = &pll3_sw_clk,
+       .get_rate = clk_ecspi_get_rate,
+       .set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+/* mx51 specific */
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       if (parent == &esdhc1_clk)
+               reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+       else if (parent == &esdhc2_clk)
+               reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+       else
+               return -EINVAL;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       if (parent == &esdhc1_clk)
+               reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+       else if (parent == &esdhc2_clk)
+               reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+       else
+               return -EINVAL;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+/* mx53 specific */
+static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       if (parent == &esdhc1_clk)
+               reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+       else if (parent == &esdhc3_mx53_clk)
+               reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+       else
+               return -EINVAL;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+
+static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       if (parent == &esdhc1_clk)
+               reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+       else if (parent == &esdhc3_mx53_clk)
+               reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+       else
+               return -EINVAL;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)         \
+       static struct clk name = {                                      \
+               .id             = i,                                    \
+               .enable_reg     = er,                                   \
+               .enable_shift   = es,                                   \
+               .get_rate       = gr,                                   \
+               .set_rate       = sr,                                   \
+               .enable         = e,                                    \
+               .disable        = d,                                    \
+               .parent         = p,                                    \
+               .secondary      = s,                                    \
+       }
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)                    \
+       DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
+
+/* Shared peripheral bus arbiter */
+DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
+       NULL,  NULL, &ipg_clk, NULL);
+
+/* UART */
+DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
+       NULL,  NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
+       NULL,  NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
+       NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
+       NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
+       NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart4_ipg_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
+       NULL,  NULL, &uart_root_clk, &uart5_ipg_clk);
+
+/* GPT */
+DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
+       NULL,  NULL, &ipg_clk, NULL);
+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_perclk, NULL);
+DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
+       NULL, NULL, &ipg_perclk, NULL);
+
+/* I2C */
+DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
+       NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
+       NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+       NULL, NULL, &ipg_perclk, NULL);
+
+/* FEC */
+DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
+       NULL,  NULL, &ipg_clk, NULL);
+
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+       clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+       NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+       NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
+       NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+               NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+               &ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+               NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+               NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+               &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+               NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+               NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+               NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+               NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+       clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
+       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
+       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+
+/* mx51 specific */
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+       clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc3_clk = {
+       .id = 2,
+       .parent = &esdhc1_clk,
+       .set_parent = clk_esdhc3_set_parent,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+       .enable  = _clk_max_enable,
+       .disable = _clk_max_disable,
+       .secondary = &esdhc3_ipg_clk,
+};
+static struct clk esdhc4_clk = {
+       .id = 3,
+       .parent = &esdhc1_clk,
+       .set_parent = clk_esdhc4_set_parent,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+       .enable  = _clk_max_enable,
+       .disable = _clk_max_disable,
+       .secondary = &esdhc4_ipg_clk,
+};
+
+/* mx53 specific */
+static struct clk esdhc2_mx53_clk = {
+       .id = 2,
+       .parent = &esdhc1_clk,
+       .set_parent = clk_esdhc2_mx53_set_parent,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+       .enable  = _clk_max_enable,
+       .disable = _clk_max_disable,
+       .secondary = &esdhc3_ipg_clk,
+};
+
+DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
+       clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc4_mx53_clk = {
+       .id = 3,
+       .parent = &esdhc1_clk,
+       .set_parent = clk_esdhc4_mx53_set_parent,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+       .enable  = _clk_max_enable,
+       .disable = _clk_max_disable,
+       .secondary = &esdhc4_ipg_clk,
+};
+
+static struct clk sata_clk = {
+       .parent = &ipg_clk,
+       .enable = _clk_max_enable,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+       .disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+       .parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+       .parent = &ahb_clk,
+};
+
+DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
+
+/* IPU */
+DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
+       NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
+
+DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
+               NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
+               &ddr_clk, NULL);
+
+DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
+               NULL, NULL, &pll3_sw_clk, NULL);
+DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
+               NULL, NULL, &pll3_sw_clk, NULL);
+
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+               NULL, NULL, &ipg_clk, &spba_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+               .dev_id = d, \
+               .con_id = n, \
+               .clk = &c,   \
+       },
+
+static struct clk_lookup mx51_lookups[] = {
+       /* i.mx51 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+       /* i.mx51 has the i.mx27 type fec */
+       _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
+       _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
+       _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+       _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
+       _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
+       _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
+       _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
+       _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
+       _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
+       _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
+       _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
+       _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
+       _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
+       _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+       _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+       /* i.mx51 has the i.mx35 type sdma */
+       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+       _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+       _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+       _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+       _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+       _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+       /* i.mx51 has the i.mx35 type cspi */
+       _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
+       _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
+       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+       _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+       _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+       _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
+       _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
+       _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
+       _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+       _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+       _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+};
+
+static struct clk_lookup mx53_lookups[] = {
+       /* i.mx53 has the i.mx21 type uart */
+       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
+       _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+       /* i.mx53 has the i.mx25 type fec */
+       _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+       _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+       _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
+       /* i.mx53 has the i.mx51 type ecspi */
+       _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+       _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+       /* i.mx53 has the i.mx25 type cspi */
+       _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
+       _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
+       _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+       _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+       /* i.mx53 has the i.mx35 type sdma */
+       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+       _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+       _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+       _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+       _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+       _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
+};
+
+static void clk_tree_init(void)
+{
+       u32 reg;
+
+       ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+
+       /*
+        * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+        * 8MHz, its derived from lp_apm.
+        *
+        * FIXME: Verify if true for all boards
+        */
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+       reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+       reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+       reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+       __raw_writel(reg, MXC_CCM_CBCDR);
+}
+
+int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
+                       unsigned long ckih1, unsigned long ckih2)
+{
+       int i;
+
+       external_low_reference = ckil;
+       external_high_reference = ckih1;
+       ckih2_reference = ckih2;
+       oscillator_reference = osc;
+
+       for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
+               clkdev_add(&mx51_lookups[i]);
+
+       clk_tree_init();
+
+       clk_enable(&cpu_clk);
+       clk_enable(&main_bus_clk);
+
+       clk_enable(&iim_clk);
+       imx_print_silicon_rev("i.MX51", mx51_revision());
+       clk_disable(&iim_clk);
+
+       /* move usb_phy_clk to 24MHz */
+       clk_set_parent(&usb_phy1_clk, &osc_clk);
+
+       /* set the usboh3_clk parent to pll2_sw_clk */
+       clk_set_parent(&usboh3_clk, &pll2_sw_clk);
+
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+       clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+       /* set SDHC root clock as 166.25MHZ*/
+       clk_set_rate(&esdhc1_clk, 166250000);
+       clk_set_rate(&esdhc2_clk, 166250000);
+
+       /* System timer */
+       mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+               MX51_INT_GPT);
+       return 0;
+}
+
+int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
+                       unsigned long ckih1, unsigned long ckih2)
+{
+       int i;
+
+       external_low_reference = ckil;
+       external_high_reference = ckih1;
+       ckih2_reference = ckih2;
+       oscillator_reference = osc;
+
+       for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
+               clkdev_add(&mx53_lookups[i]);
+
+       clk_tree_init();
+
+       clk_set_parent(&uart_root_clk, &pll3_sw_clk);
+       clk_enable(&cpu_clk);
+       clk_enable(&main_bus_clk);
+
+       clk_enable(&iim_clk);
+       imx_print_silicon_rev("i.MX53", mx53_revision());
+       clk_disable(&iim_clk);
+
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+       clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
+
+       /* set SDHC root clock as 200MHZ*/
+       clk_set_rate(&esdhc1_clk, 200000000);
+       clk_set_rate(&esdhc3_mx53_clk, 200000000);
+
+       /* System timer */
+       mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+               MX53_INT_GPT);
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+                                  unsigned long *ckih1, unsigned long *ckih2)
+{
+       struct device_node *np;
+
+       /* retrieve the freqency of fixed clocks from device tree */
+       for_each_compatible_node(np, NULL, "fixed-clock") {
+               u32 rate;
+               if (of_property_read_u32(np, "clock-frequency", &rate))
+                       continue;
+
+               if (of_device_is_compatible(np, "fsl,imx-ckil"))
+                       *ckil = rate;
+               else if (of_device_is_compatible(np, "fsl,imx-osc"))
+                       *osc = rate;
+               else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+                       *ckih1 = rate;
+               else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+                       *ckih2 = rate;
+       }
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+       unsigned long ckil, osc, ckih1, ckih2;
+
+       clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+       return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+       unsigned long ckil, osc, ckih1, ckih2;
+
+       clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+       return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
+#endif
diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
new file mode 100644 (file)
index 0000000..5e2e7a8
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * This file contains the CPU initialization code.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+static int mx5_cpu_rev = -1;
+
+#define IIM_SREV 0x24
+#define MX50_HW_ADADIG_DIGPROG 0xB0
+
+static int get_mx51_srev(void)
+{
+       void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
+       u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+       switch (rev) {
+       case 0x0:
+               return IMX_CHIP_REVISION_2_0;
+       case 0x10:
+               return IMX_CHIP_REVISION_3_0;
+       default:
+               return IMX_CHIP_REVISION_UNKNOWN;
+       }
+}
+
+/*
+ * Returns:
+ *     the silicon revision of the cpu
+ *     -EINVAL - not a mx51
+ */
+int mx51_revision(void)
+{
+       if (!cpu_is_mx51())
+               return -EINVAL;
+
+       if (mx5_cpu_rev == -1)
+               mx5_cpu_rev = get_mx51_srev();
+
+       return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx51_revision);
+
+#ifdef CONFIG_NEON
+
+/*
+ * All versions of the silicon before Rev. 3 have broken NEON implementations.
+ * Dependent on link order - so the assumption is that vfp_init is called
+ * before us.
+ */
+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)) {
+               elf_hwcap &= ~HWCAP_NEON;
+               pr_info("Turning off NEON support, detected broken NEON implementation\n");
+       }
+       return 0;
+}
+
+late_initcall(mx51_neon_fixup);
+#endif
+
+static int get_mx53_srev(void)
+{
+       void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
+       u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+       switch (rev) {
+       case 0x0:
+               return IMX_CHIP_REVISION_1_0;
+       case 0x2:
+               return IMX_CHIP_REVISION_2_0;
+       case 0x3:
+               return IMX_CHIP_REVISION_2_1;
+       default:
+               return IMX_CHIP_REVISION_UNKNOWN;
+       }
+}
+
+/*
+ * Returns:
+ *     the silicon revision of the cpu
+ *     -EINVAL - not a mx53
+ */
+int mx53_revision(void)
+{
+       if (!cpu_is_mx53())
+               return -EINVAL;
+
+       if (mx5_cpu_rev == -1)
+               mx5_cpu_rev = get_mx53_srev();
+
+       return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx53_revision);
+
+static int get_mx50_srev(void)
+{
+       void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
+       u32 rev;
+
+       if (!anatop) {
+               mx5_cpu_rev = -EINVAL;
+               return 0;
+       }
+
+       rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
+       rev &= 0xff;
+
+       iounmap(anatop);
+       if (rev == 0x0)
+               return IMX_CHIP_REVISION_1_0;
+       else if (rev == 0x1)
+               return IMX_CHIP_REVISION_1_1;
+       return 0;
+}
+
+/*
+ * Returns:
+ *     the silicon revision of the cpu
+ *     -EINVAL - not a mx50
+ */
+int mx50_revision(void)
+{
+       if (!cpu_is_mx50())
+               return -EINVAL;
+
+       if (mx5_cpu_rev == -1)
+               mx5_cpu_rev = get_mx50_srev();
+
+       return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx50_revision);
+
+static int __init post_cpu_init(void)
+{
+       unsigned int reg;
+       void __iomem *base;
+
+       if (cpu_is_mx51() || cpu_is_mx53()) {
+               if (cpu_is_mx51())
+                       base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
+               else
+                       base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
+
+               __raw_writel(0x0, base + 0x40);
+               __raw_writel(0x0, base + 0x44);
+               __raw_writel(0x0, base + 0x48);
+               __raw_writel(0x0, base + 0x4C);
+               reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+               __raw_writel(reg, base + 0x50);
+
+               if (cpu_is_mx51())
+                       base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
+               else
+                       base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
+
+               __raw_writel(0x0, base + 0x40);
+               __raw_writel(0x0, base + 0x44);
+               __raw_writel(0x0, base + 0x48);
+               __raw_writel(0x0, base + 0x4C);
+               reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+               __raw_writel(reg, base + 0x50);
+       }
+
+       return 0;
+}
+
+postcore_initcall(post_cpu_init);
diff --git a/arch/arm/mach-imx/cpu_op-mx51.c b/arch/arm/mach-imx/cpu_op-mx51.c
new file mode 100644 (file)
index 0000000..9d34c3d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/types.h>
+#include <mach/hardware.h>
+#include <linux/kernel.h>
+
+static struct cpu_op mx51_cpu_op[] = {
+       {
+       .cpu_rate = 160000000,},
+       {
+       .cpu_rate = 800000000,},
+};
+
+struct cpu_op *mx51_get_cpu_op(int *op)
+{
+       *op = ARRAY_SIZE(mx51_cpu_op);
+       return mx51_cpu_op;
+}
diff --git a/arch/arm/mach-imx/cpu_op-mx51.h b/arch/arm/mach-imx/cpu_op-mx51.h
new file mode 100644 (file)
index 0000000..97477fe
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+extern struct cpu_op *mx51_get_cpu_op(int *op);
diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h
new file mode 100644 (file)
index 0000000..5e11ba7
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+
+#define MX51_CCM_BASE          MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
+#define MX51_DPLL1_BASE                MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
+#define MX51_DPLL2_BASE                MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
+#define MX51_DPLL3_BASE                MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
+#define MX51_CORTEXA8_BASE     MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
+#define MX51_GPC_BASE          MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
+
+/*MX53*/
+#define MX53_CCM_BASE          MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
+#define MX53_DPLL1_BASE                MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
+#define MX53_DPLL2_BASE                MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
+#define MX53_DPLL3_BASE                MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+#define MX53_DPLL4_BASE                MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+
+/* PLL Register Offsets */
+#define MXC_PLL_DP_CTL                 0x00
+#define MXC_PLL_DP_CONFIG              0x04
+#define MXC_PLL_DP_OP                  0x08
+#define MXC_PLL_DP_MFD                 0x0C
+#define MXC_PLL_DP_MFN                 0x10
+#define MXC_PLL_DP_MFNMINUS            0x14
+#define MXC_PLL_DP_MFNPLUS             0x18
+#define MXC_PLL_DP_HFS_OP              0x1C
+#define MXC_PLL_DP_HFS_MFD             0x20
+#define MXC_PLL_DP_HFS_MFN             0x24
+#define MXC_PLL_DP_MFN_TOGC            0x28
+#define MXC_PLL_DP_DESTAT              0x2c
+
+/* PLL Register Bit definitions */
+#define MXC_PLL_DP_CTL_MUL_CTRL                0x2000
+#define MXC_PLL_DP_CTL_DPDCK0_2_EN     0x1000
+#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12
+#define MXC_PLL_DP_CTL_ADE             0x800
+#define MXC_PLL_DP_CTL_REF_CLK_DIV     0x400
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK        (3 << 8)
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET      8
+#define MXC_PLL_DP_CTL_HFSM            0x80
+#define MXC_PLL_DP_CTL_PRE             0x40
+#define MXC_PLL_DP_CTL_UPEN            0x20
+#define MXC_PLL_DP_CTL_RST             0x10
+#define MXC_PLL_DP_CTL_RCP             0x8
+#define MXC_PLL_DP_CTL_PLM             0x4
+#define MXC_PLL_DP_CTL_BRM0            0x2
+#define MXC_PLL_DP_CTL_LRF             0x1
+
+#define MXC_PLL_DP_CONFIG_BIST         0x8
+#define MXC_PLL_DP_CONFIG_SJC_CE       0x4
+#define MXC_PLL_DP_CONFIG_AREN         0x2
+#define MXC_PLL_DP_CONFIG_LDREQ                0x1
+
+#define MXC_PLL_DP_OP_MFI_OFFSET       4
+#define MXC_PLL_DP_OP_MFI_MASK         (0xF << 4)
+#define MXC_PLL_DP_OP_PDF_OFFSET       0
+#define MXC_PLL_DP_OP_PDF_MASK         0xF
+
+#define MXC_PLL_DP_MFD_OFFSET          0
+#define MXC_PLL_DP_MFD_MASK            0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_OFFSET          0x0
+#define MXC_PLL_DP_MFN_MASK            0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_TOGC_TOG_DIS    (1 << 17)
+#define MXC_PLL_DP_MFN_TOGC_TOG_EN     (1 << 16)
+#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0
+#define MXC_PLL_DP_MFN_TOGC_CNT_MASK   0xFFFF
+
+#define MXC_PLL_DP_DESTAT_TOG_SEL      (1 << 31)
+#define MXC_PLL_DP_DESTAT_MFN          0x07FFFFFF
+
+/* Register addresses of CCM*/
+#define MXC_CCM_CCR            (MX51_CCM_BASE + 0x00)
+#define MXC_CCM_CCDR           (MX51_CCM_BASE + 0x04)
+#define MXC_CCM_CSR            (MX51_CCM_BASE + 0x08)
+#define MXC_CCM_CCSR           (MX51_CCM_BASE + 0x0C)
+#define MXC_CCM_CACRR          (MX51_CCM_BASE + 0x10)
+#define MXC_CCM_CBCDR          (MX51_CCM_BASE + 0x14)
+#define MXC_CCM_CBCMR          (MX51_CCM_BASE + 0x18)
+#define MXC_CCM_CSCMR1         (MX51_CCM_BASE + 0x1C)
+#define MXC_CCM_CSCMR2         (MX51_CCM_BASE + 0x20)
+#define MXC_CCM_CSCDR1         (MX51_CCM_BASE + 0x24)
+#define MXC_CCM_CS1CDR         (MX51_CCM_BASE + 0x28)
+#define MXC_CCM_CS2CDR         (MX51_CCM_BASE + 0x2C)
+#define MXC_CCM_CDCDR          (MX51_CCM_BASE + 0x30)
+#define MXC_CCM_CHSCDR         (MX51_CCM_BASE + 0x34)
+#define MXC_CCM_CSCDR2         (MX51_CCM_BASE + 0x38)
+#define MXC_CCM_CSCDR3         (MX51_CCM_BASE + 0x3C)
+#define MXC_CCM_CSCDR4         (MX51_CCM_BASE + 0x40)
+#define MXC_CCM_CWDR           (MX51_CCM_BASE + 0x44)
+#define MXC_CCM_CDHIPR         (MX51_CCM_BASE + 0x48)
+#define MXC_CCM_CDCR           (MX51_CCM_BASE + 0x4C)
+#define MXC_CCM_CTOR           (MX51_CCM_BASE + 0x50)
+#define MXC_CCM_CLPCR          (MX51_CCM_BASE + 0x54)
+#define MXC_CCM_CISR           (MX51_CCM_BASE + 0x58)
+#define MXC_CCM_CIMR           (MX51_CCM_BASE + 0x5C)
+#define MXC_CCM_CCOSR          (MX51_CCM_BASE + 0x60)
+#define MXC_CCM_CGPR           (MX51_CCM_BASE + 0x64)
+#define MXC_CCM_CCGR0          (MX51_CCM_BASE + 0x68)
+#define MXC_CCM_CCGR1          (MX51_CCM_BASE + 0x6C)
+#define MXC_CCM_CCGR2          (MX51_CCM_BASE + 0x70)
+#define MXC_CCM_CCGR3          (MX51_CCM_BASE + 0x74)
+#define MXC_CCM_CCGR4          (MX51_CCM_BASE + 0x78)
+#define MXC_CCM_CCGR5          (MX51_CCM_BASE + 0x7C)
+#define MXC_CCM_CCGR6          (MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7          (MX51_CCM_BASE + 0x84)
+
+#define MXC_CCM_CMEOR          (MX51_CCM_BASE + 0x84)
+
+/* Define the bits in register CCR */
+#define MXC_CCM_CCR_COSC_EN            (1 << 12)
+#define MXC_CCM_CCR_FPM_MULT_MASK      (1 << 11)
+#define MXC_CCM_CCR_CAMP2_EN           (1 << 10)
+#define MXC_CCM_CCR_CAMP1_EN           (1 << 9)
+#define MXC_CCM_CCR_FPM_EN             (1 << 8)
+#define MXC_CCM_CCR_OSCNT_OFFSET       (0)
+#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
+
+/* Define the bits in register CCDR */
+#define MXC_CCM_CCDR_HSC_HS_MASK       (0x1 << 18)
+#define MXC_CCM_CCDR_IPU_HS_MASK       (0x1 << 17)
+#define MXC_CCM_CCDR_EMI_HS_MASK       (0x1 << 16)
+
+/* Define the bits in register CSR */
+#define MXC_CCM_CSR_COSR_READY (1 << 5)
+#define MXC_CCM_CSR_LVS_VALUE  (1 << 4)
+#define MXC_CCM_CSR_CAMP2_READY        (1 << 3)
+#define MXC_CCM_CSR_CAMP1_READY        (1 << 2)
+#define MXC_CCM_CSR_FPM_READY  (1 << 1)
+#define MXC_CCM_CSR_REF_EN_B   (1 << 0)
+
+/* Define the bits in register CCSR */
+#define MXC_CCM_CCSR_LP_APM_SEL                (0x1 << 9)
+#define MXC_CCM_CCSR_STEP_SEL_OFFSET   (7)
+#define MXC_CCM_CCSR_STEP_SEL_MASK     (0x3 << 7)
+#define MXC_CCM_CCSR_STEP_SEL_LP_APM      0
+#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS  1 /* Only when JTAG connected? */
+#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
+#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
+#define MXC_CCM_CCSR_PLL2_PODF_OFFSET  (5)
+#define MXC_CCM_CCSR_PLL2_PODF_MASK    (0x3 << 5)
+#define MXC_CCM_CCSR_PLL3_PODF_OFFSET  (3)
+#define MXC_CCM_CCSR_PLL3_PODF_MASK    (0x3 << 3)
+#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL   (1 << 2) /* 0: pll1_main_clk,
+                                                   1: step_clk */
+#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL   (1 << 1)
+#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL   (1 << 0)
+
+/* Define the bits in register CACRR */
+#define MXC_CCM_CACRR_ARM_PODF_OFFSET  (0)
+#define MXC_CCM_CACRR_ARM_PODF_MASK    (0x7)
+
+/* Define the bits in register CBCDR */
+#define MXC_CCM_CBCDR_EMI_CLK_SEL              (0x1 << 26)
+#define MXC_CCM_CBCDR_PERIPH_CLK_SEL           (0x1 << 25)
+#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET                (30)
+#define MXC_CCM_CBCDR_DDR_HF_SEL               (0x1 << 30)
+#define MXC_CCM_CBCDR_DDR_PODF_OFFSET          (27)
+#define MXC_CCM_CBCDR_DDR_PODF_MASK            (0x7 << 27)
+#define MXC_CCM_CBCDR_EMI_PODF_OFFSET          (22)
+#define MXC_CCM_CBCDR_EMI_PODF_MASK            (0x7 << 22)
+#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET                (19)
+#define MXC_CCM_CBCDR_AXI_B_PODF_MASK          (0x7 << 19)
+#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET                (16)
+#define MXC_CCM_CBCDR_AXI_A_PODF_MASK          (0x7 << 16)
+#define MXC_CCM_CBCDR_NFC_PODF_OFFSET          (13)
+#define MXC_CCM_CBCDR_NFC_PODF_MASK            (0x7 << 13)
+#define MXC_CCM_CBCDR_AHB_PODF_OFFSET          (10)
+#define MXC_CCM_CBCDR_AHB_PODF_MASK            (0x7 << 10)
+#define MXC_CCM_CBCDR_IPG_PODF_OFFSET          (8)
+#define MXC_CCM_CBCDR_IPG_PODF_MASK            (0x3 << 8)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET      (6)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK                (0x3 << 6)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET      (3)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK                (0x7 << 3)
+#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET       (0)
+#define MXC_CCM_CBCDR_PERCLK_PODF_MASK         (0x7)
+
+/* Define the bits in register CBCMR */
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET   (14)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK     (0x3 << 14)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET    (12)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK      (0x3 << 12)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET       (10)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK         (0x3 << 10)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET   (8)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK     (0x3 << 8)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET   (6)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK     (0x3 << 6)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET       (4)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK         (0x3 << 4)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET     (14)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK       (0x3 << 14)
+#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL    (0x1 << 1)
+#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL       (0x1 << 0)
+
+/* Define the bits in register CSCMR1 */
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET         (30)
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK           (0x3 << 30)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET         (28)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK           (0x3 << 28)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET          (26)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL                 (0x1 << 26)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET             (24)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK               (0x3 << 24)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET           (22)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK             (0x3 << 22)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET     (20)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK       (0x3 << 20)
+#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL                  (0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL       (0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL                  (0x1 << 18)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET     (16)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK       (0x3 << 16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET      (16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK                (0x3 << 16)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET             (14)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK               (0x3 << 14)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET             (12)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK               (0x3 << 12)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL                    (0x1 << 11)
+#define MXC_CCM_CSCMR1_VPU_RCLK_SEL                    (0x1 << 10)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET          (8)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK            (0x3 << 8)
+#define MXC_CCM_CSCMR1_TVE_CLK_SEL                     (0x1 << 7)
+#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL                 (0x1 << 6)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET             (4)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK               (0x3 << 4)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET            (2)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK              (0x3 << 2)
+#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL            (0x1 << 1)
+#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL            (0x1)
+
+/* Define the bits in register CSCMR2 */
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)            (26+n*3)
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)              (0x7 << (26+n*3))
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET                (24)
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK          (0x3 << 24)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET                (22)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK          (0x3 << 22)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET              (20)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK                        (0x3 << 20)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET             (18)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK               (0x3 << 18)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET             (16)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK               (0x3 << 16)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET            (14)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK              (0x3 << 14)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET             (12)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK               (0x3 << 12)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET              (10)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK                        (0x3 << 10)
+#define MXC_CCM_CSCMR2_SLIMBUS_COM                     (0x1 << 9)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET          (6)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK            (0x7 << 6)
+#define MXC_CCM_CSCMR2_SPDIF1_COM                      (1 << 5)
+#define MXC_CCM_CSCMR2_SPDIF0_COM                      (1 << 4)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET           (2)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK             (0x3 << 2)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET           (0)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK             (0x3)
+
+/* Define the bits in register CSCDR1 */
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET    (22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK      (0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET    (19)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK      (0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET     (22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK       (0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET     (19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK       (0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET    (16)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK      (0x7 << 16)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET             (14)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK               (0x3 << 14)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET    (11)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK      (0x7 << 11)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET          (8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK            (0x7 << 8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET          (6)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK            (0x3 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET            (3)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK              (0x7 << 3)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET            (0)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK              (0x7)
+
+/* Define the bits in register CS1CDR and CS2CDR */
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET                (22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK          (0x7 << 22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET                (16)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK          (0x3F << 16)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET            (6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK              (0x7 << 6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET            (0)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK              (0x3F)
+
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET                (22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK          (0x7 << 22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET                (16)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK          (0x3F << 16)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET            (6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK              (0x7 << 6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET            (0)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK              (0x3F)
+
+/* Define the bits in register CDCDR */
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET              (28)
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK                        (0x7 << 28)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET           (25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK             (0x7 << 25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET           (19)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK             (0x3F << 19)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET           (16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK             (0x7 << 16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET           (9)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK             (0x3F << 9)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET               (6)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK                 (0x7 << 6)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET              (3)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK                        (0x7 << 3)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET              (0)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK                        (0x7)
+
+/* Define the bits in register CHSCCDR */
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET            (12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK              (0x7 << 12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET            (6)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK              (0x3F << 6)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET           (3)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK             (0x7 << 3)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET           (0)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK             (0x7)
+
+/* Define the bits in register CSCDR2 */
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET            (25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK              (0x7 << 25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET            (19)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK              (0x3F << 19)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET             (16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK               (0x7 << 16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET             (9)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK               (0x3F << 9)
+#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET         (6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK               (0x7 << 6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET             (0)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK               (0x3F)
+
+/* Define the bits in register CSCDR3 */
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET           (16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK             (0x7 << 16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET           (9)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK             (0x3F << 9)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET            (6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK              (0x7 << 6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET            (0)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK              (0x3F)
+
+/* Define the bits in register CSCDR4 */
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET       (16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK         (0x7 << 16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET       (9)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK         (0x3F << 9)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET       (6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK         (0x7 << 6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET       (0)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK         (0x3F)
+
+/* Define the bits in register CDHIPR */
+#define MXC_CCM_CDHIPR_ARM_PODF_BUSY                   (1 << 16)
+#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY             (1 << 8)
+#define MXC_CCM_CDHIPR_DDR_PODF_BUSY                   (1 << 7)
+#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY                        (1 << 6)
+#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY             (1 << 5)
+#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY       (1 << 4)
+#define MXC_CCM_CDHIPR_AHB_PODF_BUSY                   (1 << 3)
+#define MXC_CCM_CDHIPR_EMI_PODF_BUSY                   (1 << 2)
+#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY                 (1 << 1)
+#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY                 (1 << 0)
+
+/* Define the bits in register CDCR */
+#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER            (0x1 << 2)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET       (0)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK         (0x3)
+
+/* Define the bits in register CLPCR */
+#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS                (0x1 << 23)
+#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS                (0x1 << 22)
+#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS               (0x1 << 21)
+#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS               (0x1 << 25)
+#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS       (0x1 << 20)
+#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS                (0x1 << 19)
+#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS                (0x1 << 18)
+#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS       (0x1 << 17)
+#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS       (0x1 << 16)
+#define MXC_CCM_CLPCR_COSC_PWRDOWN             (0x1 << 11)
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET                (9)
+#define MXC_CCM_CLPCR_STBY_COUNT_MASK          (0x3 << 9)
+#define MXC_CCM_CLPCR_VSTBY                    (0x1 << 8)
+#define MXC_CCM_CLPCR_DIS_REF_OSC              (0x1 << 7)
+#define MXC_CCM_CLPCR_SBYOS                    (0x1 << 6)
+#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM       (0x1 << 5)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET      (3)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK                (0x3 << 3)
+#define MXC_CCM_CLPCR_LPM_OFFSET               (0)
+#define MXC_CCM_CLPCR_LPM_MASK                 (0x3)
+
+/* Define the bits in register CISR */
+#define MXC_CCM_CISR_ARM_PODF_LOADED                   (0x1 << 25)
+#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED       (0x1 << 21)
+#define MXC_CCM_CISR_AHB_PODF_LOADED                   (0x1 << 20)
+#define MXC_CCM_CISR_EMI_PODF_LOADED                   (0x1 << 19)
+#define MXC_CCM_CISR_AXI_B_PODF_LOADED                 (0x1 << 18)
+#define MXC_CCM_CISR_AXI_A_PODF_LOADED                 (0x1 << 17)
+#define MXC_CCM_CISR_DIVIDER_LOADED                    (0x1 << 16)
+#define MXC_CCM_CISR_COSC_READY                                (0x1 << 6)
+#define MXC_CCM_CISR_CKIH2_READY                       (0x1 << 5)
+#define MXC_CCM_CISR_CKIH_READY                                (0x1 << 4)
+#define MXC_CCM_CISR_FPM_READY                         (0x1 << 3)
+#define MXC_CCM_CISR_LRF_PLL3                          (0x1 << 2)
+#define MXC_CCM_CISR_LRF_PLL2                          (0x1 << 1)
+#define MXC_CCM_CISR_LRF_PLL1                          (0x1)
+
+/* Define the bits in register CIMR */
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED              (0x1 << 25)
+#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED  (0x1 << 21)
+#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED              (0x1 << 20)
+#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED            (0x1 << 19)
+#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED            (0x1 << 18)
+#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED            (0x1 << 17)
+#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED               (0x1 << 16)
+#define MXC_CCM_CIMR_MASK_COSC_READY                   (0x1 << 5)
+#define MXC_CCM_CIMR_MASK_CKIH_READY                   (0x1 << 4)
+#define MXC_CCM_CIMR_MASK_FPM_READY                    (0x1 << 3)
+#define MXC_CCM_CIMR_MASK_LRF_PLL3                     (0x1 << 2)
+#define MXC_CCM_CIMR_MASK_LRF_PLL2                     (0x1 << 1)
+#define MXC_CCM_CIMR_MASK_LRF_PLL1                     (0x1)
+
+/* Define the bits in register CCOSR */
+#define MXC_CCM_CCOSR_CKO2_EN_OFFSET                   (0x1 << 24)
+#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET                  (21)
+#define MXC_CCM_CCOSR_CKO2_DIV_MASK                    (0x7 << 21)
+#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET                  (16)
+#define MXC_CCM_CCOSR_CKO2_SEL_MASK                    (0x1F << 16)
+#define MXC_CCM_CCOSR_CKOL_EN                          (0x1 << 7)
+#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET                  (4)
+#define MXC_CCM_CCOSR_CKOL_DIV_MASK                    (0x7 << 4)
+#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET                  (0)
+#define MXC_CCM_CCOSR_CKOL_SEL_MASK                    (0xF)
+
+/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE            (0x1 << 4)
+#define MXC_CCM_CGPR_FPM_SEL                           (0x1 << 3)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET           (0)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK             (0x7)
+
+/* Define the bits in registers CCGRx */
+#define MXC_CCM_CCGRx_CG_MASK                          0x3
+#define MXC_CCM_CCGRx_MOD_OFF                          0x0
+#define MXC_CCM_CCGRx_MOD_ON                           0x3
+#define MXC_CCM_CCGRx_MOD_IDLE                         0x1
+
+#define MXC_CCM_CCGRx_CG15_MASK                                (0x3 << 30)
+#define MXC_CCM_CCGRx_CG14_MASK                                (0x3 << 28)
+#define MXC_CCM_CCGRx_CG13_MASK                                (0x3 << 26)
+#define MXC_CCM_CCGRx_CG12_MASK                                (0x3 << 24)
+#define MXC_CCM_CCGRx_CG11_MASK                                (0x3 << 22)
+#define MXC_CCM_CCGRx_CG10_MASK                                (0x3 << 20)
+#define MXC_CCM_CCGRx_CG9_MASK                         (0x3 << 18)
+#define MXC_CCM_CCGRx_CG8_MASK                         (0x3 << 16)
+#define MXC_CCM_CCGRx_CG5_MASK                         (0x3 << 10)
+#define MXC_CCM_CCGRx_CG4_MASK                         (0x3 << 8)
+#define MXC_CCM_CCGRx_CG3_MASK                         (0x3 << 6)
+#define MXC_CCM_CCGRx_CG2_MASK                         (0x3 << 4)
+#define MXC_CCM_CCGRx_CG1_MASK                         (0x3 << 2)
+#define MXC_CCM_CCGRx_CG0_MASK                         (0x3 << 0)
+
+#define MXC_CCM_CCGRx_CG15_OFFSET                      30
+#define MXC_CCM_CCGRx_CG14_OFFSET                      28
+#define MXC_CCM_CCGRx_CG13_OFFSET                      26
+#define MXC_CCM_CCGRx_CG12_OFFSET                      24
+#define MXC_CCM_CCGRx_CG11_OFFSET                      22
+#define MXC_CCM_CCGRx_CG10_OFFSET                      20
+#define MXC_CCM_CCGRx_CG9_OFFSET                       18
+#define MXC_CCM_CCGRx_CG8_OFFSET                       16
+#define MXC_CCM_CCGRx_CG7_OFFSET                       14
+#define MXC_CCM_CCGRx_CG6_OFFSET                       12
+#define MXC_CCM_CCGRx_CG5_OFFSET                       10
+#define MXC_CCM_CCGRx_CG4_OFFSET                       8
+#define MXC_CCM_CCGRx_CG3_OFFSET                       6
+#define MXC_CCM_CCGRx_CG2_OFFSET                       4
+#define MXC_CCM_CCGRx_CG1_OFFSET                       2
+#define MXC_CCM_CCGRx_CG0_OFFSET                       0
+
+#define MXC_DPTC_LP_BASE       (MX51_GPC_BASE + 0x80)
+#define MXC_DPTC_GP_BASE       (MX51_GPC_BASE + 0x100)
+#define MXC_DVFS_CORE_BASE     (MX51_GPC_BASE + 0x180)
+#define MXC_DPTC_PER_BASE      (MX51_GPC_BASE + 0x1C0)
+#define MXC_PGC_IPU_BASE       (MX51_GPC_BASE + 0x220)
+#define MXC_PGC_VPU_BASE       (MX51_GPC_BASE + 0x240)
+#define MXC_PGC_GPU_BASE       (MX51_GPC_BASE + 0x260)
+#define MXC_SRPG_NEON_BASE     (MX51_GPC_BASE + 0x280)
+#define MXC_SRPG_ARM_BASE      (MX51_GPC_BASE + 0x2A0)
+#define MXC_SRPG_EMPGC0_BASE   (MX51_GPC_BASE + 0x2C0)
+#define MXC_SRPG_EMPGC1_BASE   (MX51_GPC_BASE + 0x2D0)
+#define MXC_SRPG_MEGAMIX_BASE  (MX51_GPC_BASE + 0x2E0)
+#define MXC_SRPG_EMI_BASE      (MX51_GPC_BASE + 0x300)
+
+/* CORTEXA8 platform */
+#define MXC_CORTEXA8_PLAT_PVID         (MX51_CORTEXA8_BASE + 0x0)
+#define MXC_CORTEXA8_PLAT_GPC          (MX51_CORTEXA8_BASE + 0x4)
+#define MXC_CORTEXA8_PLAT_PIC          (MX51_CORTEXA8_BASE + 0x8)
+#define MXC_CORTEXA8_PLAT_LPC          (MX51_CORTEXA8_BASE + 0xC)
+#define MXC_CORTEXA8_PLAT_NEON_LPC     (MX51_CORTEXA8_BASE + 0x10)
+#define MXC_CORTEXA8_PLAT_ICGC         (MX51_CORTEXA8_BASE + 0x14)
+#define MXC_CORTEXA8_PLAT_AMC          (MX51_CORTEXA8_BASE + 0x18)
+#define MXC_CORTEXA8_PLAT_NMC          (MX51_CORTEXA8_BASE + 0x20)
+#define MXC_CORTEXA8_PLAT_NMS          (MX51_CORTEXA8_BASE + 0x24)
+
+/* DVFS CORE */
+#define MXC_DVFSTHRS           (MXC_DVFS_CORE_BASE + 0x00)
+#define MXC_DVFSCOUN           (MXC_DVFS_CORE_BASE + 0x04)
+#define MXC_DVFSSIG1           (MXC_DVFS_CORE_BASE + 0x08)
+#define MXC_DVFSSIG0           (MXC_DVFS_CORE_BASE + 0x0C)
+#define MXC_DVFSGPC0           (MXC_DVFS_CORE_BASE + 0x10)
+#define MXC_DVFSGPC1           (MXC_DVFS_CORE_BASE + 0x14)
+#define MXC_DVFSGPBT           (MXC_DVFS_CORE_BASE + 0x18)
+#define MXC_DVFSEMAC           (MXC_DVFS_CORE_BASE + 0x1C)
+#define MXC_DVFSCNTR           (MXC_DVFS_CORE_BASE + 0x20)
+#define MXC_DVFSLTR0_0         (MXC_DVFS_CORE_BASE + 0x24)
+#define MXC_DVFSLTR0_1         (MXC_DVFS_CORE_BASE + 0x28)
+#define MXC_DVFSLTR1_0         (MXC_DVFS_CORE_BASE + 0x2C)
+#define MXC_DVFSLTR1_1         (MXC_DVFS_CORE_BASE + 0x30)
+#define MXC_DVFSPT0            (MXC_DVFS_CORE_BASE + 0x34)
+#define MXC_DVFSPT1            (MXC_DVFS_CORE_BASE + 0x38)
+#define MXC_DVFSPT2            (MXC_DVFS_CORE_BASE + 0x3C)
+#define MXC_DVFSPT3            (MXC_DVFS_CORE_BASE + 0x40)
+
+/* GPC */
+#define MXC_GPC_CNTR           (MX51_GPC_BASE + 0x0)
+#define MXC_GPC_PGR            (MX51_GPC_BASE + 0x4)
+#define MXC_GPC_VCR            (MX51_GPC_BASE + 0x8)
+#define MXC_GPC_ALL_PU         (MX51_GPC_BASE + 0xC)
+#define MXC_GPC_NEON           (MX51_GPC_BASE + 0x10)
+#define MXC_GPC_PGR_ARMPG_OFFSET       8
+#define MXC_GPC_PGR_ARMPG_MASK         (3 << 8)
+
+/* PGC */
+#define MXC_PGC_IPU_PGCR       (MXC_PGC_IPU_BASE + 0x0)
+#define MXC_PGC_IPU_PGSR       (MXC_PGC_IPU_BASE + 0xC)
+#define MXC_PGC_VPU_PGCR       (MXC_PGC_VPU_BASE + 0x0)
+#define MXC_PGC_VPU_PGSR       (MXC_PGC_VPU_BASE + 0xC)
+#define MXC_PGC_GPU_PGCR       (MXC_PGC_GPU_BASE + 0x0)
+#define MXC_PGC_GPU_PGSR       (MXC_PGC_GPU_BASE + 0xC)
+
+#define MXC_PGCR_PCR           1
+#define MXC_SRPGCR_PCR         1
+#define MXC_EMPGCR_PCR         1
+#define MXC_PGSR_PSR           1
+
+
+#define MXC_CORTEXA8_PLAT_LPC_DSM      (1 << 0)
+#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM  (1 << 1)
+
+/* SRPG */
+#define MXC_SRPG_NEON_SRPGCR   (MXC_SRPG_NEON_BASE + 0x0)
+#define MXC_SRPG_NEON_PUPSCR   (MXC_SRPG_NEON_BASE + 0x4)
+#define MXC_SRPG_NEON_PDNSCR   (MXC_SRPG_NEON_BASE + 0x8)
+
+#define MXC_SRPG_ARM_SRPGCR    (MXC_SRPG_ARM_BASE + 0x0)
+#define MXC_SRPG_ARM_PUPSCR    (MXC_SRPG_ARM_BASE + 0x4)
+#define MXC_SRPG_ARM_PDNSCR    (MXC_SRPG_ARM_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0)
+#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4)
+#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0)
+#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4)
+#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8)
+
+#define MXC_SRPG_MEGAMIX_SRPGCR                (MXC_SRPG_MEGAMIX_BASE + 0x0)
+#define MXC_SRPG_MEGAMIX_PUPSCR                (MXC_SRPG_MEGAMIX_BASE + 0x4)
+#define MXC_SRPG_MEGAMIX_PDNSCR                (MXC_SRPG_MEGAMIX_BASE + 0x8)
+
+#define MXC_SRPGC_EMI_SRPGCR   (MXC_SRPGC_EMI_BASE + 0x0)
+#define MXC_SRPGC_EMI_PUPSCR   (MXC_SRPGC_EMI_BASE + 0x4)
+#define MXC_SRPGC_EMI_PDNSCR   (MXC_SRPGC_EMI_BASE + 0x8)
+
+#endif                         /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h
new file mode 100644 (file)
index 0000000..7216667
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 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 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 <mach/mx50.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
+#define imx50_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
+
+extern const struct imx_fec_data imx50_fec_data;
+#define imx50_add_fec(pdata)   \
+       imx_add_fec(&imx50_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
+#define imx50_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h
new file mode 100644 (file)
index 0000000..af488bc
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx51_fec_data;
+#define imx51_add_fec(pdata)   \
+       imx_add_fec(&imx51_fec_data, pdata)
+
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata)  \
+       imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
+#define imx51_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata) \
+       imx51_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
+#define imx51_add_imx_ssi(id, pdata)   \
+       imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
+#define imx51_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata)  \
+       imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata)       \
+       imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
+#define imx51_add_mxc_nand(pdata)      \
+       imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
+#define imx51_add_sdhci_esdhc_imx(id, pdata)   \
+       imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data;
+#define imx51_add_cspi(pdata)  \
+       imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[];
+#define imx51_add_ecspi(id, pdata)     \
+       imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
+#define imx51_add_imx2_wdt(id, pdata)  \
+       imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
+
+extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
+#define imx51_add_mxc_pwm(id)  \
+       imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
+
+extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
+#define imx51_add_imx_keypad(pdata)    \
+       imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+       imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices-imx53.h b/arch/arm/mach-imx/devices-imx53.h
new file mode 100644 (file)
index 0000000..6e1e5d1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ *
+ * 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 <mach/mx53.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx53_fec_data;
+#define imx53_add_fec(pdata)   \
+       imx_add_fec(&imx53_fec_data, pdata)
+
+extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
+#define imx53_add_imx_uart(id, pdata)  \
+       imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
+
+
+extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
+#define imx53_add_imx_i2c(id, pdata)   \
+       imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
+#define imx53_add_sdhci_esdhc_imx(id, pdata)   \
+       imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx53_ecspi_data[];
+#define imx53_add_ecspi(id, pdata)     \
+       imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
+#define imx53_add_imx2_wdt(id, pdata)  \
+       imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
+
+extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
+#define imx53_add_imx_ssi(id, pdata)   \
+       imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
+#define imx53_add_imx_keypad(pdata)    \
+       imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+       imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-imx/efika.h b/arch/arm/mach-imx/efika.h
new file mode 100644 (file)
index 0000000..014aa98
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _EFIKA_H
+#define _EFIKA_H
+
+#define EFIKA_WLAN_EN          IMX_GPIO_NR(2, 16)
+#define EFIKA_WLAN_RESET       IMX_GPIO_NR(2, 10)
+#define EFIKA_USB_PHY_RESET    IMX_GPIO_NR(2, 9)
+
+void __init efika_board_common_init(void);
+
+#endif
diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c
new file mode 100644 (file)
index 0000000..c17fa13
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define MXC_OTG_OFFSET                 0
+#define MXC_H1_OFFSET                  0x200
+#define MXC_H2_OFFSET                  0x400
+
+/* USB_CTRL */
+#define MXC_OTG_UCTRL_OWIE_BIT         (1 << 27)       /* OTG wakeup intr enable */
+#define MXC_OTG_UCTRL_OPM_BIT          (1 << 24)       /* OTG power mask */
+#define MXC_H1_UCTRL_H1UIE_BIT         (1 << 12)       /* Host1 ULPI interrupt enable */
+#define MXC_H1_UCTRL_H1WIE_BIT         (1 << 11)       /* HOST1 wakeup intr enable */
+#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)               /* HOST1 power mask */
+
+/* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_DIS_BIT     (1 << 8)        /* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_DIS_BIT              (1 << 5)        /* UH1 Disable Overcurrent Event */
+
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT         (1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT         (1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT          (1 << 4)
+
+#define MXC_USBCMD_OFFSET              0x140
+
+/* USBCMD */
+#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
+
+int mx51_initialize_usb_hw(int port, unsigned int flags)
+{
+       unsigned int v;
+       void __iomem *usb_base;
+       void __iomem *usbotg_base;
+       void __iomem *usbother_base;
+       int ret = 0;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base) {
+               printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+               return -ENOMEM;
+       }
+
+       switch (port) {
+       case 0: /* OTG port */
+               usbotg_base = usb_base + MXC_OTG_OFFSET;
+               break;
+       case 1: /* Host 1 port */
+               usbotg_base = usb_base + MXC_H1_OFFSET;
+               break;
+       case 2: /* Host 2 port */
+               usbotg_base = usb_base + MXC_H2_OFFSET;
+               break;
+       default:
+               printk(KERN_ERR"%s no such port %d\n", __func__, port);
+               ret = -ENOENT;
+               goto error;
+       }
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       switch (port) {
+       case 0: /*OTG port */
+               if (flags & MXC_EHCI_INTERNAL_PHY) {
+                       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+                       if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+                               /* OC/USBPWR is not used */
+                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+                       } else {
+                               /* OC/USBPWR is used */
+                               v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+                       }
+                       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+                       v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+                       if (flags & MXC_EHCI_WAKEUP_ENABLED)
+                               v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
+                       else
+                               v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+                       if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                               v |= MXC_OTG_UCTRL_OPM_BIT;
+                       else
+                               v &= ~MXC_OTG_UCTRL_OPM_BIT;
+                       __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+               }
+               break;
+       case 1: /* Host 1 */
+               /*Host ULPI */
+               v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+               if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+                       /* HOST1 wakeup/ULPI intr enable */
+                       v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+               } else {
+                       /* HOST1 wakeup/ULPI intr disable */
+                       v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+               }
+
+               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+               else
+                       v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+               __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+
+               v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                       v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
+               else
+                       v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
+               __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+               v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
+               if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
+                       /* Interrupt Threshold Control:Immediate (no threshold) */
+                       v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
+               __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
+               break;
+       case 2: /* Host 2 ULPI */
+               v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+               if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+                       /* HOST1 wakeup/ULPI intr enable */
+                       v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+               } else {
+                       /* HOST1 wakeup/ULPI intr disable */
+                       v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+               }
+
+               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+               else
+                       v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+               __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+               break;
+       }
+
+error:
+       iounmap(usb_base);
+       return ret;
+}
+
diff --git a/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c
new file mode 100644 (file)
index 0000000..a6a3ab8
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/leds.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/mach/arch.h>
+
+#include "devices-imx51.h"
+
+#define MBIMX51_TSC2007_GPIO   IMX_GPIO_NR(3, 30)
+#define MBIMX51_LED0           IMX_GPIO_NR(3, 5)
+#define MBIMX51_LED1           IMX_GPIO_NR(3, 6)
+#define MBIMX51_LED2           IMX_GPIO_NR(3, 7)
+#define MBIMX51_LED3           IMX_GPIO_NR(3, 8)
+
+static const struct gpio_led mbimx51_leds[] __initconst = {
+       {
+               .name                   = "led0",
+               .default_trigger        = "heartbeat",
+               .active_low             = 1,
+               .gpio                   = MBIMX51_LED0,
+       },
+       {
+               .name                   = "led1",
+               .default_trigger        = "nand-disk",
+               .active_low             = 1,
+               .gpio                   = MBIMX51_LED1,
+       },
+       {
+               .name                   = "led2",
+               .default_trigger        = "mmc0",
+               .active_low             = 1,
+               .gpio                   = MBIMX51_LED2,
+       },
+       {
+               .name                   = "led3",
+               .default_trigger        = "default-on",
+               .active_low             = 1,
+               .gpio                   = MBIMX51_LED3,
+       },
+};
+
+static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
+       .leds           = mbimx51_leds,
+       .num_leds       = ARRAY_SIZE(mbimx51_leds),
+};
+
+static iomux_v3_cfg_t mbimx51_pads[] = {
+       /* UART2 */
+       MX51_PAD_UART2_RXD__UART2_RXD,
+       MX51_PAD_UART2_TXD__UART2_TXD,
+
+       /* UART3 */
+       MX51_PAD_UART3_RXD__UART3_RXD,
+       MX51_PAD_UART3_TXD__UART3_TXD,
+       MX51_PAD_KEY_COL4__UART3_RTS,
+       MX51_PAD_KEY_COL5__UART3_CTS,
+
+       /* TSC2007 IRQ */
+       MX51_PAD_NANDF_D10__GPIO3_30,
+
+       /* LEDS */
+       MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
+       MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
+       MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
+       MX51_PAD_DISPB2_SER_RS__GPIO3_8,
+
+       /* KPP */
+       MX51_PAD_KEY_ROW0__KEY_ROW0,
+       MX51_PAD_KEY_ROW1__KEY_ROW1,
+       MX51_PAD_KEY_ROW2__KEY_ROW2,
+       MX51_PAD_KEY_ROW3__KEY_ROW3,
+       MX51_PAD_KEY_COL0__KEY_COL0,
+       MX51_PAD_KEY_COL1__KEY_COL1,
+       MX51_PAD_KEY_COL2__KEY_COL2,
+       MX51_PAD_KEY_COL3__KEY_COL3,
+
+       /* SD 1 */
+       MX51_PAD_SD1_CMD__SD1_CMD,
+       MX51_PAD_SD1_CLK__SD1_CLK,
+       MX51_PAD_SD1_DATA0__SD1_DATA0,
+       MX51_PAD_SD1_DATA1__SD1_DATA1,
+       MX51_PAD_SD1_DATA2__SD1_DATA2,
+       MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+       /* SD 2 */
+       MX51_PAD_SD2_CMD__SD2_CMD,
+       MX51_PAD_SD2_CLK__SD2_CLK,
+       MX51_PAD_SD2_DATA0__SD2_DATA0,
+       MX51_PAD_SD2_DATA1__SD2_DATA1,
+       MX51_PAD_SD2_DATA2__SD2_DATA2,
+       MX51_PAD_SD2_DATA3__SD2_DATA3,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mbimx51_keymap[] = {
+       KEY(0, 0, KEY_1),
+       KEY(0, 1, KEY_2),
+       KEY(0, 2, KEY_3),
+       KEY(0, 3, KEY_UP),
+
+       KEY(1, 0, KEY_4),
+       KEY(1, 1, KEY_5),
+       KEY(1, 2, KEY_6),
+       KEY(1, 3, KEY_LEFT),
+
+       KEY(2, 0, KEY_7),
+       KEY(2, 1, KEY_8),
+       KEY(2, 2, KEY_9),
+       KEY(2, 3, KEY_RIGHT),
+
+       KEY(3, 0, KEY_0),
+       KEY(3, 1, KEY_DOWN),
+       KEY(3, 2, KEY_ESC),
+       KEY(3, 3, KEY_ENTER),
+};
+
+static const struct matrix_keymap_data mbimx51_map_data __initconst = {
+       .keymap         = mbimx51_keymap,
+       .keymap_size    = ARRAY_SIZE(mbimx51_keymap),
+};
+
+static int tsc2007_get_pendown_state(void)
+{
+       return !gpio_get_value(MBIMX51_TSC2007_GPIO);
+}
+
+struct tsc2007_platform_data tsc2007_data = {
+       .model = 2007,
+       .x_plate_ohms = 180,
+       .get_pendown_state = tsc2007_get_pendown_state,
+};
+
+static struct i2c_board_info mbimx51_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("tsc2007", 0x49),
+               .irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
+               .platform_data = &tsc2007_data,
+       }, {
+               I2C_BOARD_INFO("tlv320aic23", 0x1a),
+       },
+};
+
+/*
+ * baseboard initialization.
+ */
+void __init eukrea_mbimx51_baseboard_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
+                                       ARRAY_SIZE(mbimx51_pads));
+
+       imx51_add_imx_uart(1, NULL);
+       imx51_add_imx_uart(2, &uart_pdata);
+
+       gpio_request(MBIMX51_LED0, "LED0");
+       gpio_direction_output(MBIMX51_LED0, 1);
+       gpio_free(MBIMX51_LED0);
+       gpio_request(MBIMX51_LED1, "LED1");
+       gpio_direction_output(MBIMX51_LED1, 1);
+       gpio_free(MBIMX51_LED1);
+       gpio_request(MBIMX51_LED2, "LED2");
+       gpio_direction_output(MBIMX51_LED2, 1);
+       gpio_free(MBIMX51_LED2);
+       gpio_request(MBIMX51_LED3, "LED3");
+       gpio_direction_output(MBIMX51_LED3, 1);
+       gpio_free(MBIMX51_LED3);
+
+       gpio_led_register_device(-1, &mbimx51_leds_info);
+
+       imx51_add_imx_keypad(&mbimx51_map_data);
+
+       gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
+       gpio_direction_input(MBIMX51_TSC2007_GPIO);
+       irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
+                                       IRQF_TRIGGER_FALLING);
+       i2c_register_board_info(1, mbimx51_i2c_devices,
+                               ARRAY_SIZE(mbimx51_i2c_devices));
+
+       imx51_add_sdhci_esdhc_imx(0, NULL);
+       imx51_add_sdhci_esdhc_imx(1, NULL);
+}
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
new file mode 100644 (file)
index 0000000..d817fc8
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx51.h>
+#include <mach/audmux.h>
+
+#include "devices-imx51.h"
+
+static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
+       /* LED */
+       MX51_PAD_NANDF_D10__GPIO3_30,
+       /* SWITCH */
+       NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
+                       PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+                       PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+       /* UART2 */
+       MX51_PAD_UART2_RXD__UART2_RXD,
+       MX51_PAD_UART2_TXD__UART2_TXD,
+       /* UART 3 */
+       MX51_PAD_UART3_RXD__UART3_RXD,
+       MX51_PAD_UART3_TXD__UART3_TXD,
+       MX51_PAD_KEY_COL4__UART3_RTS,
+       MX51_PAD_KEY_COL5__UART3_CTS,
+       /* SD */
+       MX51_PAD_SD1_CMD__SD1_CMD,
+       MX51_PAD_SD1_CLK__SD1_CLK,
+       MX51_PAD_SD1_DATA0__SD1_DATA0,
+       MX51_PAD_SD1_DATA1__SD1_DATA1,
+       MX51_PAD_SD1_DATA2__SD1_DATA2,
+       MX51_PAD_SD1_DATA3__SD1_DATA3,
+       /* SD1 CD */
+       NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
+                       PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+                       PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+};
+
+#define GPIO_LED1      IMX_GPIO_NR(3, 30)
+#define GPIO_SWITCH1   IMX_GPIO_NR(3, 31)
+
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
+       {
+               .name                   = "led1",
+               .default_trigger        = "heartbeat",
+               .active_low             = 1,
+               .gpio                   = GPIO_LED1,
+       },
+};
+
+static const struct gpio_led_platform_data
+               eukrea_mbimxsd_led_info __initconst = {
+       .leds           = eukrea_mbimxsd_leds,
+       .num_leds       = ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+       {
+               .gpio           = GPIO_SWITCH1,
+               .code           = BTN_0,
+               .desc           = "BP1",
+               .active_low     = 1,
+               .wakeup         = 1,
+       },
+};
+
+static const struct gpio_keys_platform_data
+               eukrea_mbimxsd_button_data __initconst = {
+       .buttons        = eukrea_mbimxsd_gpio_buttons,
+       .nbuttons       = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("tlv320aic23", 0x1a),
+       },
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx51sd init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd51_baseboard_init(void)
+{
+       if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+                       ARRAY_SIZE(eukrea_mbimxsd_pads)))
+               printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+       imx51_add_imx_uart(1, NULL);
+       imx51_add_imx_uart(2, &uart_pdata);
+
+       imx51_add_sdhci_esdhc_imx(0, NULL);
+
+       gpio_request(GPIO_LED1, "LED1");
+       gpio_direction_output(GPIO_LED1, 1);
+       gpio_free(GPIO_LED1);
+
+       gpio_request(GPIO_SWITCH1, "SWITCH1");
+       gpio_direction_input(GPIO_SWITCH1);
+       gpio_free(GPIO_SWITCH1);
+
+       i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+                               ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+       gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
+       imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
+}
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
new file mode 100644 (file)
index 0000000..e6bad17
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+       OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+       { /* sentinel */ }
+};
+
+static int __init imx51_tzic_add_irq_domain(struct device_node *np,
+                               struct device_node *interrupt_parent)
+{
+       irq_domain_add_simple(np, 0);
+       return 0;
+}
+
+static int __init imx51_gpio_add_irq_domain(struct device_node *np,
+                               struct device_node *interrupt_parent)
+{
+       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+       gpio_irq_base -= 32;
+       irq_domain_add_simple(np, gpio_irq_base);
+
+       return 0;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+       { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+       { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+       { /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+       { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+       { /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+       struct device_node *node;
+       const struct of_device_id *of_id;
+       void (*func)(void);
+
+       of_irq_init(imx51_irq_match);
+
+       node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+       if (node) {
+               of_id = of_match_node(imx51_iomuxc_of_match, node);
+               func = of_id->data;
+               func();
+               of_node_put(node);
+       }
+
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+       mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+       .init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+       "fsl,imx51-babbage",
+       NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+       .map_io         = mx51_map_io,
+       .init_early     = imx51_init_early,
+       .init_irq       = mx51_init_irq,
+       .handle_irq     = imx51_handle_irq,
+       .timer          = &imx51_timer,
+       .init_machine   = imx51_dt_init,
+       .dt_compat      = imx51_dt_board_compat,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c
new file mode 100644 (file)
index 0000000..05ebb3e
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+       { /* sentinel */ }
+};
+
+static int __init imx53_tzic_add_irq_domain(struct device_node *np,
+                               struct device_node *interrupt_parent)
+{
+       irq_domain_add_simple(np, 0);
+       return 0;
+}
+
+static int __init imx53_gpio_add_irq_domain(struct device_node *np,
+                               struct device_node *interrupt_parent)
+{
+       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+       gpio_irq_base -= 32;
+       irq_domain_add_simple(np, gpio_irq_base);
+
+       return 0;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+       { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+       { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+       { /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+       { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+       { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+       { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+       { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+       { /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+       struct device_node *node;
+       const struct of_device_id *of_id;
+       void (*func)(void);
+
+       of_irq_init(imx53_irq_match);
+
+       node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+       if (node) {
+               of_id = of_match_node(imx53_iomuxc_of_match, node);
+               func = of_id->data;
+               func();
+               of_node_put(node);
+       }
+
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+       mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+       .init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+       "fsl,imx53-ard",
+       "fsl,imx53-evk",
+       "fsl,imx53-qsb",
+       "fsl,imx53-smd",
+       NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+       .map_io         = mx53_map_io,
+       .init_early     = imx53_init_early,
+       .init_irq       = mx53_init_irq,
+       .handle_irq     = imx53_handle_irq,
+       .timer          = &imx53_timer,
+       .init_machine   = imx53_dt_init,
+       .dt_compat      = imx53_dt_board_compat,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx51.c b/arch/arm/mach-imx/mach-cpuimx51.c
new file mode 100644 (file)
index 0000000..944025d
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+
+#define CPUIMX51_USBH1_STP     IMX_GPIO_NR(1, 27)
+#define CPUIMX51_QUARTA_GPIO   IMX_GPIO_NR(3, 28)
+#define CPUIMX51_QUARTB_GPIO   IMX_GPIO_NR(3, 25)
+#define CPUIMX51_QUARTC_GPIO   IMX_GPIO_NR(3, 26)
+#define CPUIMX51_QUARTD_GPIO   IMX_GPIO_NR(3, 27)
+#define CPUIMX51_QUART_XTAL    14745600
+#define CPUIMX51_QUART_REGSHIFT        17
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET         0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN   (1 << 25)
+
+#define        MX51_USB_PLLDIV_12_MHZ          0x00
+#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
+#define        MX51_USB_PLL_DIV_24_MHZ         0x02
+
+static struct plat_serial8250_port serial_platform_data[] = {
+       {
+               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
+               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
+               .irqflags = IRQF_TRIGGER_HIGH,
+               .uartclk = CPUIMX51_QUART_XTAL,
+               .regshift = CPUIMX51_QUART_REGSHIFT,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+       }, {
+               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
+               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
+               .irqflags = IRQF_TRIGGER_HIGH,
+               .uartclk = CPUIMX51_QUART_XTAL,
+               .regshift = CPUIMX51_QUART_REGSHIFT,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+       }, {
+               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
+               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
+               .irqflags = IRQF_TRIGGER_HIGH,
+               .uartclk = CPUIMX51_QUART_XTAL,
+               .regshift = CPUIMX51_QUART_REGSHIFT,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+       }, {
+               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
+               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
+               .irqflags = IRQF_TRIGGER_HIGH,
+               .uartclk = CPUIMX51_QUART_XTAL,
+               .regshift = CPUIMX51_QUART_REGSHIFT,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+       }, {
+       }
+};
+
+static struct platform_device serial_device = {
+       .name = "serial8250",
+       .id = 0,
+       .dev = {
+               .platform_data = serial_platform_data,
+       },
+};
+
+static struct platform_device *devices[] __initdata = {
+       &serial_device,
+};
+
+static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+
+       /* I2C2 */
+       MX51_PAD_GPIO1_2__I2C2_SCL,
+       MX51_PAD_GPIO1_3__I2C2_SDA,
+       MX51_PAD_NANDF_D10__GPIO3_30,
+
+       /* QUART IRQ */
+       MX51_PAD_NANDF_D15__GPIO3_25,
+       MX51_PAD_NANDF_D14__GPIO3_26,
+       MX51_PAD_NANDF_D13__GPIO3_27,
+       MX51_PAD_NANDF_D12__GPIO3_28,
+
+       /* USB HOST1 */
+       MX51_PAD_USBH1_CLK__USBH1_CLK,
+       MX51_PAD_USBH1_DIR__USBH1_DIR,
+       MX51_PAD_USBH1_NXT__USBH1_NXT,
+       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+       MX51_PAD_USBH1_STP__USBH1_STP,
+};
+
+static const struct mxc_nand_platform_data
+               eukrea_cpuimx51_nand_board_info __initconst = {
+       .width          = 1,
+       .hw_ecc         = 1,
+       .flash_bbt      = 1,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const
+struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("pcf8563", 0x51),
+       },
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* Set the PHY clock to 19.2MHz */
+       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+       v |= MX51_USB_PLL_DIV_19_2_MHZ;
+       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* The clock for the USBH1 ULPI port will come externally from the PHY. */
+       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+                       MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+       .init           = initialize_otg_port,
+       .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+       .operating_mode = FSL_USB2_DR_DEVICE,
+       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+       .init           = initialize_usbh1_port,
+       .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51_otg_mode(char *options)
+{
+       if (!strcmp(options, "host"))
+               otg_mode_host = 1;
+       else if (!strcmp(options, "device"))
+               otg_mode_host = 0;
+       else
+               pr_info("otg_mode neither \"host\" nor \"device\". "
+                       "Defaulting to device\n");
+       return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
+
+/*
+ * Board specific initialization.
+ */
+static void __init eukrea_cpuimx51_init(void)
+{
+       imx51_soc_init();
+
+       mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
+                                       ARRAY_SIZE(eukrea_cpuimx51_pads));
+
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
+
+       gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
+       gpio_direction_input(CPUIMX51_QUARTA_GPIO);
+       gpio_free(CPUIMX51_QUARTA_GPIO);
+       gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
+       gpio_direction_input(CPUIMX51_QUARTB_GPIO);
+       gpio_free(CPUIMX51_QUARTB_GPIO);
+       gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
+       gpio_direction_input(CPUIMX51_QUARTC_GPIO);
+       gpio_free(CPUIMX51_QUARTC_GPIO);
+       gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
+       gpio_direction_input(CPUIMX51_QUARTD_GPIO);
+       gpio_free(CPUIMX51_QUARTD_GPIO);
+
+       imx51_add_fec(NULL);
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
+       i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
+                               ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
+
+       if (otg_mode_host)
+               imx51_add_mxc_ehci_otg(&dr_utmi_config);
+       else {
+               initialize_otg_port(NULL);
+               imx51_add_fsl_usb2_udc(&usb_pdata);
+       }
+       imx51_add_mxc_ehci_hs(1, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
+       eukrea_mbimx51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+       .init   = eukrea_cpuimx51_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
+       /* Maintainer: Eric Bénard <eric@eukrea.com> */
+       .atag_offset = 0x100,
+       .map_io = mx51_map_io,
+       .init_early = imx51_init_early,
+       .init_irq = mx51_init_irq,
+       .handle_irq = imx51_handle_irq,
+       .timer = &mxc_timer,
+       .init_machine = eukrea_cpuimx51_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
new file mode 100644 (file)
index 0000000..9fbe923
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "cpu_op-mx51.h"
+
+#define USBH1_RST              IMX_GPIO_NR(2, 28)
+#define ETH_RST                        IMX_GPIO_NR(2, 31)
+#define TSC2007_IRQGPIO                IMX_GPIO_NR(3, 12)
+#define CAN_IRQGPIO            IMX_GPIO_NR(1, 1)
+#define CAN_RST                        IMX_GPIO_NR(4, 15)
+#define CAN_NCS                        IMX_GPIO_NR(4, 24)
+#define CAN_RXOBF              IMX_GPIO_NR(1, 4)
+#define CAN_RX1BF              IMX_GPIO_NR(1, 6)
+#define CAN_TXORTS             IMX_GPIO_NR(1, 7)
+#define CAN_TX1RTS             IMX_GPIO_NR(1, 8)
+#define CAN_TX2RTS             IMX_GPIO_NR(1, 9)
+#define I2C_SCL                        IMX_GPIO_NR(4, 16)
+#define I2C_SDA                        IMX_GPIO_NR(4, 17)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET         0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN   (1 << 25)
+
+#define        MX51_USB_PLLDIV_12_MHZ          0x00
+#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
+#define        MX51_USB_PLL_DIV_24_MHZ         0x02
+
+static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+
+       /* USB HOST1 */
+       MX51_PAD_USBH1_CLK__USBH1_CLK,
+       MX51_PAD_USBH1_DIR__USBH1_DIR,
+       MX51_PAD_USBH1_NXT__USBH1_NXT,
+       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+       MX51_PAD_USBH1_STP__USBH1_STP,
+       MX51_PAD_EIM_CS3__GPIO2_28,             /* PHY nRESET */
+
+       /* FEC */
+       MX51_PAD_EIM_DTACK__GPIO2_31,           /* PHY nRESET */
+
+       /* HSI2C */
+       MX51_PAD_I2C1_CLK__GPIO4_16,
+       MX51_PAD_I2C1_DAT__GPIO4_17,
+
+       /* CAN */
+       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+       MX51_PAD_CSPI1_SS0__GPIO4_24,           /* nCS */
+       MX51_PAD_CSI2_PIXCLK__GPIO4_15,         /* nReset */
+       MX51_PAD_GPIO1_1__GPIO1_1,              /* IRQ */
+       MX51_PAD_GPIO1_4__GPIO1_4,              /* Control signals */
+       MX51_PAD_GPIO1_6__GPIO1_6,
+       MX51_PAD_GPIO1_7__GPIO1_7,
+       MX51_PAD_GPIO1_8__GPIO1_8,
+       MX51_PAD_GPIO1_9__GPIO1_9,
+
+       /* Touchscreen */
+       /* IRQ */
+       NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
+                       PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+                       PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct tsc2007_platform_data tsc2007_info = {
+       .model                  = 2007,
+       .x_plate_ohms           = 180,
+};
+
+static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("pcf8563", 0x51),
+       }, {
+               I2C_BOARD_INFO("tsc2007", 0x49),
+               .type           = "tsc2007",
+               .platform_data  = &tsc2007_info,
+               .irq            = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
+       },
+};
+
+static const struct mxc_nand_platform_data
+               eukrea_cpuimx51sd_nand_board_info __initconst = {
+       .width          = 1,
+       .hw_ecc         = 1,
+       .flash_bbt      = 1,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* Set the PHY clock to 19.2MHz */
+       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+       v |= MX51_USB_PLL_DIV_19_2_MHZ;
+       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* The clock for the USBH1 ULPI port will come from the PHY. */
+       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+                       usbother_base + MX51_USB_CTRL_1_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+                       MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+       .init           = initialize_otg_port,
+       .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+       .operating_mode = FSL_USB2_DR_DEVICE,
+       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+       .init           = initialize_usbh1_port,
+       .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51sd_otg_mode(char *options)
+{
+       if (!strcmp(options, "host"))
+               otg_mode_host = 1;
+       else if (!strcmp(options, "device"))
+               otg_mode_host = 0;
+       else
+               pr_info("otg_mode neither \"host\" nor \"device\". "
+                       "Defaulting to device\n");
+       return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
+
+static struct i2c_gpio_platform_data pdata = {
+       .sda_pin                = I2C_SDA,
+       .sda_is_open_drain      = 0,
+       .scl_pin                = I2C_SCL,
+       .scl_is_open_drain      = 0,
+       .udelay                 = 2,
+};
+
+static struct platform_device hsi2c_gpio_device = {
+       .name                   = "i2c-gpio",
+       .id                     = 0,
+       .dev.platform_data      = &pdata,
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+       .oscillator_frequency = 24E6,
+};
+
+static struct spi_board_info cpuimx51sd_spi_device[] = {
+       {
+               .modalias        = "mcp2515",
+               .max_speed_hz    = 10000000,
+               .bus_num         = 0,
+               .mode           = SPI_MODE_0,
+               .chip_select     = 0,
+               .platform_data   = &mcp251x_info,
+               .irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
+       },
+};
+
+static int cpuimx51sd_spi1_cs[] = {
+       CAN_NCS,
+};
+
+static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
+       .chipselect     = cpuimx51sd_spi1_cs,
+       .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+       &hsi2c_gpio_device,
+};
+
+static void __init eukrea_cpuimx51sd_init(void)
+{
+       imx51_soc_init();
+
+       mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
+                                       ARRAY_SIZE(eukrea_cpuimx51sd_pads));
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+       get_cpu_op = mx51_get_cpu_op;
+#endif
+
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+
+       gpio_request(ETH_RST, "eth_rst");
+       gpio_set_value(ETH_RST, 1);
+       imx51_add_fec(NULL);
+
+       gpio_request(CAN_IRQGPIO, "can_irq");
+       gpio_direction_input(CAN_IRQGPIO);
+       gpio_free(CAN_IRQGPIO);
+       gpio_request(CAN_NCS, "can_ncs");
+       gpio_direction_output(CAN_NCS, 1);
+       gpio_free(CAN_NCS);
+       gpio_request(CAN_RST, "can_rst");
+       gpio_direction_output(CAN_RST, 0);
+       msleep(20);
+       gpio_set_value(CAN_RST, 1);
+       imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+       spi_register_board_info(cpuimx51sd_spi_device,
+                               ARRAY_SIZE(cpuimx51sd_spi_device));
+
+       gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
+       gpio_direction_input(TSC2007_IRQGPIO);
+       gpio_free(TSC2007_IRQGPIO);
+
+       i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
+                       ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
+       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+       if (otg_mode_host)
+               imx51_add_mxc_ehci_otg(&dr_utmi_config);
+       else {
+               initialize_otg_port(NULL);
+               imx51_add_fsl_usb2_udc(&usb_pdata);
+       }
+
+       gpio_request(USBH1_RST, "usb_rst");
+       gpio_direction_output(USBH1_RST, 0);
+       msleep(20);
+       gpio_set_value(USBH1_RST, 1);
+       imx51_add_mxc_ehci_hs(1, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
+       eukrea_mbimxsd51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51sd_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+       .init   = eukrea_cpuimx51sd_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
+       /* Maintainer: Eric Bénard <eric@eukrea.com> */
+       .atag_offset = 0x100,
+       .map_io = mx51_map_io,
+       .init_early = imx51_init_early,
+       .init_irq = mx51_init_irq,
+       .handle_irq = imx51_handle_irq,
+       .timer = &mxc_timer,
+       .init_machine = eukrea_cpuimx51sd_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx50_rdp.c b/arch/arm/mach-imx/mach-mx50_rdp.c
new file mode 100644 (file)
index 0000000..42b66e8
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2010 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 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx50.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx50.h"
+
+#define FEC_EN         IMX_GPIO_NR(6, 23)
+#define FEC_RESET_B    IMX_GPIO_NR(4, 12)
+
+static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
+       /* SD1 */
+       MX50_PAD_ECSPI2_SS0__GPIO_4_19,
+       MX50_PAD_EIM_CRE__GPIO_1_27,
+       MX50_PAD_SD1_CMD__SD1_CMD,
+
+       MX50_PAD_SD1_CLK__SD1_CLK,
+       MX50_PAD_SD1_D0__SD1_D0,
+       MX50_PAD_SD1_D1__SD1_D1,
+       MX50_PAD_SD1_D2__SD1_D2,
+       MX50_PAD_SD1_D3__SD1_D3,
+
+       /* SD2 */
+       MX50_PAD_SD2_CD__GPIO_5_17,
+       MX50_PAD_SD2_WP__GPIO_5_16,
+       MX50_PAD_SD2_CMD__SD2_CMD,
+       MX50_PAD_SD2_CLK__SD2_CLK,
+       MX50_PAD_SD2_D0__SD2_D0,
+       MX50_PAD_SD2_D1__SD2_D1,
+       MX50_PAD_SD2_D2__SD2_D2,
+       MX50_PAD_SD2_D3__SD2_D3,
+       MX50_PAD_SD2_D4__SD2_D4,
+       MX50_PAD_SD2_D5__SD2_D5,
+       MX50_PAD_SD2_D6__SD2_D6,
+       MX50_PAD_SD2_D7__SD2_D7,
+
+       /* SD3 */
+       MX50_PAD_SD3_CMD__SD3_CMD,
+       MX50_PAD_SD3_CLK__SD3_CLK,
+       MX50_PAD_SD3_D0__SD3_D0,
+       MX50_PAD_SD3_D1__SD3_D1,
+       MX50_PAD_SD3_D2__SD3_D2,
+       MX50_PAD_SD3_D3__SD3_D3,
+       MX50_PAD_SD3_D4__SD3_D4,
+       MX50_PAD_SD3_D5__SD3_D5,
+       MX50_PAD_SD3_D6__SD3_D6,
+       MX50_PAD_SD3_D7__SD3_D7,
+
+       /* PWR_INT */
+       MX50_PAD_ECSPI2_MISO__GPIO_4_18,
+
+       /* UART pad setting */
+       MX50_PAD_UART1_TXD__UART1_TXD,
+       MX50_PAD_UART1_RXD__UART1_RXD,
+       MX50_PAD_UART1_RTS__UART1_RTS,
+       MX50_PAD_UART2_TXD__UART2_TXD,
+       MX50_PAD_UART2_RXD__UART2_RXD,
+       MX50_PAD_UART2_CTS__UART2_CTS,
+       MX50_PAD_UART2_RTS__UART2_RTS,
+
+       MX50_PAD_I2C1_SCL__I2C1_SCL,
+       MX50_PAD_I2C1_SDA__I2C1_SDA,
+       MX50_PAD_I2C2_SCL__I2C2_SCL,
+       MX50_PAD_I2C2_SDA__I2C2_SDA,
+
+       MX50_PAD_EPITO__USBH1_PWR,
+       /* Need to comment below line if
+        * one needs to debug owire.
+        */
+       MX50_PAD_OWIRE__USBH1_OC,
+       /* using gpio to control otg pwr */
+       MX50_PAD_PWM2__GPIO_6_25,
+       MX50_PAD_I2C3_SCL__USBOTG_OC,
+
+       MX50_PAD_SSI_RXC__FEC_MDIO,
+       MX50_PAD_SSI_RXFS__FEC_MDC,
+       MX50_PAD_DISP_D0__FEC_TXCLK,
+       MX50_PAD_DISP_D1__FEC_RX_ER,
+       MX50_PAD_DISP_D2__FEC_RX_DV,
+       MX50_PAD_DISP_D3__FEC_RXD1,
+       MX50_PAD_DISP_D4__FEC_RXD0,
+       MX50_PAD_DISP_D5__FEC_TX_EN,
+       MX50_PAD_DISP_D6__FEC_TXD1,
+       MX50_PAD_DISP_D7__FEC_TXD0,
+       MX50_PAD_I2C3_SDA__GPIO_6_23,
+       MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
+
+       MX50_PAD_CSPI_SS0__CSPI_SS0,
+       MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
+       MX50_PAD_CSPI_MOSI__CSPI_MOSI,
+       MX50_PAD_CSPI_MISO__CSPI_MISO,
+
+       /* SGTL500_OSC_EN */
+       MX50_PAD_UART1_CTS__GPIO_6_8,
+
+       /* SGTL_AMP_SHDN */
+       MX50_PAD_UART3_RXD__GPIO_6_15,
+
+       /* Keypad */
+       MX50_PAD_KEY_COL0__KEY_COL0,
+       MX50_PAD_KEY_ROW0__KEY_ROW0,
+       MX50_PAD_KEY_COL1__KEY_COL1,
+       MX50_PAD_KEY_ROW1__KEY_ROW1,
+       MX50_PAD_KEY_COL2__KEY_COL2,
+       MX50_PAD_KEY_ROW2__KEY_ROW2,
+       MX50_PAD_KEY_COL3__KEY_COL3,
+       MX50_PAD_KEY_ROW3__KEY_ROW3,
+       MX50_PAD_EIM_DA0__KEY_COL4,
+       MX50_PAD_EIM_DA1__KEY_ROW4,
+       MX50_PAD_EIM_DA2__KEY_COL5,
+       MX50_PAD_EIM_DA3__KEY_ROW5,
+       MX50_PAD_EIM_DA4__KEY_COL6,
+       MX50_PAD_EIM_DA5__KEY_ROW6,
+       MX50_PAD_EIM_DA6__KEY_COL7,
+       MX50_PAD_EIM_DA7__KEY_ROW7,
+       /*EIM pads */
+       MX50_PAD_EIM_DA8__GPIO_1_8,
+       MX50_PAD_EIM_DA9__GPIO_1_9,
+       MX50_PAD_EIM_DA10__GPIO_1_10,
+       MX50_PAD_EIM_DA11__GPIO_1_11,
+       MX50_PAD_EIM_DA12__GPIO_1_12,
+       MX50_PAD_EIM_DA13__GPIO_1_13,
+       MX50_PAD_EIM_DA14__GPIO_1_14,
+       MX50_PAD_EIM_DA15__GPIO_1_15,
+       MX50_PAD_EIM_CS2__GPIO_1_16,
+       MX50_PAD_EIM_CS1__GPIO_1_17,
+       MX50_PAD_EIM_CS0__GPIO_1_18,
+       MX50_PAD_EIM_EB0__GPIO_1_19,
+       MX50_PAD_EIM_EB1__GPIO_1_20,
+       MX50_PAD_EIM_WAIT__GPIO_1_21,
+       MX50_PAD_EIM_BCLK__GPIO_1_22,
+       MX50_PAD_EIM_RDY__GPIO_1_23,
+       MX50_PAD_EIM_OE__GPIO_1_24,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct fec_platform_data fec_data __initconst = {
+       .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static inline void mx50_rdp_fec_reset(void)
+{
+       gpio_request(FEC_EN, "fec-en");
+       gpio_direction_output(FEC_EN, 0);
+       gpio_request(FEC_RESET_B, "fec-reset_b");
+       gpio_direction_output(FEC_RESET_B, 0);
+       msleep(1);
+       gpio_set_value(FEC_RESET_B, 1);
+}
+
+static const struct imxi2c_platform_data i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx50_rdp_board_init(void)
+{
+       imx50_soc_init();
+
+       mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
+                                       ARRAY_SIZE(mx50_rdp_pads));
+
+       imx50_add_imx_uart(0, &uart_pdata);
+       imx50_add_imx_uart(1, &uart_pdata);
+       mx50_rdp_fec_reset();
+       imx50_add_fec(&fec_data);
+       imx50_add_imx_i2c(0, &i2c_data);
+       imx50_add_imx_i2c(1, &i2c_data);
+       imx50_add_imx_i2c(2, &i2c_data);
+}
+
+static void __init mx50_rdp_timer_init(void)
+{
+       mx50_clocks_init(32768, 24000000, 22579200);
+}
+
+static struct sys_timer mx50_rdp_timer = {
+       .init   = mx50_rdp_timer_init,
+};
+
+MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
+       .map_io = mx50_map_io,
+       .init_early = imx50_init_early,
+       .init_irq = mx50_init_irq,
+       .handle_irq = imx50_handle_irq,
+       .timer = &mx50_rdp_timer,
+       .init_machine = mx50_rdp_board_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c
new file mode 100644 (file)
index 0000000..83eab41
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx51.h>
+#include <mach/3ds_debugboard.h>
+
+#include "devices-imx51.h"
+
+#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(1, 6))
+#define MX51_3DS_ECSPI2_CS     (GPIO_PORTC + 28)
+
+static iomux_v3_cfg_t mx51_3ds_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+
+       /* UART2 */
+       MX51_PAD_UART2_RXD__UART2_RXD,
+       MX51_PAD_UART2_TXD__UART2_TXD,
+       MX51_PAD_EIM_D25__UART2_CTS,
+       MX51_PAD_EIM_D26__UART2_RTS,
+
+       /* UART3 */
+       MX51_PAD_UART3_RXD__UART3_RXD,
+       MX51_PAD_UART3_TXD__UART3_TXD,
+       MX51_PAD_EIM_D24__UART3_CTS,
+       MX51_PAD_EIM_D27__UART3_RTS,
+
+       /* CPLD PARENT IRQ PIN */
+       MX51_PAD_GPIO1_6__GPIO1_6,
+
+       /* KPP */
+       MX51_PAD_KEY_ROW0__KEY_ROW0,
+       MX51_PAD_KEY_ROW1__KEY_ROW1,
+       MX51_PAD_KEY_ROW2__KEY_ROW2,
+       MX51_PAD_KEY_ROW3__KEY_ROW3,
+       MX51_PAD_KEY_COL0__KEY_COL0,
+       MX51_PAD_KEY_COL1__KEY_COL1,
+       MX51_PAD_KEY_COL2__KEY_COL2,
+       MX51_PAD_KEY_COL3__KEY_COL3,
+       MX51_PAD_KEY_COL4__KEY_COL4,
+       MX51_PAD_KEY_COL5__KEY_COL5,
+
+       /* eCSPI2 */
+       MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
+       MX51_PAD_NANDF_RB3__ECSPI2_MISO,
+       MX51_PAD_NANDF_D15__ECSPI2_MOSI,
+       MX51_PAD_NANDF_D12__GPIO3_28,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mx51_3ds_board_keymap[] = {
+       KEY(0, 0, KEY_1),
+       KEY(0, 1, KEY_2),
+       KEY(0, 2, KEY_3),
+       KEY(0, 3, KEY_F1),
+       KEY(0, 4, KEY_UP),
+       KEY(0, 5, KEY_F2),
+
+       KEY(1, 0, KEY_4),
+       KEY(1, 1, KEY_5),
+       KEY(1, 2, KEY_6),
+       KEY(1, 3, KEY_LEFT),
+       KEY(1, 4, KEY_SELECT),
+       KEY(1, 5, KEY_RIGHT),
+
+       KEY(2, 0, KEY_7),
+       KEY(2, 1, KEY_8),
+       KEY(2, 2, KEY_9),
+       KEY(2, 3, KEY_F3),
+       KEY(2, 4, KEY_DOWN),
+       KEY(2, 5, KEY_F4),
+
+       KEY(3, 0, KEY_0),
+       KEY(3, 1, KEY_OK),
+       KEY(3, 2, KEY_ESC),
+       KEY(3, 3, KEY_ENTER),
+       KEY(3, 4, KEY_MENU),
+       KEY(3, 5, KEY_BACK)
+};
+
+static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
+       .keymap         = mx51_3ds_board_keymap,
+       .keymap_size    = ARRAY_SIZE(mx51_3ds_board_keymap),
+};
+
+static int mx51_3ds_spi2_cs[] = {
+       MXC_SPI_CS(0),
+       MX51_3DS_ECSPI2_CS,
+};
+
+static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
+       .chipselect     = mx51_3ds_spi2_cs,
+       .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs),
+};
+
+static struct spi_board_info mx51_3ds_spi_nor_device[] = {
+       {
+        .modalias = "m25p80",
+        .max_speed_hz = 25000000,      /* max spi clock (SCK) speed in HZ */
+        .bus_num = 1,
+        .chip_select = 1,
+        .mode = SPI_MODE_0,
+        .platform_data = NULL,},
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx51_3ds_init(void)
+{
+       imx51_soc_init();
+
+       mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
+                                       ARRAY_SIZE(mx51_3ds_pads));
+
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_imx_uart(1, &uart_pdata);
+       imx51_add_imx_uart(2, &uart_pdata);
+
+       imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
+       spi_register_board_info(mx51_3ds_spi_nor_device,
+                               ARRAY_SIZE(mx51_3ds_spi_nor_device));
+
+       if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+               printk(KERN_WARNING "Init of the debugboard failed, all "
+                                   "devices on the board are unusable.\n");
+
+       imx51_add_sdhci_esdhc_imx(0, NULL);
+       imx51_add_imx_keypad(&mx51_3ds_map_data);
+       imx51_add_imx2_wdt(0, NULL);
+}
+
+static void __init mx51_3ds_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx51_3ds_timer = {
+       .init = mx51_3ds_timer_init,
+};
+
+MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
+       /* Maintainer: Freescale Semiconductor, Inc. */
+       .atag_offset = 0x100,
+       .map_io = mx51_map_io,
+       .init_early = imx51_init_early,
+       .init_irq = mx51_init_irq,
+       .handle_irq = imx51_handle_irq,
+       .timer = &mx51_3ds_timer,
+       .init_machine = mx51_3ds_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c
new file mode 100644 (file)
index 0000000..e4b822e
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "cpu_op-mx51.h"
+
+#define BABBAGE_USB_HUB_RESET  IMX_GPIO_NR(1, 7)
+#define BABBAGE_USBH1_STP      IMX_GPIO_NR(1, 27)
+#define BABBAGE_USB_PHY_RESET  IMX_GPIO_NR(2, 5)
+#define BABBAGE_FEC_PHY_RESET  IMX_GPIO_NR(2, 14)
+#define BABBAGE_POWER_KEY      IMX_GPIO_NR(2, 21)
+#define BABBAGE_ECSPI1_CS0     IMX_GPIO_NR(4, 24)
+#define BABBAGE_ECSPI1_CS1     IMX_GPIO_NR(4, 25)
+#define BABBAGE_SD2_CD         IMX_GPIO_NR(1, 6)
+#define BABBAGE_SD2_WP         IMX_GPIO_NR(1, 5)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET                 0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN           (1 << 25)
+
+#define        MX51_USB_PLLDIV_12_MHZ          0x00
+#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
+#define        MX51_USB_PLL_DIV_24_MHZ 0x02
+
+static struct gpio_keys_button babbage_buttons[] = {
+       {
+               .gpio           = BABBAGE_POWER_KEY,
+               .code           = BTN_0,
+               .desc           = "PWR",
+               .active_low     = 1,
+               .wakeup         = 1,
+       },
+};
+
+static const struct gpio_keys_platform_data imx_button_data __initconst = {
+       .buttons        = babbage_buttons,
+       .nbuttons       = ARRAY_SIZE(babbage_buttons),
+};
+
+static iomux_v3_cfg_t mx51babbage_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+
+       /* UART2 */
+       MX51_PAD_UART2_RXD__UART2_RXD,
+       MX51_PAD_UART2_TXD__UART2_TXD,
+
+       /* UART3 */
+       MX51_PAD_EIM_D25__UART3_RXD,
+       MX51_PAD_EIM_D26__UART3_TXD,
+       MX51_PAD_EIM_D27__UART3_RTS,
+       MX51_PAD_EIM_D24__UART3_CTS,
+
+       /* I2C1 */
+       MX51_PAD_EIM_D16__I2C1_SDA,
+       MX51_PAD_EIM_D19__I2C1_SCL,
+
+       /* I2C2 */
+       MX51_PAD_KEY_COL4__I2C2_SCL,
+       MX51_PAD_KEY_COL5__I2C2_SDA,
+
+       /* HSI2C */
+       MX51_PAD_I2C1_CLK__I2C1_CLK,
+       MX51_PAD_I2C1_DAT__I2C1_DAT,
+
+       /* USB HOST1 */
+       MX51_PAD_USBH1_CLK__USBH1_CLK,
+       MX51_PAD_USBH1_DIR__USBH1_DIR,
+       MX51_PAD_USBH1_NXT__USBH1_NXT,
+       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+       /* USB HUB reset line*/
+       MX51_PAD_GPIO1_7__GPIO1_7,
+
+       /* USB PHY reset line */
+       MX51_PAD_EIM_D21__GPIO2_5,
+
+       /* FEC */
+       MX51_PAD_EIM_EB2__FEC_MDIO,
+       MX51_PAD_EIM_EB3__FEC_RDATA1,
+       MX51_PAD_EIM_CS2__FEC_RDATA2,
+       MX51_PAD_EIM_CS3__FEC_RDATA3,
+       MX51_PAD_EIM_CS4__FEC_RX_ER,
+       MX51_PAD_EIM_CS5__FEC_CRS,
+       MX51_PAD_NANDF_RB2__FEC_COL,
+       MX51_PAD_NANDF_RB3__FEC_RX_CLK,
+       MX51_PAD_NANDF_D9__FEC_RDATA0,
+       MX51_PAD_NANDF_D8__FEC_TDATA0,
+       MX51_PAD_NANDF_CS2__FEC_TX_ER,
+       MX51_PAD_NANDF_CS3__FEC_MDC,
+       MX51_PAD_NANDF_CS4__FEC_TDATA1,
+       MX51_PAD_NANDF_CS5__FEC_TDATA2,
+       MX51_PAD_NANDF_CS6__FEC_TDATA3,
+       MX51_PAD_NANDF_CS7__FEC_TX_EN,
+       MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+       /* FEC PHY reset line */
+       MX51_PAD_EIM_A20__GPIO2_14,
+
+       /* SD 1 */
+       MX51_PAD_SD1_CMD__SD1_CMD,
+       MX51_PAD_SD1_CLK__SD1_CLK,
+       MX51_PAD_SD1_DATA0__SD1_DATA0,
+       MX51_PAD_SD1_DATA1__SD1_DATA1,
+       MX51_PAD_SD1_DATA2__SD1_DATA2,
+       MX51_PAD_SD1_DATA3__SD1_DATA3,
+       /* CD/WP from controller */
+       MX51_PAD_GPIO1_0__SD1_CD,
+       MX51_PAD_GPIO1_1__SD1_WP,
+
+       /* SD 2 */
+       MX51_PAD_SD2_CMD__SD2_CMD,
+       MX51_PAD_SD2_CLK__SD2_CLK,
+       MX51_PAD_SD2_DATA0__SD2_DATA0,
+       MX51_PAD_SD2_DATA1__SD2_DATA1,
+       MX51_PAD_SD2_DATA2__SD2_DATA2,
+       MX51_PAD_SD2_DATA3__SD2_DATA3,
+       /* CD/WP gpio */
+       MX51_PAD_GPIO1_6__GPIO1_6,
+       MX51_PAD_GPIO1_5__GPIO1_5,
+
+       /* eCSPI1 */
+       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+       MX51_PAD_CSPI1_SS0__GPIO4_24,
+       MX51_PAD_CSPI1_SS1__GPIO4_25,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
+       .bitrate = 400000,
+};
+
+static struct gpio mx51_babbage_usbh1_gpios[] = {
+       { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
+       { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
+};
+
+static int gpio_usbh1_active(void)
+{
+       iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+       int ret;
+
+       /* Set USBH1_STP to GPIO and toggle it */
+       mxc_iomux_v3_setup_pad(usbh1stp_gpio);
+       ret = gpio_request_array(mx51_babbage_usbh1_gpios,
+                                       ARRAY_SIZE(mx51_babbage_usbh1_gpios));
+
+       if (ret) {
+               pr_debug("failed to get USBH1 pins: %d\n", ret);
+               return ret;
+       }
+
+       msleep(100);
+       gpio_set_value(BABBAGE_USBH1_STP, 1);
+       gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
+       gpio_free_array(mx51_babbage_usbh1_gpios,
+                                       ARRAY_SIZE(mx51_babbage_usbh1_gpios));
+       return 0;
+}
+
+static inline void babbage_usbhub_reset(void)
+{
+       int ret;
+
+       /* Reset USB hub */
+       ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
+                                       GPIOF_OUT_INIT_LOW, "GPIO1_7");
+       if (ret) {
+               printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
+               return;
+       }
+
+       msleep(2);
+       /* Deassert reset */
+       gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
+}
+
+static inline void babbage_fec_reset(void)
+{
+       int ret;
+
+       /* reset FEC PHY */
+       ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
+                                       GPIOF_OUT_INIT_LOW, "fec-phy-reset");
+       if (ret) {
+               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+               return;
+       }
+       msleep(1);
+       gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+}
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* Set the PHY clock to 19.2MHz */
+       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+       v |= MX51_USB_PLL_DIV_19_2_MHZ;
+       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       /* The clock for the USBH1 ULPI port will come externally from the PHY. */
+       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+                       MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+       .init           = initialize_otg_port,
+       .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+       .operating_mode = FSL_USB2_DR_DEVICE,
+       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+       .init           = initialize_usbh1_port,
+       .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init babbage_otg_mode(char *options)
+{
+       if (!strcmp(options, "host"))
+               otg_mode_host = 1;
+       else if (!strcmp(options, "device"))
+               otg_mode_host = 0;
+       else
+               pr_info("otg_mode neither \"host\" nor \"device\". "
+                       "Defaulting to device\n");
+       return 0;
+}
+__setup("otg_mode=", babbage_otg_mode);
+
+static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
+       {
+               .modalias = "mtd_dataflash",
+               .max_speed_hz = 25000000,
+               .bus_num = 0,
+               .chip_select = 1,
+               .mode = SPI_MODE_0,
+               .platform_data = NULL,
+       },
+};
+
+static int mx51_babbage_spi_cs[] = {
+       BABBAGE_ECSPI1_CS0,
+       BABBAGE_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
+       .chipselect     = mx51_babbage_spi_cs,
+       .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
+       .cd_type = ESDHC_CD_CONTROLLER,
+       .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
+       .cd_gpio = BABBAGE_SD2_CD,
+       .wp_gpio = BABBAGE_SD2_WP,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_GPIO,
+};
+
+void __init imx51_babbage_common_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+                                        ARRAY_SIZE(mx51babbage_pads));
+}
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx51_babbage_init(void)
+{
+       iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+       iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+               PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
+
+       imx51_soc_init();
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+       get_cpu_op = mx51_get_cpu_op;
+#endif
+       imx51_babbage_common_init();
+
+       imx51_add_imx_uart(0, &uart_pdata);
+       imx51_add_imx_uart(1, NULL);
+       imx51_add_imx_uart(2, &uart_pdata);
+
+       babbage_fec_reset();
+       imx51_add_fec(NULL);
+
+       /* Set the PAD settings for the pwr key. */
+       mxc_iomux_v3_setup_pad(power_key);
+       imx_add_gpio_keys(&imx_button_data);
+
+       imx51_add_imx_i2c(0, &babbage_i2c_data);
+       imx51_add_imx_i2c(1, &babbage_i2c_data);
+       imx51_add_hsi2c(&babbage_hsi2c_data);
+
+       if (otg_mode_host)
+               imx51_add_mxc_ehci_otg(&dr_utmi_config);
+       else {
+               initialize_otg_port(NULL);
+               imx51_add_fsl_usb2_udc(&usb_pdata);
+       }
+
+       gpio_usbh1_active();
+       imx51_add_mxc_ehci_hs(1, &usbh1_config);
+       /* setback USBH1_STP to be function */
+       mxc_iomux_v3_setup_pad(usbh1stp);
+       babbage_usbhub_reset();
+
+       imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
+       imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
+
+       spi_register_board_info(mx51_babbage_spi_board_info,
+               ARRAY_SIZE(mx51_babbage_spi_board_info));
+       imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
+       imx51_add_imx2_wdt(0, NULL);
+}
+
+static void __init mx51_babbage_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx51_babbage_timer = {
+       .init = mx51_babbage_timer_init,
+};
+
+MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
+       /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
+       .atag_offset = 0x100,
+       .map_io = mx51_map_io,
+       .init_early = imx51_init_early,
+       .init_irq = mx51_init_irq,
+       .handle_irq = imx51_handle_irq,
+       .timer = &mx51_babbage_timer,
+       .init_machine = mx51_babbage_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_efikamx.c b/arch/arm/mach-imx/mach-mx51_efikamx.c
new file mode 100644 (file)
index 0000000..3a5ed2d
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2010 Linaro Limited
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+
+#define EFIKAMX_PCBID0         IMX_GPIO_NR(3, 16)
+#define EFIKAMX_PCBID1         IMX_GPIO_NR(3, 17)
+#define EFIKAMX_PCBID2         IMX_GPIO_NR(3, 11)
+
+#define EFIKAMX_BLUE_LED       IMX_GPIO_NR(3, 13)
+#define EFIKAMX_GREEN_LED      IMX_GPIO_NR(3, 14)
+#define EFIKAMX_RED_LED                IMX_GPIO_NR(3, 15)
+
+#define EFIKAMX_POWER_KEY      IMX_GPIO_NR(2, 31)
+
+/* board 1.1 doesn't have same reset gpio */
+#define EFIKAMX_RESET1_1       IMX_GPIO_NR(3, 2)
+#define EFIKAMX_RESET          IMX_GPIO_NR(1, 4)
+
+#define EFIKAMX_POWEROFF       IMX_GPIO_NR(4, 13)
+
+#define EFIKAMX_PMIC           IMX_GPIO_NR(1, 6)
+
+/* the pci ids pin have pull up. they're driven low according to board id */
+#define MX51_PAD_PCBID0        IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID1        IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID2        IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PWRKEY        IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+
+static iomux_v3_cfg_t mx51efikamx_pads[] = {
+       /* board id */
+       MX51_PAD_PCBID0,
+       MX51_PAD_PCBID1,
+       MX51_PAD_PCBID2,
+
+       /* leds */
+       MX51_PAD_CSI1_D9__GPIO3_13,
+       MX51_PAD_CSI1_VSYNC__GPIO3_14,
+       MX51_PAD_CSI1_HSYNC__GPIO3_15,
+
+       /* power key */
+       MX51_PAD_PWRKEY,
+
+       /* reset */
+       MX51_PAD_DI1_PIN13__GPIO3_2,
+       MX51_PAD_GPIO1_4__GPIO1_4,
+
+       /* power off */
+       MX51_PAD_CSI2_VSYNC__GPIO4_13,
+};
+
+/*   PCBID2  PCBID1 PCBID0  STATE
+       1       1      1    ER1:rev1.1
+       1       1      0    ER2:rev1.2
+       1       0      1    ER3:rev1.3
+       1       0      0    ER4:rev1.4
+*/
+static void __init mx51_efikamx_board_id(void)
+{
+       int id;
+
+       /* things are taking time to settle */
+       msleep(150);
+
+       gpio_request(EFIKAMX_PCBID0, "pcbid0");
+       gpio_direction_input(EFIKAMX_PCBID0);
+       gpio_request(EFIKAMX_PCBID1, "pcbid1");
+       gpio_direction_input(EFIKAMX_PCBID1);
+       gpio_request(EFIKAMX_PCBID2, "pcbid2");
+       gpio_direction_input(EFIKAMX_PCBID2);
+
+       id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
+       id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
+       id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
+
+       switch (id) {
+       case 7:
+               system_rev = 0x11;
+               break;
+       case 6:
+               system_rev = 0x12;
+               break;
+       case 5:
+               system_rev = 0x13;
+               break;
+       case 4:
+               system_rev = 0x14;
+               break;
+       default:
+               system_rev = 0x10;
+               break;
+       }
+
+       if ((system_rev == 0x10)
+               || (system_rev == 0x12)
+               || (system_rev == 0x14)) {
+               printk(KERN_WARNING
+                       "EfikaMX: Unsupported board revision 1.%u!\n",
+                       system_rev & 0xf);
+       }
+}
+
+static struct gpio_led mx51_efikamx_leds[] __initdata = {
+       {
+               .name = "efikamx:green",
+               .default_trigger = "default-on",
+               .gpio = EFIKAMX_GREEN_LED,
+       },
+       {
+               .name = "efikamx:red",
+               .default_trigger = "ide-disk",
+               .gpio = EFIKAMX_RED_LED,
+       },
+       {
+               .name = "efikamx:blue",
+               .default_trigger = "mmc0",
+               .gpio = EFIKAMX_BLUE_LED,
+       },
+};
+
+static const struct gpio_led_platform_data
+               mx51_efikamx_leds_data __initconst = {
+       .leds = mx51_efikamx_leds,
+       .num_leds = ARRAY_SIZE(mx51_efikamx_leds),
+};
+
+static struct esdhc_platform_data sd_pdata = {
+       .cd_type = ESDHC_CD_CONTROLLER,
+       .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct gpio_keys_button mx51_efikamx_powerkey[] = {
+       {
+               .code = KEY_POWER,
+               .gpio = EFIKAMX_POWER_KEY,
+               .type = EV_PWR,
+               .desc = "Power Button (CM)",
+               .wakeup = 1,
+               .debounce_interval = 10, /* ms */
+       },
+};
+
+static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
+       .buttons = mx51_efikamx_powerkey,
+       .nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
+};
+
+static void mx51_efikamx_restart(char mode, const char *cmd)
+{
+       if (system_rev == 0x11)
+               gpio_direction_output(EFIKAMX_RESET1_1, 0);
+       else
+               gpio_direction_output(EFIKAMX_RESET, 0);
+}
+
+static struct regulator *pwgt1, *pwgt2, *coincell;
+
+static void mx51_efikamx_power_off(void)
+{
+       if (!IS_ERR(coincell))
+               regulator_disable(coincell);
+
+       if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+               regulator_disable(pwgt2);
+               regulator_disable(pwgt1);
+       }
+       gpio_direction_output(EFIKAMX_POWEROFF, 1);
+}
+
+static int __init mx51_efikamx_power_init(void)
+{
+       if (machine_is_mx51_efikamx()) {
+               pwgt1 = regulator_get(NULL, "pwgt1");
+               pwgt2 = regulator_get(NULL, "pwgt2");
+               if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+                       regulator_enable(pwgt1);
+                       regulator_enable(pwgt2);
+               }
+               gpio_request(EFIKAMX_POWEROFF, "poweroff");
+               pm_power_off = mx51_efikamx_power_off;
+
+               /* enable coincell charger. maybe need a small power driver ? */
+               coincell = regulator_get(NULL, "coincell");
+               if (!IS_ERR(coincell)) {
+                       regulator_set_voltage(coincell, 3000000, 3000000);
+                       regulator_enable(coincell);
+               }
+
+               regulator_has_full_constraints();
+       }
+
+       return 0;
+}
+late_initcall(mx51_efikamx_power_init);
+
+static void __init mx51_efikamx_init(void)
+{
+       imx51_soc_init();
+
+       mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
+                                       ARRAY_SIZE(mx51efikamx_pads));
+       efika_board_common_init();
+
+       mx51_efikamx_board_id();
+
+       /* on < 1.2 boards both SD controllers are used */
+       if (system_rev < 0x12) {
+               imx51_add_sdhci_esdhc_imx(0, NULL);
+               imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
+               mx51_efikamx_leds[2].default_trigger = "mmc1";
+       } else
+               imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
+
+       gpio_led_register_device(-1, &mx51_efikamx_leds_data);
+       imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
+
+       if (system_rev == 0x11) {
+               gpio_request(EFIKAMX_RESET1_1, "reset");
+               gpio_direction_output(EFIKAMX_RESET1_1, 1);
+       } else {
+               gpio_request(EFIKAMX_RESET, "reset");
+               gpio_direction_output(EFIKAMX_RESET, 1);
+       }
+
+       /*
+        * enable wifi by default only on mx
+        * sb and mx have same wlan pin but the value to enable it are
+        * different :/
+        */
+       gpio_request(EFIKA_WLAN_EN, "wlan_en");
+       gpio_direction_output(EFIKA_WLAN_EN, 0);
+       msleep(10);
+
+       gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
+       gpio_direction_output(EFIKA_WLAN_RESET, 0);
+       msleep(10);
+       gpio_set_value(EFIKA_WLAN_RESET, 1);
+}
+
+static void __init mx51_efikamx_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikamx_timer = {
+       .init = mx51_efikamx_timer_init,
+};
+
+MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
+       /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
+       .atag_offset = 0x100,
+       .map_io = mx51_map_io,
+       .init_early = imx51_init_early,
+       .init_irq = mx51_init_irq,
+       .handle_irq = imx51_handle_irq,
+       .timer = &mx51_efikamx_timer,
+       .init_machine = mx51_efikamx_init,
+       .restart = mx51_efikamx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_efikasb.c b/arch/arm/mach-imx/mach-mx51_efikasb.c
new file mode 100644 (file)
index 0000000..ea5f65b
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+
+#define EFIKASB_USBH2_STP      IMX_GPIO_NR(2, 20)
+#define EFIKASB_GREEN_LED      IMX_GPIO_NR(1, 3)
+#define EFIKASB_WHITE_LED      IMX_GPIO_NR(2, 25)
+#define EFIKASB_PCBID0         IMX_GPIO_NR(2, 28)
+#define EFIKASB_PCBID1         IMX_GPIO_NR(2, 29)
+#define EFIKASB_PWRKEY         IMX_GPIO_NR(2, 31)
+#define EFIKASB_LID            IMX_GPIO_NR(3, 14)
+#define EFIKASB_POWEROFF       IMX_GPIO_NR(4, 13)
+#define EFIKASB_RFKILL         IMX_GPIO_NR(3, 1)
+
+#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+#define MX51_PAD_SD1_CD        IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+
+static iomux_v3_cfg_t mx51efikasb_pads[] = {
+       /* USB HOST2 */
+       MX51_PAD_EIM_D16__USBH2_DATA0,
+       MX51_PAD_EIM_D17__USBH2_DATA1,
+       MX51_PAD_EIM_D18__USBH2_DATA2,
+       MX51_PAD_EIM_D19__USBH2_DATA3,
+       MX51_PAD_EIM_D20__USBH2_DATA4,
+       MX51_PAD_EIM_D21__USBH2_DATA5,
+       MX51_PAD_EIM_D22__USBH2_DATA6,
+       MX51_PAD_EIM_D23__USBH2_DATA7,
+       MX51_PAD_EIM_A24__USBH2_CLK,
+       MX51_PAD_EIM_A25__USBH2_DIR,
+       MX51_PAD_EIM_A26__USBH2_STP,
+       MX51_PAD_EIM_A27__USBH2_NXT,
+
+       /* leds */
+       MX51_PAD_EIM_CS0__GPIO2_25,
+       MX51_PAD_GPIO1_3__GPIO1_3,
+
+       /* pcb id */
+       MX51_PAD_EIM_CS3__GPIO2_28,
+       MX51_PAD_EIM_CS4__GPIO2_29,
+
+       /* lid */
+       MX51_PAD_CSI1_VSYNC__GPIO3_14,
+
+       /* power key*/
+       MX51_PAD_PWRKEY,
+
+       /* wifi/bt button */
+       MX51_PAD_DI1_PIN12__GPIO3_1,
+
+       /* power off */
+       MX51_PAD_CSI2_VSYNC__GPIO4_13,
+
+       /* wdog reset */
+       MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
+
+       /* BT */
+       MX51_PAD_EIM_A17__GPIO2_11,
+
+       MX51_PAD_SD1_CD,
+};
+
+static int initialize_usbh2_port(struct platform_device *pdev)
+{
+       iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
+       iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
+
+       mxc_iomux_v3_setup_pad(usbh2gpio);
+       gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
+       gpio_direction_output(EFIKASB_USBH2_STP, 0);
+       msleep(1);
+       gpio_set_value(EFIKASB_USBH2_STP, 1);
+       msleep(1);
+
+       gpio_free(EFIKASB_USBH2_STP);
+       mxc_iomux_v3_setup_pad(usbh2stp);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
+       .init   = initialize_usbh2_port,
+       .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void __init mx51_efikasb_usb(void)
+{
+       usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+                       ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+       if (usbh2_config.otg)
+               imx51_add_mxc_ehci_hs(2, &usbh2_config);
+}
+
+static const struct gpio_led mx51_efikasb_leds[] __initconst = {
+       {
+               .name = "efikasb:green",
+               .default_trigger = "default-on",
+               .gpio = EFIKASB_GREEN_LED,
+               .active_low = 1,
+       },
+       {
+               .name = "efikasb:white",
+               .default_trigger = "caps",
+               .gpio = EFIKASB_WHITE_LED,
+       },
+};
+
+static const struct gpio_led_platform_data
+               mx51_efikasb_leds_data __initconst = {
+       .leds = mx51_efikasb_leds,
+       .num_leds = ARRAY_SIZE(mx51_efikasb_leds),
+};
+
+static struct gpio_keys_button mx51_efikasb_keys[] = {
+       {
+               .code = KEY_POWER,
+               .gpio = EFIKASB_PWRKEY,
+               .type = EV_KEY,
+               .desc = "Power Button",
+               .wakeup = 1,
+               .active_low = 1,
+       },
+       {
+               .code = SW_LID,
+               .gpio = EFIKASB_LID,
+               .type = EV_SW,
+               .desc = "Lid Switch",
+               .active_low = 1,
+       },
+       {
+               .code = KEY_RFKILL,
+               .gpio = EFIKASB_RFKILL,
+               .type = EV_KEY,
+               .desc = "rfkill",
+               .active_low = 1,
+       },
+};
+
+static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
+       .buttons = mx51_efikasb_keys,
+       .nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
+};
+
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27)
+       .cd_gpio = EFIKASB_SD1_CD,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+       .cd_type = ESDHC_CD_CONTROLLER,
+       .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct regulator *pwgt1, *pwgt2;
+
+static void mx51_efikasb_power_off(void)
+{
+       gpio_set_value(EFIKA_USB_PHY_RESET, 0);
+
+       if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+               regulator_disable(pwgt2);
+               regulator_disable(pwgt1);
+       }
+       gpio_direction_output(EFIKASB_POWEROFF, 1);
+}
+
+static int __init mx51_efikasb_power_init(void)
+{
+       if (machine_is_mx51_efikasb()) {
+               pwgt1 = regulator_get(NULL, "pwgt1");
+               pwgt2 = regulator_get(NULL, "pwgt2");
+               if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+                       regulator_enable(pwgt1);
+                       regulator_enable(pwgt2);
+               }
+               gpio_request(EFIKASB_POWEROFF, "poweroff");
+               pm_power_off = mx51_efikasb_power_off;
+
+               regulator_has_full_constraints();
+       }
+
+       return 0;
+}
+late_initcall(mx51_efikasb_power_init);
+
+/* 01     R1.3 board
+   10     R2.0 board */
+static void __init mx51_efikasb_board_id(void)
+{
+       int id;
+
+       gpio_request(EFIKASB_PCBID0, "pcb id0");
+       gpio_direction_input(EFIKASB_PCBID0);
+       gpio_request(EFIKASB_PCBID1, "pcb id1");
+       gpio_direction_input(EFIKASB_PCBID1);
+
+       id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
+       id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
+
+       switch (id) {
+       default:
+               break;
+       case 1:
+               system_rev = 0x13;
+               break;
+       case 2:
+               system_rev = 0x20;
+               break;
+       }
+}
+
+static void __init efikasb_board_init(void)
+{
+       imx51_soc_init();
+
+       mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
+                                       ARRAY_SIZE(mx51efikasb_pads));
+       efika_board_common_init();
+
+       mx51_efikasb_board_id();
+       mx51_efikasb_usb();
+       imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+       imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
+
+       gpio_led_register_device(-1, &mx51_efikasb_leds_data);
+       imx_add_gpio_keys(&mx51_efikasb_keys_data);
+}
+
+static void __init mx51_efikasb_timer_init(void)
+{
+       mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikasb_timer = {
+       .init   = mx51_efikasb_timer_init,
+};
+
+MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
+       .atag_offset = 0x100,
+       .map_io = mx51_map_io,
+       .init_early = imx51_init_early,
+       .init_irq = mx51_init_irq,
+       .handle_irq = imx51_handle_irq,
+       .init_machine =  efikasb_board_init,
+       .timer = &mx51_efikasb_timer,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c
new file mode 100644 (file)
index 0000000..753f4fc
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 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 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/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B     IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD             IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP             IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B       IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN         IMX_GPIO_NR(4, 0)
+#define ARD_HOME                       IMX_GPIO_NR(5, 10)
+#define ARD_BACK                       IMX_GPIO_NR(5, 11)
+#define ARD_PROG                       IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP           IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+       /* UART1 */
+       MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+       MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+       /* WEIM for CS1 */
+       MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+       MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+       MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+       MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+       MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+       MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+       MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+       MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+       MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+       MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+       MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+       MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+       MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+       MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+       MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+       MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+       MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+       MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+       MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+       MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+       MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+       MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+       MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+       MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+       MX53_PAD_EIM_OE__EMI_WEIM_OE,
+       MX53_PAD_EIM_RW__EMI_WEIM_RW,
+       MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+       /* SDHC1 */
+       MX53_PAD_SD1_CMD__ESDHC1_CMD,
+       MX53_PAD_SD1_CLK__ESDHC1_CLK,
+       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+       MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+       MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+       MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+       MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+       MX53_PAD_GPIO_1__GPIO1_1,
+       MX53_PAD_GPIO_9__GPIO1_9,
+       /* I2C2 */
+       MX53_PAD_EIM_EB2__I2C2_SCL,
+       MX53_PAD_KEY_ROW3__I2C2_SDA,
+       /* I2C3 */
+       MX53_PAD_GPIO_3__I2C3_SCL,
+       MX53_PAD_GPIO_16__I2C3_SDA,
+       /* GPIO */
+       MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
+       MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
+       MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
+       MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
+       MX53_PAD_GPIO_10__GPIO4_0,              /* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)   \
+{                                                      \
+       .gpio           = gpio_num,                             \
+       .type           = EV_KEY,                               \
+       .code           = ev_code,                              \
+       .active_low     = act_low,                              \
+       .desc           = "btn " descr,                 \
+       .wakeup         = wake,                                 \
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+       GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+       GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+       GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+       GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+       GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+       .buttons        = ard_buttons,
+       .nbuttons       = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+       {
+               .start = MX53_CS1_64MB_BASE_ADDR,
+               .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+               .end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+       .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+       .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+       .name = "smsc911x",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+       .resource = ard_smsc911x_resources,
+       .dev = {
+               .platform_data = &ard_smsc911x_config,
+       },
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+       .cd_gpio = ARD_SD1_CD,
+       .wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+       .bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+       .bitrate = 400000,
+};
+
+static void __init mx53_ard_io_init(void)
+{
+       gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+       gpio_direction_input(ARD_ETHERNET_INT_B);
+
+       gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+       gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+       u32 reg;
+       void __iomem *weim_base, *iomuxc_base;
+
+       weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+       if (!weim_base)
+               return -ENOMEM;
+
+       iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+       if (!iomuxc_base) {
+               iounmap(weim_base);
+               return -ENOMEM;
+       }
+
+       /* CS1 timings for LAN9220 */
+       writel(0x20001, (weim_base + 0x18));
+       writel(0x0, (weim_base + 0x1C));
+       writel(0x16000202, (weim_base + 0x20));
+       writel(0x00000002, (weim_base + 0x24));
+       writel(0x16002082, (weim_base + 0x28));
+       writel(0x00000000, (weim_base + 0x2C));
+       writel(0x00000000, (weim_base + 0x90));
+
+       /* specify 64 MB on CS1 and CS0 on GPR1 */
+       reg = readl(iomuxc_base + 0x4);
+       reg &= ~0x3F;
+       reg |= 0x1B;
+       writel(reg, (iomuxc_base + 0x4));
+
+       iounmap(iomuxc_base);
+       iounmap(weim_base);
+
+       return 0;
+}
+
+void __init imx53_ard_common_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+                                        ARRAY_SIZE(mx53_ard_pads));
+       weim_cs_config();
+}
+
+static struct platform_device *devices[] __initdata = {
+       &ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+       imx53_soc_init();
+       imx53_add_imx_uart(0, NULL);
+
+       imx53_ard_common_init();
+       mx53_ard_io_init();
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
+       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
+       imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
+       imx_add_gpio_keys(&ard_button_data);
+       imx53_add_ahci_imx();
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+       mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+       .init   = mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+       .map_io = mx53_map_io,
+       .init_early = imx53_init_early,
+       .init_irq = mx53_init_irq,
+       .handle_irq = imx53_handle_irq,
+       .timer = &mx53_ard_timer,
+       .init_machine = mx53_ard_board_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_evk.c b/arch/arm/mach-imx/mach-mx53_evk.c
new file mode 100644 (file)
index 0000000..5a72188
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/iomux-mx53.h>
+
+#define MX53_EVK_FEC_PHY_RST   IMX_GPIO_NR(7, 6)
+#define EVK_ECSPI1_CS0         IMX_GPIO_NR(2, 30)
+#define EVK_ECSPI1_CS1         IMX_GPIO_NR(3, 19)
+#define MX53EVK_LED            IMX_GPIO_NR(7, 7)
+
+#include "devices-imx53.h"
+
+static iomux_v3_cfg_t mx53_evk_pads[] = {
+       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+       MX53_PAD_PATA_DIOR__UART2_RTS,
+       MX53_PAD_PATA_INTRQ__UART2_CTS,
+
+       MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+       MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+
+       MX53_PAD_EIM_D16__ECSPI1_SCLK,
+       MX53_PAD_EIM_D17__ECSPI1_MISO,
+       MX53_PAD_EIM_D18__ECSPI1_MOSI,
+
+       /* ecspi chip select lines */
+       MX53_PAD_EIM_EB2__GPIO2_30,
+       MX53_PAD_EIM_D19__GPIO3_19,
+       /* LED */
+       MX53_PAD_PATA_DA_1__GPIO7_7,
+};
+
+static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct gpio_led mx53evk_leds[] __initconst = {
+       {
+               .name                   = "green",
+               .default_trigger        = "heartbeat",
+               .gpio                   = MX53EVK_LED,
+       },
+};
+
+static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
+       .leds           = mx53evk_leds,
+       .num_leds       = ARRAY_SIZE(mx53evk_leds),
+};
+
+static inline void mx53_evk_init_uart(void)
+{
+       imx53_add_imx_uart(0, NULL);
+       imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
+       imx53_add_imx_uart(2, NULL);
+}
+
+static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+static inline void mx53_evk_fec_reset(void)
+{
+       int ret;
+
+       /* reset FEC PHY */
+       ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
+                                                       "fec-phy-reset");
+       if (ret) {
+               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+               return;
+       }
+       msleep(1);
+       gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
+       .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
+       {
+               .modalias = "mtd_dataflash",
+               .max_speed_hz = 25000000,
+               .bus_num = 0,
+               .chip_select = 1,
+               .mode = SPI_MODE_0,
+               .platform_data = NULL,
+       },
+};
+
+static int mx53_evk_spi_cs[] = {
+       EVK_ECSPI1_CS0,
+       EVK_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx53_evk_spi_data __initconst = {
+       .chipselect     = mx53_evk_spi_cs,
+       .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
+};
+
+void __init imx53_evk_common_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+                                        ARRAY_SIZE(mx53_evk_pads));
+}
+
+static void __init mx53_evk_board_init(void)
+{
+       imx53_soc_init();
+       imx53_evk_common_init();
+
+       mx53_evk_init_uart();
+       mx53_evk_fec_reset();
+       imx53_add_fec(&mx53_evk_fec_pdata);
+
+       imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
+       imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
+
+       imx53_add_sdhci_esdhc_imx(0, NULL);
+       imx53_add_sdhci_esdhc_imx(1, NULL);
+
+       spi_register_board_info(mx53_evk_spi_board_info,
+               ARRAY_SIZE(mx53_evk_spi_board_info));
+       imx53_add_ecspi(0, &mx53_evk_spi_data);
+       imx53_add_imx2_wdt(0, NULL);
+       gpio_led_register_device(-1, &mx53evk_leds_data);
+}
+
+static void __init mx53_evk_timer_init(void)
+{
+       mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_evk_timer = {
+       .init   = mx53_evk_timer_init,
+};
+
+MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
+       .map_io = mx53_map_io,
+       .init_early = imx53_init_early,
+       .init_irq = mx53_init_irq,
+       .handle_irq = imx53_handle_irq,
+       .timer = &mx53_evk_timer,
+       .init_machine = mx53_evk_board_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_loco.c b/arch/arm/mach-imx/mach-mx53_loco.c
new file mode 100644 (file)
index 0000000..37f67ca
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 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 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/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define MX53_LOCO_POWER                        IMX_GPIO_NR(1, 8)
+#define MX53_LOCO_UI1                  IMX_GPIO_NR(2, 14)
+#define MX53_LOCO_UI2                  IMX_GPIO_NR(2, 15)
+#define LOCO_FEC_PHY_RST               IMX_GPIO_NR(7, 6)
+#define LOCO_LED                       IMX_GPIO_NR(7, 7)
+#define LOCO_SD3_CD                    IMX_GPIO_NR(3, 11)
+#define LOCO_SD3_WP                    IMX_GPIO_NR(3, 12)
+#define LOCO_SD1_CD                    IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN                  IMX_GPIO_NR(6, 14)
+
+static iomux_v3_cfg_t mx53_loco_pads[] = {
+       /* FEC */
+       MX53_PAD_FEC_MDC__FEC_MDC,
+       MX53_PAD_FEC_MDIO__FEC_MDIO,
+       MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
+       MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+       MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
+       MX53_PAD_FEC_RXD1__FEC_RDATA_1,
+       MX53_PAD_FEC_RXD0__FEC_RDATA_0,
+       MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+       MX53_PAD_FEC_TXD1__FEC_TDATA_1,
+       MX53_PAD_FEC_TXD0__FEC_TDATA_0,
+       /* FEC_nRST */
+       MX53_PAD_PATA_DA_0__GPIO7_6,
+       /* FEC_nINT */
+       MX53_PAD_PATA_DATA4__GPIO2_4,
+       /* AUDMUX5 */
+       MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
+       MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
+       MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
+       MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+       /* I2C1 */
+       MX53_PAD_CSI0_DAT8__I2C1_SDA,
+       MX53_PAD_CSI0_DAT9__I2C1_SCL,
+       MX53_PAD_NANDF_CS1__GPIO6_14,   /* Accelerometer Enable */
+       /* I2C2 */
+       MX53_PAD_KEY_COL3__I2C2_SCL,
+       MX53_PAD_KEY_ROW3__I2C2_SDA,
+       /* SD1 */
+       MX53_PAD_SD1_CMD__ESDHC1_CMD,
+       MX53_PAD_SD1_CLK__ESDHC1_CLK,
+       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+       /* SD1_CD */
+       MX53_PAD_EIM_DA13__GPIO3_13,
+       /* SD3 */
+       MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+       MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+       MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+       MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+       MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+       MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+       MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+       MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+       MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+       MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+       /* SD3_CD */
+       MX53_PAD_EIM_DA11__GPIO3_11,
+       /* SD3_WP */
+       MX53_PAD_EIM_DA12__GPIO3_12,
+       /* VGA */
+       MX53_PAD_EIM_OE__IPU_DI1_PIN7,
+       MX53_PAD_EIM_RW__IPU_DI1_PIN8,
+       /* DISPLB */
+       MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
+       MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
+       MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
+       MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
+       /* DISP0_POWER_EN */
+       MX53_PAD_EIM_D24__GPIO3_24,
+       /* DISP0 DET INT */
+       MX53_PAD_EIM_D31__GPIO3_31,
+       /* LVDS */
+       MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+       MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+       MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+       MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+       MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+       MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+       MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+       MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+       MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+       MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+       /* I2C1 */
+       MX53_PAD_CSI0_DAT8__I2C1_SDA,
+       MX53_PAD_CSI0_DAT9__I2C1_SCL,
+       /* UART1 */
+       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+       /* CSI0 */
+       MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
+       MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
+       MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
+       MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
+       MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
+       MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
+       MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
+       MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
+       MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
+       MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
+       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
+       /* DISPLAY */
+       MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+       MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+       MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+       MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+       MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+       MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+       MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+       MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+       MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+       MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+       MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+       MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+       MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+       MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+       MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+       MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+       MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+       MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+       MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+       MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+       MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+       MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+       MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+       MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+       MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+       MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+       MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+       MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+       /* Audio CLK*/
+       MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
+       /* PWM */
+       MX53_PAD_GPIO_1__PWM2_PWMO,
+       /* SPDIF */
+       MX53_PAD_GPIO_7__SPDIF_PLOCK,
+       MX53_PAD_GPIO_17__SPDIF_OUT1,
+       /* GPIO */
+       MX53_PAD_PATA_DA_1__GPIO7_7,            /* LED */
+       MX53_PAD_PATA_DA_2__GPIO7_8,
+       MX53_PAD_PATA_DATA5__GPIO2_5,
+       MX53_PAD_PATA_DATA6__GPIO2_6,
+       MX53_PAD_PATA_DATA14__GPIO2_14,
+       MX53_PAD_PATA_DATA15__GPIO2_15,
+       MX53_PAD_PATA_INTRQ__GPIO7_2,
+       MX53_PAD_EIM_WAIT__GPIO5_0,
+       MX53_PAD_NANDF_WP_B__GPIO6_9,
+       MX53_PAD_NANDF_RB0__GPIO6_10,
+       MX53_PAD_NANDF_CS1__GPIO6_14,
+       MX53_PAD_NANDF_CS2__GPIO6_15,
+       MX53_PAD_NANDF_CS3__GPIO6_16,
+       MX53_PAD_GPIO_5__GPIO1_5,
+       MX53_PAD_GPIO_16__GPIO7_11,
+       MX53_PAD_GPIO_8__GPIO1_8,
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)   \
+{                                                              \
+       .gpio           = gpio_num,                             \
+       .type           = EV_KEY,                               \
+       .code           = ev_code,                              \
+       .active_low     = act_low,                              \
+       .desc           = "btn " descr,                         \
+       .wakeup         = wake,                                 \
+}
+
+static struct gpio_keys_button loco_buttons[] = {
+       GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
+       GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
+       GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data loco_button_data __initconst = {
+       .buttons        = loco_buttons,
+       .nbuttons       = ARRAY_SIZE(loco_buttons),
+};
+
+static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
+       .cd_gpio = LOCO_SD1_CD,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_NONE,
+};
+
+static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
+       .cd_gpio = LOCO_SD3_CD,
+       .wp_gpio = LOCO_SD3_WP,
+       .cd_type = ESDHC_CD_GPIO,
+       .wp_type = ESDHC_WP_GPIO,
+};
+
+static inline void mx53_loco_fec_reset(void)
+{
+       int ret;
+
+       /* reset FEC PHY */
+       ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
+       if (ret) {
+               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+               return;
+       }
+       gpio_direction_output(LOCO_FEC_PHY_RST, 0);
+       msleep(1);
+       gpio_set_value(LOCO_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_loco_fec_data __initconst = {
+       .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+static const struct gpio_led mx53loco_leds[] __initconst = {
+       {
+               .name                   = "green",
+               .default_trigger        = "heartbeat",
+               .gpio                   = LOCO_LED,
+       },
+};
+
+static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
+       .leds           = mx53loco_leds,
+       .num_leds       = ARRAY_SIZE(mx53loco_leds),
+};
+
+void __init imx53_qsb_common_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+                                        ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("mma8450", 0x1C),
+       },
+};
+
+static void __init mx53_loco_board_init(void)
+{
+       int ret;
+       imx53_soc_init();
+       imx53_qsb_common_init();
+
+       imx53_add_imx_uart(0, NULL);
+       mx53_loco_fec_reset();
+       imx53_add_fec(&mx53_loco_fec_data);
+       imx53_add_imx2_wdt(0, NULL);
+
+       ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+       if (ret)
+               pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+       i2c_register_board_info(0, mx53loco_i2c_devices,
+                               ARRAY_SIZE(mx53loco_i2c_devices));
+       imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
+       imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
+       imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
+       imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
+       imx_add_gpio_keys(&loco_button_data);
+       gpio_led_register_device(-1, &mx53loco_leds_data);
+       imx53_add_ahci_imx();
+}
+
+static void __init mx53_loco_timer_init(void)
+{
+       mx53_clocks_init(32768, 24000000, 0, 0);
+}
+
+static struct sys_timer mx53_loco_timer = {
+       .init   = mx53_loco_timer_init,
+};
+
+MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
+       .map_io = mx53_map_io,
+       .init_early = imx53_init_early,
+       .init_irq = mx53_init_irq,
+       .handle_irq = imx53_handle_irq,
+       .timer = &mx53_loco_timer,
+       .init_machine = mx53_loco_board_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_smd.c b/arch/arm/mach-imx/mach-mx53_smd.c
new file mode 100644 (file)
index 0000000..8e972c5
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 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 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/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define SMD_FEC_PHY_RST                IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
+
+static iomux_v3_cfg_t mx53_smd_pads[] = {
+       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+
+       MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+       MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+       MX53_PAD_PATA_DA_1__UART3_CTS,
+       MX53_PAD_PATA_DA_2__UART3_RTS,
+       /* I2C1 */
+       MX53_PAD_CSI0_DAT8__I2C1_SDA,
+       MX53_PAD_CSI0_DAT9__I2C1_SCL,
+       /* SD1 */
+       MX53_PAD_SD1_CMD__ESDHC1_CMD,
+       MX53_PAD_SD1_CLK__ESDHC1_CLK,
+       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+       /* SD2 */
+       MX53_PAD_SD2_CMD__ESDHC2_CMD,
+       MX53_PAD_SD2_CLK__ESDHC2_CLK,
+       MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
+       MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
+       MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
+       MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
+       /* SD3 */
+       MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+       MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+       MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+       MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+       MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+       MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+       MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+       MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+       MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+       MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+};
+
+static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mx53_smd_init_uart(void)
+{
+       imx53_add_imx_uart(0, NULL);
+       imx53_add_imx_uart(1, NULL);
+       imx53_add_imx_uart(2, &mx53_smd_uart_data);
+}
+
+static inline void mx53_smd_fec_reset(void)
+{
+       int ret;
+
+       /* reset FEC PHY */
+       ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
+       if (ret) {
+               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+               return;
+       }
+       gpio_direction_output(SMD_FEC_PHY_RST, 0);
+       msleep(1);
+       gpio_set_value(SMD_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_smd_fec_data __initconst = {
+       .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
+       .bitrate = 100000,
+};
+
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+       int ret;
+
+       /* Enable SATA PWR */
+       ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+                       GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+       if (ret) {
+               pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+               return;
+       }
+}
+
+void __init imx53_smd_common_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+                                        ARRAY_SIZE(mx53_smd_pads));
+}
+
+static void __init mx53_smd_board_init(void)
+{
+       imx53_soc_init();
+       imx53_smd_common_init();
+
+       mx53_smd_init_uart();
+       mx53_smd_fec_reset();
+       imx53_add_fec(&mx53_smd_fec_data);
+       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
+       imx53_add_sdhci_esdhc_imx(0, NULL);
+       imx53_add_sdhci_esdhc_imx(1, NULL);
+       imx53_add_sdhci_esdhc_imx(2, NULL);
+       mx53_smd_ahci_pwr_on();
+       imx53_add_ahci_imx();
+}
+
+static void __init mx53_smd_timer_init(void)
+{
+       mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_smd_timer = {
+       .init   = mx53_smd_timer_init,
+};
+
+MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
+       .map_io = mx53_map_io,
+       .init_early = imx53_init_early,
+       .init_irq = mx53_init_irq,
+       .handle_irq = imx53_handle_irq,
+       .timer = &mx53_smd_timer,
+       .init_machine = mx53_smd_board_init,
+       .restart        = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
new file mode 100644 (file)
index 0000000..bc17dfe
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License.  You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/iomux-v3.h>
+
+static struct clk *gpc_dvfs_clk;
+
+static void imx5_idle(void)
+{
+       if (!need_resched()) {
+               /* gpc clock is needed for SRPG */
+               if (gpc_dvfs_clk == NULL) {
+                       gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+                       if (IS_ERR(gpc_dvfs_clk))
+                               goto err0;
+               }
+               clk_enable(gpc_dvfs_clk);
+               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+               if (tzic_enable_wake())
+                       goto err1;
+               cpu_do_idle();
+err1:
+               clk_disable(gpc_dvfs_clk);
+       }
+err0:
+       local_irq_enable();
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+       imx_map_entry(MX50, TZIC, MT_DEVICE),
+       imx_map_entry(MX50, SPBA0, MT_DEVICE),
+       imx_map_entry(MX50, AIPS1, MT_DEVICE),
+       imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
+/*
+ * Define the MX51 memory map.
+ */
+static struct map_desc mx51_io_desc[] __initdata = {
+       imx_map_entry(MX51, TZIC, MT_DEVICE),
+       imx_map_entry(MX51, IRAM, MT_DEVICE),
+       imx_map_entry(MX51, AIPS1, MT_DEVICE),
+       imx_map_entry(MX51, SPBA0, MT_DEVICE),
+       imx_map_entry(MX51, AIPS2, MT_DEVICE),
+};
+
+/*
+ * Define the MX53 memory map.
+ */
+static struct map_desc mx53_io_desc[] __initdata = {
+       imx_map_entry(MX53, TZIC, MT_DEVICE),
+       imx_map_entry(MX53, AIPS1, MT_DEVICE),
+       imx_map_entry(MX53, SPBA0, MT_DEVICE),
+       imx_map_entry(MX53, AIPS2, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx50_map_io(void)
+{
+       iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
+void __init mx51_map_io(void)
+{
+       iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
+}
+
+void __init mx53_map_io(void)
+{
+       iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
+       mxc_set_cpu_type(MXC_CPU_MX50);
+       mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
+       mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
+}
+
+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));
+       pm_idle = imx5_idle;
+}
+
+void __init imx53_init_early(void)
+{
+       mxc_set_cpu_type(MXC_CPU_MX53);
+       mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
+       mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
+}
+
+void __init mx50_init_irq(void)
+{
+       tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
+
+void __init mx51_init_irq(void)
+{
+       tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
+}
+
+void __init mx53_init_irq(void)
+{
+       tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
+       .ap_2_ap_addr = 642,
+       .uart_2_mcu_addr = 817,
+       .mcu_2_app_addr = 747,
+       .mcu_2_shp_addr = 961,
+       .ata_2_mcu_addr = 1473,
+       .mcu_2_ata_addr = 1392,
+       .app_2_per_addr = 1033,
+       .app_2_mcu_addr = 683,
+       .shp_2_per_addr = 1251,
+       .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_platform_data imx51_sdma_pdata __initdata = {
+       .fw_name = "sdma-imx51.bin",
+       .script_addrs = &imx51_sdma_script,
+};
+
+static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
+       .ap_2_ap_addr = 642,
+       .app_2_mcu_addr = 683,
+       .mcu_2_app_addr = 747,
+       .uart_2_mcu_addr = 817,
+       .shp_2_mcu_addr = 891,
+       .mcu_2_shp_addr = 960,
+       .uartsh_2_mcu_addr = 1032,
+       .spdif_2_mcu_addr = 1100,
+       .mcu_2_spdif_addr = 1134,
+       .firi_2_mcu_addr = 1193,
+       .mcu_2_firi_addr = 1290,
+};
+
+static struct sdma_platform_data imx53_sdma_pdata __initdata = {
+       .fw_name = "sdma-imx53.bin",
+       .script_addrs = &imx53_sdma_script,
+};
+
+void __init imx50_soc_init(void)
+{
+       /* i.mx50 has the i.mx31 type gpio */
+       mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+       mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+       mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+       mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+       mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+       mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
+void __init imx51_soc_init(void)
+{
+       /* i.mx51 has the i.mx31 type gpio */
+       mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+       mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+       mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+       mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
+
+       /* i.mx51 has the i.mx35 type sdma */
+       imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+}
+
+void __init imx53_soc_init(void)
+{
+       /* i.mx53 has the i.mx31 type gpio */
+       mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
+       mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
+       mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
+       mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
+       mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
+       mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
+       mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+
+       /* i.mx53 has the i.mx35 type sdma */
+       imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+}
diff --git a/arch/arm/mach-imx/mx51_efika.c b/arch/arm/mach-imx/mx51_efika.c
new file mode 100644 (file)
index 0000000..ec6ca91
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+#include "cpu_op-mx51.h"
+
+#define MX51_USB_CTRL_1_OFFSET          0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
+#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
+
+#define EFIKAMX_USB_HUB_RESET  IMX_GPIO_NR(1, 5)
+#define EFIKAMX_USBH1_STP      IMX_GPIO_NR(1, 27)
+
+#define EFIKAMX_SPI_CS0                IMX_GPIO_NR(4, 24)
+#define EFIKAMX_SPI_CS1                IMX_GPIO_NR(4, 25)
+
+#define EFIKAMX_PMIC           IMX_GPIO_NR(1, 6)
+
+static iomux_v3_cfg_t mx51efika_pads[] = {
+       /* UART1 */
+       MX51_PAD_UART1_RXD__UART1_RXD,
+       MX51_PAD_UART1_TXD__UART1_TXD,
+       MX51_PAD_UART1_RTS__UART1_RTS,
+       MX51_PAD_UART1_CTS__UART1_CTS,
+
+       /* SD 1 */
+       MX51_PAD_SD1_CMD__SD1_CMD,
+       MX51_PAD_SD1_CLK__SD1_CLK,
+       MX51_PAD_SD1_DATA0__SD1_DATA0,
+       MX51_PAD_SD1_DATA1__SD1_DATA1,
+       MX51_PAD_SD1_DATA2__SD1_DATA2,
+       MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+       /* SD 2 */
+       MX51_PAD_SD2_CMD__SD2_CMD,
+       MX51_PAD_SD2_CLK__SD2_CLK,
+       MX51_PAD_SD2_DATA0__SD2_DATA0,
+       MX51_PAD_SD2_DATA1__SD2_DATA1,
+       MX51_PAD_SD2_DATA2__SD2_DATA2,
+       MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+       /* SD/MMC WP/CD */
+       MX51_PAD_GPIO1_0__SD1_CD,
+       MX51_PAD_GPIO1_1__SD1_WP,
+       MX51_PAD_GPIO1_7__SD2_WP,
+       MX51_PAD_GPIO1_8__SD2_CD,
+
+       /* spi */
+       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+       MX51_PAD_CSPI1_SS0__GPIO4_24,
+       MX51_PAD_CSPI1_SS1__GPIO4_25,
+       MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+       MX51_PAD_GPIO1_6__GPIO1_6,
+
+       /* USB HOST1 */
+       MX51_PAD_USBH1_CLK__USBH1_CLK,
+       MX51_PAD_USBH1_DIR__USBH1_DIR,
+       MX51_PAD_USBH1_NXT__USBH1_NXT,
+       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+       /* USB HUB RESET */
+       MX51_PAD_GPIO1_5__GPIO1_5,
+
+       /* WLAN */
+       MX51_PAD_EIM_A22__GPIO2_16,
+       MX51_PAD_EIM_A16__GPIO2_10,
+
+       /* USB PHY RESET */
+       MX51_PAD_EIM_D27__GPIO2_9,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata = {
+       .flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *usbother_base;
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base)
+               return -ENOMEM;
+       usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+       /* Set the PHY clock to 19.2MHz */
+       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+       v |= MX51_USB_PLL_DIV_19_2_MHZ;
+       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+       iounmap(usb_base);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+       .init   = initialize_otg_port,
+       .portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+       iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+       iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+       u32 v;
+       void __iomem *usb_base;
+       void __iomem *socregs_base;
+
+       mxc_iomux_v3_setup_pad(usbh1gpio);
+       gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
+       gpio_direction_output(EFIKAMX_USBH1_STP, 0);
+       msleep(1);
+       gpio_set_value(EFIKAMX_USBH1_STP, 1);
+       msleep(1);
+
+       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+       socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+       /* The clock for the USBH1 ULPI port will come externally */
+       /* from the PHY. */
+       v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
+       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+                       socregs_base + MX51_USB_CTRL_1_OFFSET);
+
+       iounmap(usb_base);
+
+       gpio_free(EFIKAMX_USBH1_STP);
+       mxc_iomux_v3_setup_pad(usbh1stp);
+
+       mdelay(10);
+
+       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
+       .init   = initialize_usbh1_port,
+       .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void mx51_efika_hubreset(void)
+{
+       gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
+       gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
+       msleep(1);
+       gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
+       msleep(1);
+       gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
+}
+
+static void __init mx51_efika_usb(void)
+{
+       mx51_efika_hubreset();
+
+       /* pulling it low, means no USB at all... */
+       gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
+       gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
+       msleep(1);
+       gpio_set_value(EFIKA_USB_PHY_RESET, 1);
+
+       usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+                       ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+
+       imx51_add_mxc_ehci_otg(&dr_utmi_config);
+       if (usbh1_config.otg)
+               imx51_add_mxc_ehci_hs(1, &usbh1_config);
+}
+
+static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
+       {
+        .name = "u-boot",
+        .offset = 0,
+        .size = SZ_256K,
+       },
+       {
+         .name = "config",
+         .offset = MTDPART_OFS_APPEND,
+         .size = SZ_64K,
+       },
+};
+
+static struct flash_platform_data mx51_efika_spi_flash_data = {
+       .name           = "spi_flash",
+       .parts          = mx51_efika_spi_nor_partitions,
+       .nr_parts       = ARRAY_SIZE(mx51_efika_spi_nor_partitions),
+       .type           = "sst25vf032b",
+};
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+       {
+               .supply = "cpu_vcc",
+       }
+};
+
+static struct regulator_consumer_supply vdig_consumers[] = {
+       /* sgtl5000 */
+       REGULATOR_SUPPLY("VDDA", "1-000a"),
+       REGULATOR_SUPPLY("VDDD", "1-000a"),
+};
+
+static struct regulator_consumer_supply vvideo_consumers[] = {
+       /* sgtl5000 */
+       REGULATOR_SUPPLY("VDDIO", "1-000a"),
+};
+
+static struct regulator_consumer_supply vsd_consumers[] = {
+       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
+       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
+};
+
+static struct regulator_consumer_supply pwgt1_consumer[] = {
+       {
+               .supply = "pwgt1",
+       }
+};
+
+static struct regulator_consumer_supply pwgt2_consumer[] = {
+       {
+               .supply = "pwgt2",
+       }
+};
+
+static struct regulator_consumer_supply coincell_consumer[] = {
+       {
+               .supply = "coincell",
+       }
+};
+
+static struct regulator_init_data sw1_init = {
+       .constraints = {
+               .name = "SW1",
+               .min_uV = 600000,
+               .max_uV = 1375000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .valid_modes_mask = 0,
+               .always_on = 1,
+               .boot_on = 1,
+               .state_mem = {
+                       .uV = 850000,
+                       .mode = REGULATOR_MODE_NORMAL,
+                       .enabled = 1,
+               },
+       },
+       .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+       .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+       .constraints = {
+               .name = "SW2",
+               .min_uV = 900000,
+               .max_uV = 1850000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .always_on = 1,
+               .boot_on = 1,
+               .state_mem = {
+                       .uV = 950000,
+                       .mode = REGULATOR_MODE_NORMAL,
+                       .enabled = 1,
+               },
+       }
+};
+
+static struct regulator_init_data sw3_init = {
+       .constraints = {
+               .name = "SW3",
+               .min_uV = 1100000,
+               .max_uV = 1850000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .always_on = 1,
+               .boot_on = 1,
+       }
+};
+
+static struct regulator_init_data sw4_init = {
+       .constraints = {
+               .name = "SW4",
+               .min_uV = 1100000,
+               .max_uV = 1850000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .always_on = 1,
+               .boot_on = 1,
+       }
+};
+
+static struct regulator_init_data viohi_init = {
+       .constraints = {
+               .name = "VIOHI",
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data vusb_init = {
+       .constraints = {
+               .name = "VUSB",
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data swbst_init = {
+       .constraints = {
+               .name = "SWBST",
+       }
+};
+
+static struct regulator_init_data vdig_init = {
+       .constraints = {
+               .name = "VDIG",
+               .min_uV = 1050000,
+               .max_uV = 1800000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+               .always_on = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
+       .consumer_supplies = vdig_consumers,
+};
+
+static struct regulator_init_data vpll_init = {
+       .constraints = {
+               .name = "VPLL",
+               .min_uV = 1050000,
+               .max_uV = 1800000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data vusb2_init = {
+       .constraints = {
+               .name = "VUSB2",
+               .min_uV = 2400000,
+               .max_uV = 2775000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data vvideo_init = {
+       .constraints = {
+               .name = "VVIDEO",
+               .min_uV = 2775000,
+               .max_uV = 2775000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+               .apply_uV = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
+       .consumer_supplies = vvideo_consumers,
+};
+
+static struct regulator_init_data vaudio_init = {
+       .constraints = {
+               .name = "VAUDIO",
+               .min_uV = 2300000,
+               .max_uV = 3000000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+       }
+};
+
+static struct regulator_init_data vsd_init = {
+       .constraints = {
+               .name = "VSD",
+               .min_uV = 1800000,
+               .max_uV = 3150000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE,
+               .boot_on = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
+       .consumer_supplies = vsd_consumers,
+};
+
+static struct regulator_init_data vcam_init = {
+       .constraints = {
+               .name = "VCAM",
+               .min_uV = 2500000,
+               .max_uV = 3000000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE |
+                       REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+               .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+               .boot_on = 1,
+       }
+};
+
+static struct regulator_init_data vgen1_init = {
+       .constraints = {
+               .name = "VGEN1",
+               .min_uV = 1200000,
+               .max_uV = 3150000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data vgen2_init = {
+       .constraints = {
+               .name = "VGEN2",
+               .min_uV = 1200000,
+               .max_uV = 3150000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data vgen3_init = {
+       .constraints = {
+               .name = "VGEN3",
+               .min_uV = 1800000,
+               .max_uV = 2900000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+               .boot_on = 1,
+               .always_on = 1,
+       }
+};
+
+static struct regulator_init_data gpo1_init = {
+       .constraints = {
+               .name = "GPO1",
+       }
+};
+
+static struct regulator_init_data gpo2_init = {
+       .constraints = {
+               .name = "GPO2",
+       }
+};
+
+static struct regulator_init_data gpo3_init = {
+       .constraints = {
+               .name = "GPO3",
+       }
+};
+
+static struct regulator_init_data gpo4_init = {
+       .constraints = {
+               .name = "GPO4",
+       }
+};
+
+static struct regulator_init_data pwgt1_init = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .boot_on        = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
+       .consumer_supplies = pwgt1_consumer,
+};
+
+static struct regulator_init_data pwgt2_init = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .boot_on        = 1,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
+       .consumer_supplies = pwgt2_consumer,
+};
+
+static struct regulator_init_data vcoincell_init = {
+       .constraints = {
+               .name = "COINCELL",
+               .min_uV = 3000000,
+               .max_uV = 3000000,
+               .valid_ops_mask =
+                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
+       .consumer_supplies = coincell_consumer,
+};
+
+static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
+       { .id = MC13892_SW1,            .init_data =  &sw1_init },
+       { .id = MC13892_SW2,            .init_data =  &sw2_init },
+       { .id = MC13892_SW3,            .init_data =  &sw3_init },
+       { .id = MC13892_SW4,            .init_data =  &sw4_init },
+       { .id = MC13892_SWBST,          .init_data =  &swbst_init },
+       { .id = MC13892_VIOHI,          .init_data =  &viohi_init },
+       { .id = MC13892_VPLL,           .init_data =  &vpll_init },
+       { .id = MC13892_VDIG,           .init_data =  &vdig_init },
+       { .id = MC13892_VSD,            .init_data =  &vsd_init },
+       { .id = MC13892_VUSB2,          .init_data =  &vusb2_init },
+       { .id = MC13892_VVIDEO,         .init_data =  &vvideo_init },
+       { .id = MC13892_VAUDIO,         .init_data =  &vaudio_init },
+       { .id = MC13892_VCAM,           .init_data =  &vcam_init },
+       { .id = MC13892_VGEN1,          .init_data =  &vgen1_init },
+       { .id = MC13892_VGEN2,          .init_data =  &vgen2_init },
+       { .id = MC13892_VGEN3,          .init_data =  &vgen3_init },
+       { .id = MC13892_VUSB,           .init_data =  &vusb_init },
+       { .id = MC13892_GPO1,           .init_data =  &gpo1_init },
+       { .id = MC13892_GPO2,           .init_data =  &gpo2_init },
+       { .id = MC13892_GPO3,           .init_data =  &gpo3_init },
+       { .id = MC13892_GPO4,           .init_data =  &gpo4_init },
+       { .id = MC13892_PWGT1SPI,       .init_data = &pwgt1_init },
+       { .id = MC13892_PWGT2SPI,       .init_data = &pwgt2_init },
+       { .id = MC13892_VCOINCELL,      .init_data = &vcoincell_init },
+};
+
+static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
+       .flags = MC13XXX_USE_RTC,
+       .regulators = {
+               .num_regulators = ARRAY_SIZE(mx51_efika_regulators),
+               .regulators = mx51_efika_regulators,
+       },
+};
+
+static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
+       {
+               .modalias = "m25p80",
+               .max_speed_hz = 25000000,
+               .bus_num = 0,
+               .chip_select = 1,
+               .platform_data = &mx51_efika_spi_flash_data,
+               .irq = -1,
+       },
+       {
+               .modalias = "mc13892",
+               .max_speed_hz = 1000000,
+               .bus_num = 0,
+               .chip_select = 0,
+               .platform_data = &mx51_efika_mc13892_data,
+               .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
+       },
+};
+
+static int mx51_efika_spi_cs[] = {
+       EFIKAMX_SPI_CS0,
+       EFIKAMX_SPI_CS1,
+};
+
+static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
+       .chipselect     = mx51_efika_spi_cs,
+       .num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
+};
+
+void __init efika_board_common_init(void)
+{
+       mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
+                                       ARRAY_SIZE(mx51efika_pads));
+       imx51_add_imx_uart(0, &uart_pdata);
+       mx51_efika_usb();
+
+       /* FIXME: comes from original code. check this. */
+       if (mx51_revision() < IMX_CHIP_REVISION_2_0)
+               sw2_init.constraints.state_mem.uV = 1100000;
+       else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
+               sw2_init.constraints.state_mem.uV = 1250000;
+               sw1_init.constraints.state_mem.uV = 1000000;
+       }
+       if (machine_is_mx51_efikasb())
+               vgen1_init.constraints.max_uV = 1200000;
+
+       gpio_request(EFIKAMX_PMIC, "pmic irq");
+       gpio_direction_input(EFIKAMX_PMIC);
+       spi_register_board_info(mx51_efika_spi_board_info,
+               ARRAY_SIZE(mx51_efika_spi_board_info));
+       imx51_add_ecspi(0, &mx51_efika_spi_pdata);
+
+       imx51_add_pata_imx();
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+       get_cpu_op = mx51_get_cpu_op;
+#endif
+}
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
new file mode 100644 (file)
index 0000000..6dc0934
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include "crm-regs-imx5.h"
+
+static struct clk *gpc_dvfs_clk;
+
+/*
+ * set cpu low power mode before WFI instruction. This function is called
+ * mx5 because it can be used for mx50, mx51, and mx53.
+ */
+void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+       u32 plat_lpc, arm_srpgcr, ccm_clpcr;
+       u32 empgc0, empgc1;
+       int stop_mode = 0;
+
+       /* always allow platform to issue a deep sleep mode request */
+       plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+           ~(MXC_CORTEXA8_PLAT_LPC_DSM);
+       ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+       arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
+       empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
+       empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+
+       switch (mode) {
+       case WAIT_CLOCKED:
+               break;
+       case WAIT_UNCLOCKED:
+               ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+               break;
+       case WAIT_UNCLOCKED_POWER_OFF:
+       case STOP_POWER_OFF:
+               plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
+                           | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
+               if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+                       ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+                       ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+                       ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+                       stop_mode = 0;
+               } else {
+                       ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+                       ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+                       ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+                       ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+                       stop_mode = 1;
+               }
+               arm_srpgcr |= MXC_SRPGCR_PCR;
+               break;
+       case STOP_POWER_ON:
+               ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+               break;
+       default:
+               printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+               return;
+       }
+
+       __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
+       __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+       __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
+
+       /* Enable NEON SRPG for all but MX50TO1.0. */
+       if (mx50_revision() != IMX_CHIP_REVISION_1_0)
+               __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+
+       if (stop_mode) {
+               empgc0 |= MXC_SRPGCR_PCR;
+               empgc1 |= MXC_SRPGCR_PCR;
+
+               __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
+               __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+       }
+}
+
+static int mx5_suspend_prepare(void)
+{
+       return clk_enable(gpc_dvfs_clk);
+}
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_MEM:
+               mx5_cpu_lp_set(STOP_POWER_OFF);
+               break;
+       case PM_SUSPEND_STANDBY:
+               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (state == PM_SUSPEND_MEM) {
+               local_flush_tlb_all();
+               flush_cache_all();
+
+               /*clear the EMPGC0/1 bits */
+               __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+               __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+       }
+       cpu_do_idle();
+       return 0;
+}
+
+static void mx5_suspend_finish(void)
+{
+       clk_disable(gpc_dvfs_clk);
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+       return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+       .valid = mx5_pm_valid,
+       .prepare = mx5_suspend_prepare,
+       .enter = mx5_suspend_enter,
+       .finish = mx5_suspend_finish,
+};
+
+static int __init mx5_pm_init(void)
+{
+       if (!cpu_is_mx51() && !cpu_is_mx53())
+               return 0;
+
+       if (gpc_dvfs_clk == NULL)
+               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+       if (!IS_ERR(gpc_dvfs_clk)) {
+               if (cpu_is_mx51())
+                       suspend_set_ops(&mx5_suspend_ops);
+       } else
+               return -EPERM;
+
+       return 0;
+}
+device_initcall(mx5_pm_init);
index 4bde04f99e38ceda85fd4cb43f89bf2eb080ead7..e15f1555c59b1ebd2712ba8b8c31772c340b06ef 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/smp.h>
-#include <asm/unified.h>
+#include <asm/smp_plat.h>
 
 #define SRC_SCR                                0x000
 #define SRC_GPR1                       0x020
 
 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;
@@ -43,7 +39,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)),
+       writel_relaxed(virt_to_phys(jump_addr),
                       src_base + SRC_GPR1 + cpu * 8);
 }
 
index cc15426787b15531de64868f50ff782244e1218b..77d4852e19f283e3b06f1fd63e9ff61707f99146 100644 (file)
@@ -27,6 +27,7 @@
 #include <plat/cache-feroceon-l2.h>
 #include <plat/mvsdio.h>
 #include <plat/orion_nand.h>
+#include <plat/ehci-orion.h>
 #include <plat/common.h>
 #include <plat/time.h>
 #include <plat/addr-map.h>
@@ -73,7 +74,7 @@ unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
 void __init kirkwood_ehci_init(void)
 {
        kirkwood_clk_ctrl |= CGC_USB0;
-       orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB);
+       orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
 }
 
 
index e8fda45c0736a866ead683af59f9b8a4d59d68f3..d5a0d1da2e0eb42b1f0e6f47172587d58e18e0d9 100644 (file)
 #define MPP_F6282_MASK         MPP(  0, 0x0, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP0_GPIO              MPP(  0, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP0_NF_IO2            MPP(  0, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP0_SPI_SCn           MPP(  0, 0x2, 0, 1, 1,   1,   1,   1,   1 )
+#define MPP0_NF_IO2            MPP(  0, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP0_SPI_SCn           MPP(  0, 0x2, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP1_GPO               MPP(  1, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP1_NF_IO3            MPP(  1, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP1_SPI_MOSI          MPP(  1, 0x2, 0, 1, 1,   1,   1,   1,   1 )
+#define MPP1_NF_IO3            MPP(  1, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP1_SPI_MOSI          MPP(  1, 0x2, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP2_GPO               MPP(  2, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP2_NF_IO4            MPP(  2, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP2_SPI_SCK           MPP(  2, 0x2, 0, 1, 1,   1,   1,   1,   1 )
+#define MPP2_NF_IO4            MPP(  2, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP2_SPI_SCK           MPP(  2, 0x2, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP3_GPO               MPP(  3, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP3_NF_IO5            MPP(  3, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP3_SPI_MISO          MPP(  3, 0x2, 1, 0, 1,   1,   1,   1,   1 )
+#define MPP3_NF_IO5            MPP(  3, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP3_SPI_MISO          MPP(  3, 0x2, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP4_GPIO              MPP(  4, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP4_NF_IO6            MPP(  4, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP4_UART0_RXD         MPP(  4, 0x2, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP4_SATA1_ACTn                MPP(  4, 0x5, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP4_NF_IO6            MPP(  4, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP4_UART0_RXD         MPP(  4, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP4_SATA1_ACTn                MPP(  4, 0x5, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP4_LCD_VGA_HSYNC     MPP(  4, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP4_PTP_CLK           MPP(  4, 0xd, 1, 0, 1,   1,   1,   1,   0 )
+#define MPP4_PTP_CLK           MPP(  4, 0xd, 0, 0, 1,   1,   1,   1,   0 )
 
 #define MPP5_GPO               MPP(  5, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP5_NF_IO7            MPP(  5, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP5_UART0_TXD         MPP(  5, 0x2, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP5_PTP_TRIG_GEN      MPP(  5, 0x4, 0, 1, 1,   1,   1,   1,   0 )
-#define MPP5_SATA0_ACTn                MPP(  5, 0x5, 0, 1, 0,   1,   1,   1,   1 )
+#define MPP5_NF_IO7            MPP(  5, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP5_UART0_TXD         MPP(  5, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP5_PTP_TRIG_GEN      MPP(  5, 0x4, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP5_SATA0_ACTn                MPP(  5, 0x5, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP5_LCD_VGA_VSYNC     MPP(  5, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
-#define MPP6_SYSRST_OUTn       MPP(  6, 0x1, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP6_SPI_MOSI          MPP(  6, 0x2, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP6_PTP_TRIG_GEN      MPP(  6, 0x3, 0, 1, 1,   1,   1,   1,   0 )
+#define MPP6_SYSRST_OUTn       MPP(  6, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP6_SPI_MOSI          MPP(  6, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP6_PTP_TRIG_GEN      MPP(  6, 0x3, 0, 0, 1,   1,   1,   1,   0 )
 
 #define MPP7_GPO               MPP(  7, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP7_PEX_RST_OUTn      MPP(  7, 0x1, 0, 1, 1,   1,   1,   1,   0 )
-#define MPP7_SPI_SCn           MPP(  7, 0x2, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP7_PTP_TRIG_GEN      MPP(  7, 0x3, 0, 1, 1,   1,   1,   1,   0 )
-#define MPP7_LCD_PWM           MPP(  7, 0xb, 0, 1, 0,   0,   0,   0,   1 )
+#define MPP7_PEX_RST_OUTn      MPP(  7, 0x1, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP7_SPI_SCn           MPP(  7, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP7_PTP_TRIG_GEN      MPP(  7, 0x3, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP7_LCD_PWM           MPP(  7, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP8_GPIO              MPP(  8, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP8_TW0_SDA           MPP(  8, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP8_UART0_RTS         MPP(  8, 0x2, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP8_UART1_RTS         MPP(  8, 0x3, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP8_MII0_RXERR                MPP(  8, 0x4, 1, 0, 0,   1,   1,   1,   1 )
-#define MPP8_SATA1_PRESENTn    MPP(  8, 0x5, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP8_PTP_CLK           MPP(  8, 0xc, 1, 0, 1,   1,   1,   1,   0 )
-#define MPP8_MII0_COL          MPP(  8, 0xd, 1, 0, 1,   1,   1,   1,   1 )
+#define MPP8_TW0_SDA           MPP(  8, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP8_UART0_RTS         MPP(  8, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP8_UART1_RTS         MPP(  8, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP8_MII0_RXERR                MPP(  8, 0x4, 0, 0, 0,   1,   1,   1,   1 )
+#define MPP8_SATA1_PRESENTn    MPP(  8, 0x5, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP8_PTP_CLK           MPP(  8, 0xc, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP8_MII0_COL          MPP(  8, 0xd, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP9_GPIO              MPP(  9, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP9_TW0_SCK           MPP(  9, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP9_UART0_CTS         MPP(  9, 0x2, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP9_UART1_CTS         MPP(  9, 0x3, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP9_SATA0_PRESENTn    MPP(  9, 0x5, 0, 1, 0,   1,   1,   1,   1 )
-#define MPP9_PTP_EVENT_REQ     MPP(  9, 0xc, 1, 0, 1,   1,   1,   1,   0 )
-#define MPP9_MII0_CRS          MPP(  9, 0xd, 1, 0, 1,   1,   1,   1,   1 )
+#define MPP9_TW0_SCK           MPP(  9, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP9_UART0_CTS         MPP(  9, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP9_UART1_CTS         MPP(  9, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP9_SATA0_PRESENTn    MPP(  9, 0x5, 0, 0, 0,   1,   1,   1,   1 )
+#define MPP9_PTP_EVENT_REQ     MPP(  9, 0xc, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP9_MII0_CRS          MPP(  9, 0xd, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP10_GPO              MPP( 10, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP10_SPI_SCK          MPP( 10, 0x2, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP10_UART0_TXD                MPP( 10, 0X3, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP10_SATA1_ACTn       MPP( 10, 0x5, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP10_PTP_TRIG_GEN     MPP( 10, 0xc, 0, 1, 1,   1,   1,   1,   0 )
+#define MPP10_SPI_SCK          MPP( 10, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP10_UART0_TXD                MPP( 10, 0X3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP10_SATA1_ACTn       MPP( 10, 0x5, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP10_PTP_TRIG_GEN     MPP( 10, 0xc, 0, 0, 1,   1,   1,   1,   0 )
 
 #define MPP11_GPIO             MPP( 11, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP11_SPI_MISO         MPP( 11, 0x2, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP11_UART0_RXD                MPP( 11, 0x3, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP11_PTP_EVENT_REQ    MPP( 11, 0x4, 1, 0, 1,   1,   1,   1,   0 )
-#define MPP11_PTP_TRIG_GEN     MPP( 11, 0xc, 0, 1, 1,   1,   1,   1,   0 )
-#define MPP11_PTP_CLK          MPP( 11, 0xd, 1, 0, 1,   1,   1,   1,   0 )
-#define MPP11_SATA0_ACTn       MPP( 11, 0x5, 0, 1, 0,   1,   1,   1,   1 )
+#define MPP11_SPI_MISO         MPP( 11, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP11_UART0_RXD                MPP( 11, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP11_PTP_EVENT_REQ    MPP( 11, 0x4, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP11_PTP_TRIG_GEN     MPP( 11, 0xc, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP11_PTP_CLK          MPP( 11, 0xd, 0, 0, 1,   1,   1,   1,   0 )
+#define MPP11_SATA0_ACTn       MPP( 11, 0x5, 0, 0, 0,   1,   1,   1,   1 )
 
 #define MPP12_GPO              MPP( 12, 0x0, 0, 1, 1,   1,   1,   1,   1 )
 #define MPP12_GPIO             MPP( 12, 0x0, 1, 1, 0,   0,   0,   1,   0 )
-#define MPP12_SD_CLK           MPP( 12, 0x1, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP12_AU_SPDIF0                MPP( 12, 0xa, 0, 1, 0,   0,   0,   0,   1 )
-#define MPP12_SPI_MOSI         MPP( 12, 0xb, 0, 1, 0,   0,   0,   0,   1 )
-#define MPP12_TW1_SDA          MPP( 12, 0xd, 1, 0, 0,   0,   0,   0,   1 )
+#define MPP12_SD_CLK           MPP( 12, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP12_AU_SPDIF0                MPP( 12, 0xa, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP12_SPI_MOSI         MPP( 12, 0xb, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP12_TW1_SDA          MPP( 12, 0xd, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP13_GPIO             MPP( 13, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP13_SD_CMD           MPP( 13, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP13_UART1_TXD                MPP( 13, 0x3, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP13_AU_SPDIFRMCLK    MPP( 13, 0xa, 0, 1, 0,   0,   0,   0,   1 )
-#define MPP13_LCDPWM           MPP( 13, 0xb, 0, 1, 0,   0,   0,   0,   1 )
+#define MPP13_SD_CMD           MPP( 13, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP13_UART1_TXD                MPP( 13, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP13_AU_SPDIFRMCLK    MPP( 13, 0xa, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP13_LCDPWM           MPP( 13, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP14_GPIO             MPP( 14, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP14_SD_D0            MPP( 14, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP14_UART1_RXD                MPP( 14, 0x3, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP14_SATA1_PRESENTn   MPP( 14, 0x4, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP14_AU_SPDIFI                MPP( 14, 0xa, 1, 0, 0,   0,   0,   0,   1 )
-#define MPP14_AU_I2SDI         MPP( 14, 0xb, 1, 0, 0,   0,   0,   0,   1 )
-#define MPP14_MII0_COL         MPP( 14, 0xd, 1, 0, 1,   1,   1,   1,   1 )
+#define MPP14_SD_D0            MPP( 14, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP14_UART1_RXD                MPP( 14, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP14_SATA1_PRESENTn   MPP( 14, 0x4, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP14_AU_SPDIFI                MPP( 14, 0xa, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP14_AU_I2SDI         MPP( 14, 0xb, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP14_MII0_COL         MPP( 14, 0xd, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP15_GPIO             MPP( 15, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP15_SD_D1            MPP( 15, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP15_UART0_RTS                MPP( 15, 0x2, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP15_UART1_TXD                MPP( 15, 0x3, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP15_SATA0_ACTn       MPP( 15, 0x4, 0, 1, 0,   1,   1,   1,   1 )
-#define MPP15_SPI_CSn          MPP( 15, 0xb, 0, 1, 0,   0,   0,   0,   1 )
+#define MPP15_SD_D1            MPP( 15, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP15_UART0_RTS                MPP( 15, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP15_UART1_TXD                MPP( 15, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP15_SATA0_ACTn       MPP( 15, 0x4, 0, 0, 0,   1,   1,   1,   1 )
+#define MPP15_SPI_CSn          MPP( 15, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP16_GPIO             MPP( 16, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP16_SD_D2            MPP( 16, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP16_UART0_CTS                MPP( 16, 0x2, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP16_UART1_RXD                MPP( 16, 0x3, 1, 0, 1,   1,   1,   1,   1 )
-#define MPP16_SATA1_ACTn       MPP( 16, 0x4, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP16_LCD_EXT_REF_CLK  MPP( 16, 0xb, 1, 0, 0,   0,   0,   0,   1 )
-#define MPP16_MII0_CRS         MPP( 16, 0xd, 1, 0, 1,   1,   1,   1,   1 )
+#define MPP16_SD_D2            MPP( 16, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP16_UART0_CTS                MPP( 16, 0x2, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP16_UART1_RXD                MPP( 16, 0x3, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP16_SATA1_ACTn       MPP( 16, 0x4, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP16_LCD_EXT_REF_CLK  MPP( 16, 0xb, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP16_MII0_CRS         MPP( 16, 0xd, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP17_GPIO             MPP( 17, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP17_SD_D3            MPP( 17, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP17_SATA0_PRESENTn   MPP( 17, 0x4, 0, 1, 0,   1,   1,   1,   1 )
-#define MPP17_SATA1_ACTn       MPP( 17, 0xa, 0, 1, 0,   0,   0,   0,   1 )
-#define MPP17_TW1_SCK          MPP( 17, 0xd, 1, 1, 0,   0,   0,   0,   1 )
+#define MPP17_SD_D3            MPP( 17, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP17_SATA0_PRESENTn   MPP( 17, 0x4, 0, 0, 0,   1,   1,   1,   1 )
+#define MPP17_SATA1_ACTn       MPP( 17, 0xa, 0, 0, 0,   0,   0,   0,   1 )
+#define MPP17_TW1_SCK          MPP( 17, 0xd, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP18_GPO              MPP( 18, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP18_NF_IO0           MPP( 18, 0x1, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP18_PEX0_CLKREQ      MPP( 18, 0x2, 0, 1, 0,   0,   0,   0,   1 )
+#define MPP18_NF_IO0           MPP( 18, 0x1, 0, 0, 1,   1,   1,   1,   1 )
+#define MPP18_PEX0_CLKREQ      MPP( 18, 0x2, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP19_GPO              MPP( 19, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP19_NF_IO1           MPP( 19, 0x1, 1, 1, 1,   1,   1,   1,   1 )
+#define MPP19_NF_IO1           MPP( 19, 0x1, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP20_GPIO             MPP( 20, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP20_TSMP0            MPP( 20, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP20_TDM_CH0_TX_QL    MPP( 20, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP20_TSMP0            MPP( 20, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP20_TDM_CH0_TX_QL    MPP( 20, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP20_GE1_TXD0         MPP( 20, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP20_AU_SPDIFI                MPP( 20, 0x4, 1, 0, 0,   0,   1,   1,   1 )
-#define MPP20_SATA1_ACTn       MPP( 20, 0x5, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP20_AU_SPDIFI                MPP( 20, 0x4, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP20_SATA1_ACTn       MPP( 20, 0x5, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP20_LCD_D0           MPP( 20, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP21_GPIO             MPP( 21, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP21_TSMP1            MPP( 21, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP21_TDM_CH0_RX_QL    MPP( 21, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP21_TSMP1            MPP( 21, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP21_TDM_CH0_RX_QL    MPP( 21, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP21_GE1_TXD1         MPP( 21, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP21_AU_SPDIFO                MPP( 21, 0x4, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP21_SATA0_ACTn       MPP( 21, 0x5, 0, 1, 0,   1,   1,   1,   1 )
+#define MPP21_AU_SPDIFO                MPP( 21, 0x4, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP21_SATA0_ACTn       MPP( 21, 0x5, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP21_LCD_D1           MPP( 21, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP22_GPIO             MPP( 22, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP22_TSMP2            MPP( 22, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP22_TDM_CH2_TX_QL    MPP( 22, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP22_TSMP2            MPP( 22, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP22_TDM_CH2_TX_QL    MPP( 22, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP22_GE1_TXD2         MPP( 22, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP22_AU_SPDIFRMKCLK   MPP( 22, 0x4, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP22_SATA1_PRESENTn   MPP( 22, 0x5, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP22_AU_SPDIFRMKCLK   MPP( 22, 0x4, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP22_SATA1_PRESENTn   MPP( 22, 0x5, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP22_LCD_D2           MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP23_GPIO             MPP( 23, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP23_TSMP3            MPP( 23, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP23_TDM_CH2_RX_QL    MPP( 23, 0x2, 1, 0, 0,   0,   1,   1,   1 )
+#define MPP23_TSMP3            MPP( 23, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP23_TDM_CH2_RX_QL    MPP( 23, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP23_GE1_TXD3         MPP( 23, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP23_AU_I2SBCLK       MPP( 23, 0x4, 0, 1, 0,   0,   1,   1,   1 )
-#define MPP23_SATA0_PRESENTn   MPP( 23, 0x5, 0, 1, 0,   1,   1,   1,   1 )
+#define MPP23_AU_I2SBCLK       MPP( 23, 0x4, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP23_SATA0_PRESENTn   MPP( 23, 0x5, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP23_LCD_D3           MPP( 23, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP24_GPIO             MPP( 24, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP24_TSMP4            MPP( 24, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP24_TDM_SPI_CS0      MPP( 24, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP24_TSMP4            MPP( 24, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP24_TDM_SPI_CS0      MPP( 24, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP24_GE1_RXD0         MPP( 24, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP24_AU_I2SDO         MPP( 24, 0x4, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP24_AU_I2SDO         MPP( 24, 0x4, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP24_LCD_D4           MPP( 24, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP25_GPIO             MPP( 25, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP25_TSMP5            MPP( 25, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP25_TDM_SPI_SCK      MPP( 25, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP25_TSMP5            MPP( 25, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP25_TDM_SPI_SCK      MPP( 25, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP25_GE1_RXD1         MPP( 25, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP25_AU_I2SLRCLK      MPP( 25, 0x4, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP25_AU_I2SLRCLK      MPP( 25, 0x4, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP25_LCD_D5           MPP( 25, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP26_GPIO             MPP( 26, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP26_TSMP6            MPP( 26, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP26_TDM_SPI_MISO     MPP( 26, 0x2, 1, 0, 0,   0,   1,   1,   1 )
+#define MPP26_TSMP6            MPP( 26, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP26_TDM_SPI_MISO     MPP( 26, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP26_GE1_RXD2         MPP( 26, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP26_AU_I2SMCLK       MPP( 26, 0x4, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP26_AU_I2SMCLK       MPP( 26, 0x4, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP26_LCD_D6           MPP( 26, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP27_GPIO             MPP( 27, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP27_TSMP7            MPP( 27, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP27_TDM_SPI_MOSI     MPP( 27, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP27_TSMP7            MPP( 27, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP27_TDM_SPI_MOSI     MPP( 27, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP27_GE1_RXD3         MPP( 27, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP27_AU_I2SDI         MPP( 27, 0x4, 1, 0, 0,   0,   1,   1,   1 )
+#define MPP27_AU_I2SDI         MPP( 27, 0x4, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP27_LCD_D7           MPP( 27, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP28_GPIO             MPP( 28, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP28_TSMP8            MPP( 28, 0x1, 1, 1, 0,   0,   1,   1,   1 )
+#define MPP28_TSMP8            MPP( 28, 0x1, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP28_TDM_CODEC_INTn   MPP( 28, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP28_GE1_COL          MPP( 28, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP28_AU_EXTCLK                MPP( 28, 0x4, 1, 0, 0,   0,   1,   1,   1 )
+#define MPP28_AU_EXTCLK                MPP( 28, 0x4, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP28_LCD_D8           MPP( 28, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP29_GPIO             MPP( 29, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP29_TSMP9            MPP( 29, 0x1, 1, 1, 0,   0,   1,   1,   1 )
+#define MPP29_TSMP9            MPP( 29, 0x1, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP29_TDM_CODEC_RSTn   MPP( 29, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP29_GE1_TCLK         MPP( 29, 0x3, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP29_LCD_D9           MPP( 29, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP30_GPIO             MPP( 30, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP30_TSMP10           MPP( 30, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP30_TDM_PCLK         MPP( 30, 0x2, 1, 1, 0,   0,   1,   1,   1 )
+#define MPP30_TSMP10           MPP( 30, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP30_TDM_PCLK         MPP( 30, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP30_GE1_RXCTL                MPP( 30, 0x3, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP30_LCD_D10          MPP( 30, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP31_GPIO             MPP( 31, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP31_TSMP11           MPP( 31, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP31_TDM_FS           MPP( 31, 0x2, 1, 1, 0,   0,   1,   1,   1 )
+#define MPP31_TSMP11           MPP( 31, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP31_TDM_FS           MPP( 31, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP31_GE1_RXCLK                MPP( 31, 0x3, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP31_LCD_D11          MPP( 31, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP32_GPIO             MPP( 32, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP32_TSMP12           MPP( 32, 0x1, 1, 1, 0,   0,   1,   1,   1 )
-#define MPP32_TDM_DRX          MPP( 32, 0x2, 1, 0, 0,   0,   1,   1,   1 )
+#define MPP32_TSMP12           MPP( 32, 0x1, 0, 0, 0,   0,   1,   1,   1 )
+#define MPP32_TDM_DRX          MPP( 32, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP32_GE1_TCLKOUT      MPP( 32, 0x3, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP32_LCD_D12          MPP( 32, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP33_GPO              MPP( 33, 0x0, 0, 1, 0,   1,   1,   1,   1 )
-#define MPP33_TDM_DTX          MPP( 33, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP33_TDM_DTX          MPP( 33, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP33_GE1_TXCTL                MPP( 33, 0x3, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP33_LCD_D13          MPP( 33, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP34_GPIO             MPP( 34, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP34_TDM_SPI_CS1      MPP( 34, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP34_TDM_SPI_CS1      MPP( 34, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP34_GE1_TXEN         MPP( 34, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP34_SATA1_ACTn       MPP( 34, 0x5, 0, 1, 0,   0,   0,   1,   1 )
+#define MPP34_SATA1_ACTn       MPP( 34, 0x5, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP34_LCD_D14          MPP( 34, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP35_GPIO             MPP( 35, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP35_TDM_CH0_TX_QL    MPP( 35, 0x2, 0, 1, 0,   0,   1,   1,   1 )
+#define MPP35_TDM_CH0_TX_QL    MPP( 35, 0x2, 0, 0, 0,   0,   1,   1,   1 )
 #define MPP35_GE1_RXERR                MPP( 35, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP35_SATA0_ACTn       MPP( 35, 0x5, 0, 1, 0,   1,   1,   1,   1 )
+#define MPP35_SATA0_ACTn       MPP( 35, 0x5, 0, 0, 0,   1,   1,   1,   1 )
 #define MPP35_LCD_D15          MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP35_MII0_RXERR       MPP( 35, 0xc, 1, 0, 1,   1,   1,   1,   1 )
+#define MPP35_MII0_RXERR       MPP( 35, 0xc, 0, 0, 1,   1,   1,   1,   1 )
 
 #define MPP36_GPIO             MPP( 36, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP36_TSMP0            MPP( 36, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP36_TDM_SPI_CS1      MPP( 36, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP36_AU_SPDIFI                MPP( 36, 0x4, 1, 0, 1,   0,   0,   1,   1 )
-#define MPP36_TW1_SDA          MPP( 36, 0xb, 1, 1, 0,   0,   0,   0,   1 )
+#define MPP36_TSMP0            MPP( 36, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP36_TDM_SPI_CS1      MPP( 36, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP36_AU_SPDIFI                MPP( 36, 0x4, 0, 0, 1,   0,   0,   1,   1 )
+#define MPP36_TW1_SDA          MPP( 36, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP37_GPIO             MPP( 37, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP37_TSMP1            MPP( 37, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP37_TDM_CH2_TX_QL    MPP( 37, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP37_AU_SPDIFO                MPP( 37, 0x4, 0, 1, 1,   0,   0,   1,   1 )
-#define MPP37_TW1_SCK          MPP( 37, 0xb, 1, 1, 0,   0,   0,   0,   1 )
+#define MPP37_TSMP1            MPP( 37, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP37_TDM_CH2_TX_QL    MPP( 37, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP37_AU_SPDIFO                MPP( 37, 0x4, 0, 0, 1,   0,   0,   1,   1 )
+#define MPP37_TW1_SCK          MPP( 37, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP38_GPIO             MPP( 38, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP38_TSMP2            MPP( 38, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP38_TDM_CH2_RX_QL    MPP( 38, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP38_AU_SPDIFRMLCLK   MPP( 38, 0x4, 0, 1, 1,   0,   0,   1,   1 )
+#define MPP38_TSMP2            MPP( 38, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP38_TDM_CH2_RX_QL    MPP( 38, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP38_AU_SPDIFRMLCLK   MPP( 38, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP38_LCD_D18          MPP( 38, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP39_GPIO             MPP( 39, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP39_TSMP3            MPP( 39, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP39_TDM_SPI_CS0      MPP( 39, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP39_AU_I2SBCLK       MPP( 39, 0x4, 0, 1, 1,   0,   0,   1,   1 )
+#define MPP39_TSMP3            MPP( 39, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP39_TDM_SPI_CS0      MPP( 39, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP39_AU_I2SBCLK       MPP( 39, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP39_LCD_D19          MPP( 39, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP40_GPIO             MPP( 40, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP40_TSMP4            MPP( 40, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP40_TDM_SPI_SCK      MPP( 40, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP40_AU_I2SDO         MPP( 40, 0x4, 0, 1, 1,   0,   0,   1,   1 )
+#define MPP40_TSMP4            MPP( 40, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP40_TDM_SPI_SCK      MPP( 40, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP40_AU_I2SDO         MPP( 40, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP40_LCD_D20          MPP( 40, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP41_GPIO             MPP( 41, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP41_TSMP5            MPP( 41, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP41_TDM_SPI_MISO     MPP( 41, 0x2, 1, 0, 0,   0,   0,   1,   1 )
-#define MPP41_AU_I2SLRCLK      MPP( 41, 0x4, 0, 1, 1,   0,   0,   1,   1 )
+#define MPP41_TSMP5            MPP( 41, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP41_TDM_SPI_MISO     MPP( 41, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP41_AU_I2SLRCLK      MPP( 41, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP41_LCD_D21          MPP( 41, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP42_GPIO             MPP( 42, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP42_TSMP6            MPP( 42, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP42_TDM_SPI_MOSI     MPP( 42, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP42_AU_I2SMCLK       MPP( 42, 0x4, 0, 1, 1,   0,   0,   1,   1 )
+#define MPP42_TSMP6            MPP( 42, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP42_TDM_SPI_MOSI     MPP( 42, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP42_AU_I2SMCLK       MPP( 42, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP42_LCD_D22          MPP( 42, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP43_GPIO             MPP( 43, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP43_TSMP7            MPP( 43, 0x1, 1, 1, 0,   0,   0,   1,   1 )
+#define MPP43_TSMP7            MPP( 43, 0x1, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP43_TDM_CODEC_INTn   MPP( 43, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP43_AU_I2SDI         MPP( 43, 0x4, 1, 0, 1,   0,   0,   1,   1 )
+#define MPP43_AU_I2SDI         MPP( 43, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP43_LCD_D23          MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP44_GPIO             MPP( 44, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP44_TSMP8            MPP( 44, 0x1, 1, 1, 0,   0,   0,   1,   1 )
+#define MPP44_TSMP8            MPP( 44, 0x1, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP44_TDM_CODEC_RSTn   MPP( 44, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP44_AU_EXTCLK                MPP( 44, 0x4, 1, 0, 1,   0,   0,   1,   1 )
+#define MPP44_AU_EXTCLK                MPP( 44, 0x4, 0, 0, 1,   0,   0,   1,   1 )
 #define MPP44_LCD_CLK          MPP( 44, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP45_GPIO             MPP( 45, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP45_TSMP9            MPP( 45, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP45_TDM_PCLK         MPP( 45, 0x2, 1, 1, 0,   0,   0,   1,   1 )
+#define MPP45_TSMP9            MPP( 45, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP45_TDM_PCLK         MPP( 45, 0x2, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP245_LCD_E           MPP( 45, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP46_GPIO             MPP( 46, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP46_TSMP10           MPP( 46, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP46_TDM_FS           MPP( 46, 0x2, 1, 1, 0,   0,   0,   1,   1 )
+#define MPP46_TSMP10           MPP( 46, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP46_TDM_FS           MPP( 46, 0x2, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP46_LCD_HSYNC                MPP( 46, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP47_GPIO             MPP( 47, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP47_TSMP11           MPP( 47, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP47_TDM_DRX          MPP( 47, 0x2, 1, 0, 0,   0,   0,   1,   1 )
+#define MPP47_TSMP11           MPP( 47, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP47_TDM_DRX          MPP( 47, 0x2, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP47_LCD_VSYNC                MPP( 47, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP48_GPIO             MPP( 48, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP48_TSMP12           MPP( 48, 0x1, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP48_TDM_DTX          MPP( 48, 0x2, 0, 1, 0,   0,   0,   1,   1 )
+#define MPP48_TSMP12           MPP( 48, 0x1, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP48_TDM_DTX          MPP( 48, 0x2, 0, 0, 0,   0,   0,   1,   1 )
 #define MPP48_LCD_D16          MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP49_GPIO             MPP( 49, 0x0, 1, 1, 0,   0,   0,   1,   0 )
 #define MPP49_GPO              MPP( 49, 0x0, 0, 1, 0,   0,   0,   0,   1 )
-#define MPP49_TSMP9            MPP( 49, 0x1, 1, 1, 0,   0,   0,   1,   0 )
-#define MPP49_TDM_CH0_RX_QL    MPP( 49, 0x2, 0, 1, 0,   0,   0,   1,   1 )
-#define MPP49_PTP_CLK          MPP( 49, 0x5, 1, 0, 0,   0,   0,   1,   0 )
-#define MPP49_PEX0_CLKREQ      MPP( 49, 0xa, 0, 1, 0,   0,   0,   0,   1 )
+#define MPP49_TSMP9            MPP( 49, 0x1, 0, 0, 0,   0,   0,   1,   0 )
+#define MPP49_TDM_CH0_RX_QL    MPP( 49, 0x2, 0, 0, 0,   0,   0,   1,   1 )
+#define MPP49_PTP_CLK          MPP( 49, 0x5, 0, 0, 0,   0,   0,   1,   0 )
+#define MPP49_PEX0_CLKREQ      MPP( 49, 0xa, 0, 0, 0,   0,   0,   0,   1 )
 #define MPP49_LCD_D17          MPP( 49, 0xb, 0, 0, 0,   0,   0,   0,   1 )
 
 #define MPP_MAX                        49
index 0c631a9f8647f5b8ec35dd5998da65bc937860d0..bcd5af223deabaf48451bf3a4d67cea23c82566e 100644 (file)
@@ -34,6 +34,7 @@ pen:  ldr     r7, [r6]
         * should now contain the SVC stack for this core
         */
        b       secondary_startup
+ENDPROC(msm_secondary_startup)
 
        .align
 1:     .long   .
index 41c252de0215b3c66aaad2c7074d90230b431c19..a446fc14221f6f0394806fb32af411ef2742e85e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 
 extern volatile int pen_release;
 
index 0b3e357c4c8c8166e144a023a059336bddb660d7..db0117ec55f4ad32a10d154d1eb2c41654a73bac 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
+#include <asm/smp_plat.h>
 
 #include <mach/msm_iomap.h>
 
index a9103bc6615f01ac526d8b085939fb4f20433ffb..bd66ed04d6dc0edfdc489a56a7f1e9fb84dbafc1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/debugfs.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <mach/vreg.h>
 
index 0cdd41004ad05d1001b80adf04a2a32bd164eaaf..a5dcf766a3f9ca53a050c8f4be1ec2823ac98145 100644 (file)
@@ -19,6 +19,7 @@
 #include <mach/mv78xx0.h>
 #include <mach/bridge-regs.h>
 #include <plat/cache-feroceon-l2.h>
+#include <plat/ehci-orion.h>
 #include <plat/orion_nand.h>
 #include <plat/time.h>
 #include <plat/common.h>
@@ -169,7 +170,7 @@ void __init mv78xx0_map_io(void)
  ****************************************************************************/
 void __init mv78xx0_ehci0_init(void)
 {
-       orion_ehci_init(USB0_PHYS_BASE, IRQ_MV78XX0_USB_0);
+       orion_ehci_init(USB0_PHYS_BASE, IRQ_MV78XX0_USB_0, EHCI_PHY_NA);
 }
 
 
index b61b50927123f3178320f084de9fe19910eb1862..3752302ae2ee3e3dc049cfe7cab40d5af7cb8af9 100644 (file)
 #define MPP_78100_A0_MASK    MPP(0, 0x0, 0, 0, 1)
 
 #define MPP0_GPIO        MPP(0, 0x0, 1, 1, 1)
-#define MPP0_GE0_COL        MPP(0, 0x1, 1, 0, 1)
-#define MPP0_GE1_TXCLK        MPP(0, 0x2, 0, 1, 1)
+#define MPP0_GE0_COL        MPP(0, 0x1, 0, 0, 1)
+#define MPP0_GE1_TXCLK        MPP(0, 0x2, 0, 0, 1)
 #define MPP0_UNUSED        MPP(0, 0x3, 0, 0, 1)
 
 #define MPP1_GPIO        MPP(1, 0x0, 1, 1, 1)
-#define MPP1_GE0_RXERR        MPP(1, 0x1, 1, 0, 1)
-#define MPP1_GE1_TXCTL        MPP(1, 0x2, 0, 1, 1)
+#define MPP1_GE0_RXERR        MPP(1, 0x1, 0, 0, 1)
+#define MPP1_GE1_TXCTL        MPP(1, 0x2, 0, 0, 1)
 #define MPP1_UNUSED        MPP(1, 0x3, 0, 0, 1)
 
 #define MPP2_GPIO        MPP(2, 0x0, 1, 1, 1)
-#define MPP2_GE0_CRS        MPP(2, 0x1, 1, 0, 1)
-#define MPP2_GE1_RXCTL        MPP(2, 0x2, 1, 0, 1)
+#define MPP2_GE0_CRS        MPP(2, 0x1, 0, 0, 1)
+#define MPP2_GE1_RXCTL        MPP(2, 0x2, 0, 0, 1)
 #define MPP2_UNUSED        MPP(2, 0x3, 0, 0, 1)
 
 #define MPP3_GPIO        MPP(3, 0x0, 1, 1, 1)
-#define MPP3_GE0_TXERR        MPP(3, 0x1, 0, 1, 1)
-#define MPP3_GE1_RXCLK        MPP(3, 0x2, 1, 0, 1)
+#define MPP3_GE0_TXERR        MPP(3, 0x1, 0, 0, 1)
+#define MPP3_GE1_RXCLK        MPP(3, 0x2, 0, 0, 1)
 #define MPP3_UNUSED        MPP(3, 0x3, 0, 0, 1)
 
 #define MPP4_GPIO        MPP(4, 0x0, 1, 1, 1)
-#define MPP4_GE0_TXD4        MPP(4, 0x1, 0, 1, 1)
-#define MPP4_GE1_TXD0        MPP(4, 0x2, 0, 1, 1)
+#define MPP4_GE0_TXD4        MPP(4, 0x1, 0, 0, 1)
+#define MPP4_GE1_TXD0        MPP(4, 0x2, 0, 0, 1)
 #define MPP4_UNUSED        MPP(4, 0x3, 0, 0, 1)
 
 #define MPP5_GPIO        MPP(5, 0x0, 1, 1, 1)
-#define MPP5_GE0_TXD5        MPP(5, 0x1, 0, 1, 1)
-#define MPP5_GE1_TXD1        MPP(5, 0x2, 0, 1, 1)
+#define MPP5_GE0_TXD5        MPP(5, 0x1, 0, 0, 1)
+#define MPP5_GE1_TXD1        MPP(5, 0x2, 0, 0, 1)
 #define MPP5_UNUSED        MPP(5, 0x3, 0, 0, 1)
 
 #define MPP6_GPIO        MPP(6, 0x0, 1, 1, 1)
-#define MPP6_GE0_TXD6        MPP(6, 0x1, 0, 1, 1)
-#define MPP6_GE1_TXD2        MPP(6, 0x2, 0, 1, 1)
+#define MPP6_GE0_TXD6        MPP(6, 0x1, 0, 0, 1)
+#define MPP6_GE1_TXD2        MPP(6, 0x2, 0, 0, 1)
 #define MPP6_UNUSED        MPP(6, 0x3, 0, 0, 1)
 
 #define MPP7_GPIO        MPP(7, 0x0, 1, 1, 1)
-#define MPP7_GE0_TXD7        MPP(7, 0x1, 0, 1, 1)
-#define MPP7_GE1_TXD3        MPP(7, 0x2, 0, 1, 1)
+#define MPP7_GE0_TXD7        MPP(7, 0x1, 0, 0, 1)
+#define MPP7_GE1_TXD3        MPP(7, 0x2, 0, 0, 1)
 #define MPP7_UNUSED        MPP(7, 0x3, 0, 0, 1)
 
 #define MPP8_GPIO        MPP(8, 0x0, 1, 1, 1)
-#define MPP8_GE0_RXD4        MPP(8, 0x1, 1, 0, 1)
-#define MPP8_GE1_RXD0        MPP(8, 0x2, 1, 0, 1)
+#define MPP8_GE0_RXD4        MPP(8, 0x1, 0, 0, 1)
+#define MPP8_GE1_RXD0        MPP(8, 0x2, 0, 0, 1)
 #define MPP8_UNUSED        MPP(8, 0x3, 0, 0, 1)
 
 #define MPP9_GPIO        MPP(9, 0x0, 1, 1, 1)
-#define MPP9_GE0_RXD5        MPP(9, 0x1, 1, 0, 1)
-#define MPP9_GE1_RXD1        MPP(9, 0x2, 1, 0, 1)
+#define MPP9_GE0_RXD5        MPP(9, 0x1, 0, 0, 1)
+#define MPP9_GE1_RXD1        MPP(9, 0x2, 0, 0, 1)
 #define MPP9_UNUSED        MPP(9, 0x3, 0, 0, 1)
 
 #define MPP10_GPIO        MPP(10, 0x0, 1, 1, 1)
-#define MPP10_GE0_RXD6        MPP(10, 0x1, 1, 0, 1)
-#define MPP10_GE1_RXD2        MPP(10, 0x2, 1, 0, 1)
+#define MPP10_GE0_RXD6        MPP(10, 0x1, 0, 0, 1)
+#define MPP10_GE1_RXD2        MPP(10, 0x2, 0, 0, 1)
 #define MPP10_UNUSED        MPP(10, 0x3, 0, 0, 1)
 
 #define MPP11_GPIO        MPP(11, 0x0, 1, 1, 1)
-#define MPP11_GE0_RXD7        MPP(11, 0x1, 1, 0, 1)
-#define MPP11_GE1_RXD3        MPP(11, 0x2, 1, 0, 1)
+#define MPP11_GE0_RXD7        MPP(11, 0x1, 0, 0, 1)
+#define MPP11_GE1_RXD3        MPP(11, 0x2, 0, 0, 1)
 #define MPP11_UNUSED        MPP(11, 0x3, 0, 0, 1)
 
 #define MPP12_GPIO        MPP(12, 0x0, 1, 1, 1)
-#define MPP12_M_BB        MPP(12, 0x3, 1, 0, 1)
-#define MPP12_UA0_CTSn        MPP(12, 0x4, 1, 0, 1)
-#define MPP12_NAND_FLASH_REn0    MPP(12, 0x5, 0, 1, 1)
-#define MPP12_TDM0_SCSn        MPP(12, 0X6, 0, 1, 1)
+#define MPP12_M_BB        MPP(12, 0x3, 0, 0, 1)
+#define MPP12_UA0_CTSn        MPP(12, 0x4, 0, 0, 1)
+#define MPP12_NAND_FLASH_REn0    MPP(12, 0x5, 0, 0, 1)
+#define MPP12_TDM0_SCSn        MPP(12, 0X6, 0, 0, 1)
 #define MPP12_UNUSED        MPP(12, 0x1, 0, 0, 1)
 
 #define MPP13_GPIO        MPP(13, 0x0, 1, 1, 1)
-#define MPP13_SYSRST_OUTn    MPP(13, 0x3, 0, 1, 1)
-#define MPP13_UA0_RTSn        MPP(13, 0x4, 0, 1, 1)
-#define MPP13_NAN_FLASH_WEn0    MPP(13, 0x5, 0, 1, 1)
-#define MPP13_TDM_SCLK        MPP(13, 0x6, 0, 1, 1)
+#define MPP13_SYSRST_OUTn    MPP(13, 0x3, 0, 0, 1)
+#define MPP13_UA0_RTSn        MPP(13, 0x4, 0, 0, 1)
+#define MPP13_NAN_FLASH_WEn0    MPP(13, 0x5, 0, 0, 1)
+#define MPP13_TDM_SCLK        MPP(13, 0x6, 0, 0, 1)
 #define MPP13_UNUSED        MPP(13, 0x1, 0, 0, 1)
 
 #define MPP14_GPIO        MPP(14, 0x0, 1, 1, 1)
-#define MPP14_SATA1_ACTn    MPP(14, 0x3, 0, 1, 1)
-#define MPP14_UA1_CTSn        MPP(14, 0x4, 1, 0, 1)
-#define MPP14_NAND_FLASH_REn1    MPP(14, 0x5, 0, 1, 1)
-#define MPP14_TDM_SMOSI        MPP(14, 0x6, 0, 1, 1)
+#define MPP14_SATA1_ACTn    MPP(14, 0x3, 0, 0, 1)
+#define MPP14_UA1_CTSn        MPP(14, 0x4, 0, 0, 1)
+#define MPP14_NAND_FLASH_REn1    MPP(14, 0x5, 0, 0, 1)
+#define MPP14_TDM_SMOSI        MPP(14, 0x6, 0, 0, 1)
 #define MPP14_UNUSED        MPP(14, 0x1, 0, 0, 1)
 
 #define MPP15_GPIO        MPP(15, 0x0, 1, 1, 1)
-#define MPP15_SATA0_ACTn    MPP(15, 0x3, 0, 1, 1)
-#define MPP15_UA1_RTSn        MPP(15, 0x4, 0, 1, 1)
-#define MPP15_NAND_FLASH_WEn1    MPP(15, 0x5, 0, 1, 1)
-#define MPP15_TDM_SMISO        MPP(15, 0x6, 1, 0, 1)
+#define MPP15_SATA0_ACTn    MPP(15, 0x3, 0, 0, 1)
+#define MPP15_UA1_RTSn        MPP(15, 0x4, 0, 0, 1)
+#define MPP15_NAND_FLASH_WEn1    MPP(15, 0x5, 0, 0, 1)
+#define MPP15_TDM_SMISO        MPP(15, 0x6, 0, 0, 1)
 #define MPP15_UNUSED        MPP(15, 0x1, 0, 0, 1)
 
 #define MPP16_GPIO        MPP(16, 0x0, 1, 1, 1)
-#define MPP16_SATA1_PRESENTn    MPP(16, 0x3, 0, 1, 1)
-#define MPP16_UA2_TXD        MPP(16, 0x4, 0, 1, 1)
-#define MPP16_NAND_FLASH_REn3    MPP(16, 0x5, 0, 1, 1)
-#define MPP16_TDM_INTn        MPP(16, 0x6, 1, 0, 1)
+#define MPP16_SATA1_PRESENTn    MPP(16, 0x3, 0, 0, 1)
+#define MPP16_UA2_TXD        MPP(16, 0x4, 0, 0, 1)
+#define MPP16_NAND_FLASH_REn3    MPP(16, 0x5, 0, 0, 1)
+#define MPP16_TDM_INTn        MPP(16, 0x6, 0, 0, 1)
 #define MPP16_UNUSED        MPP(16, 0x1, 0, 0, 1)
 
 
 #define MPP17_GPIO        MPP(17, 0x0, 1, 1, 1)
-#define MPP17_SATA0_PRESENTn    MPP(17, 0x3, 0, 1, 1)
-#define MPP17_UA2_RXD        MPP(17, 0x4, 1, 0, 1)
-#define MPP17_NAND_FLASH_WEn3    MPP(17, 0x5, 0, 1, 1)
-#define MPP17_TDM_RSTn        MPP(17, 0x6, 0, 1, 1)
+#define MPP17_SATA0_PRESENTn    MPP(17, 0x3, 0, 0, 1)
+#define MPP17_UA2_RXD        MPP(17, 0x4, 0, 0, 1)
+#define MPP17_NAND_FLASH_WEn3    MPP(17, 0x5, 0, 0, 1)
+#define MPP17_TDM_RSTn        MPP(17, 0x6, 0, 0, 1)
 #define MPP17_UNUSED        MPP(17, 0x1, 0, 0, 1)
 
 
 #define MPP18_GPIO        MPP(18, 0x0, 1, 1, 1)
-#define MPP18_UA0_CTSn        MPP(18, 0x4, 1, 0, 1)
-#define MPP18_BOOT_FLASH_REn    MPP(18, 0x5, 0, 1, 1)
+#define MPP18_UA0_CTSn        MPP(18, 0x4, 0, 0, 1)
+#define MPP18_BOOT_FLASH_REn    MPP(18, 0x5, 0, 0, 1)
 #define MPP18_UNUSED        MPP(18, 0x1, 0, 0, 1)
 
 
 
 #define MPP19_GPIO        MPP(19, 0x0, 1, 1, 1)
-#define MPP19_UA0_CTSn        MPP(19, 0x4, 0, 1, 1)
-#define MPP19_BOOT_FLASH_WEn    MPP(19, 0x5, 0, 1, 1)
+#define MPP19_UA0_CTSn        MPP(19, 0x4, 0, 0, 1)
+#define MPP19_BOOT_FLASH_WEn    MPP(19, 0x5, 0, 0, 1)
 #define MPP19_UNUSED        MPP(19, 0x1, 0, 0, 1)
 
 
 #define MPP20_GPIO        MPP(20, 0x0, 1, 1, 1)
-#define MPP20_UA1_CTSs        MPP(20, 0x4, 1, 0, 1)
-#define MPP20_TDM_PCLK        MPP(20, 0x6, 1, 1, 0)
+#define MPP20_UA1_CTSs        MPP(20, 0x4, 0, 0, 1)
+#define MPP20_TDM_PCLK        MPP(20, 0x6, 0, 0, 0)
 #define MPP20_UNUSED        MPP(20, 0x1, 0, 0, 1)
 
 
 
 #define MPP21_GPIO        MPP(21, 0x0, 1, 1, 1)
-#define MPP21_UA1_CTSs        MPP(21, 0x4, 0, 1, 1)
-#define MPP21_TDM_FSYNC        MPP(21, 0x6, 1, 1, 0)
+#define MPP21_UA1_CTSs        MPP(21, 0x4, 0, 0, 1)
+#define MPP21_TDM_FSYNC        MPP(21, 0x6, 0, 0, 0)
 #define MPP21_UNUSED        MPP(21, 0x1, 0, 0, 1)
 
 
 
 #define MPP22_GPIO        MPP(22, 0x0, 1, 1, 1)
-#define MPP22_UA3_TDX        MPP(22, 0x4, 0, 1, 1)
-#define MPP22_NAND_FLASH_REn2    MPP(22, 0x5, 0, 1, 1)
-#define MPP22_TDM_DRX        MPP(22, 0x6, 1, 0, 1)
+#define MPP22_UA3_TDX        MPP(22, 0x4, 0, 0, 1)
+#define MPP22_NAND_FLASH_REn2    MPP(22, 0x5, 0, 0, 1)
+#define MPP22_TDM_DRX        MPP(22, 0x6, 0, 0, 1)
 #define MPP22_UNUSED        MPP(22, 0x1, 0, 0, 1)
 
 
 
 #define MPP23_GPIO        MPP(23, 0x0, 1, 1, 1)
-#define MPP23_UA3_RDX        MPP(23, 0x4, 1, 0, 1)
-#define MPP23_NAND_FLASH_WEn2    MPP(23, 0x5, 0, 1, 1)
-#define MPP23_TDM_DTX        MPP(23, 0x6, 0, 1, 1)
+#define MPP23_UA3_RDX        MPP(23, 0x4, 0, 0, 1)
+#define MPP23_NAND_FLASH_WEn2    MPP(23, 0x5, 0, 0, 1)
+#define MPP23_TDM_DTX        MPP(23, 0x6, 0, 0, 1)
 #define MPP23_UNUSED        MPP(23, 0x1, 0, 0, 1)
 
 
 #define MPP24_GPIO        MPP(24, 0x0, 1, 1, 1)
-#define MPP24_UA2_TXD        MPP(24, 0x4, 0, 1, 1)
-#define MPP24_TDM_INTn        MPP(24, 0x6, 1, 0, 1)
+#define MPP24_UA2_TXD        MPP(24, 0x4, 0, 0, 1)
+#define MPP24_TDM_INTn        MPP(24, 0x6, 0, 0, 1)
 #define MPP24_UNUSED        MPP(24, 0x1, 0, 0, 1)
 
 
 #define MPP25_GPIO        MPP(25, 0x0, 1, 1, 1)
-#define MPP25_UA2_RXD        MPP(25, 0x4, 1, 0, 1)
-#define MPP25_TDM_RSTn        MPP(25, 0x6, 0, 1, 1)
+#define MPP25_UA2_RXD        MPP(25, 0x4, 0, 0, 1)
+#define MPP25_TDM_RSTn        MPP(25, 0x6, 0, 0, 1)
 #define MPP25_UNUSED        MPP(25, 0x1, 0, 0, 1)
 
 
 #define MPP26_GPIO        MPP(26, 0x0, 1, 1, 1)
-#define MPP26_UA2_CTSn        MPP(26, 0x4, 1, 0, 1)
-#define MPP26_TDM_PCLK        MPP(26, 0x6, 1, 1, 1)
+#define MPP26_UA2_CTSn        MPP(26, 0x4, 0, 0, 1)
+#define MPP26_TDM_PCLK        MPP(26, 0x6, 0, 0, 1)
 #define MPP26_UNUSED        MPP(26, 0x1, 0, 0, 1)
 
 
 #define MPP27_GPIO        MPP(27, 0x0, 1, 1, 1)
-#define MPP27_UA2_RTSn        MPP(27, 0x4, 0, 1, 1)
-#define MPP27_TDM_FSYNC        MPP(27, 0x6, 1, 1, 1)
+#define MPP27_UA2_RTSn        MPP(27, 0x4, 0, 0, 1)
+#define MPP27_TDM_FSYNC        MPP(27, 0x6, 0, 0, 1)
 #define MPP27_UNUSED        MPP(27, 0x1, 0, 0, 1)
 
 
 #define MPP28_GPIO        MPP(28, 0x0, 1, 1, 1)
-#define MPP28_UA3_TXD        MPP(28, 0x4, 0, 1, 1)
-#define MPP28_TDM_DRX        MPP(28, 0x6, 1, 0, 1)
+#define MPP28_UA3_TXD        MPP(28, 0x4, 0, 0, 1)
+#define MPP28_TDM_DRX        MPP(28, 0x6, 0, 0, 1)
 #define MPP28_UNUSED        MPP(28, 0x1, 0, 0, 1)
 
 #define MPP29_GPIO        MPP(29, 0x0, 1, 1, 1)
-#define MPP29_UA3_RXD        MPP(29, 0x4, 1, 0, 1)
-#define MPP29_SYSRST_OUTn    MPP(29, 0x5, 0, 1, 1)
-#define MPP29_TDM_DTX        MPP(29, 0x6, 0, 1, 1)
+#define MPP29_UA3_RXD        MPP(29, 0x4, 0, 0, 1)
+#define MPP29_SYSRST_OUTn    MPP(29, 0x5, 0, 0, 1)
+#define MPP29_TDM_DTX        MPP(29, 0x6, 0, 0, 1)
 #define MPP29_UNUSED        MPP(29, 0x1, 0, 0, 1)
 
 #define MPP30_GPIO        MPP(30, 0x0, 1, 1, 1)
-#define MPP30_UA3_CTSn        MPP(30, 0x4, 1, 0, 1)
+#define MPP30_UA3_CTSn        MPP(30, 0x4, 0, 0, 1)
 #define MPP30_UNUSED        MPP(30, 0x1, 0, 0, 1)
 
 #define MPP31_GPIO        MPP(31, 0x0, 1, 1, 1)
-#define MPP31_UA3_RTSn        MPP(31, 0x4, 0, 1, 1)
-#define MPP31_TDM1_SCSn        MPP(31, 0x6, 0, 1, 1)
+#define MPP31_UA3_RTSn        MPP(31, 0x4, 0, 0, 1)
+#define MPP31_TDM1_SCSn        MPP(31, 0x6, 0, 0, 1)
 #define MPP31_UNUSED        MPP(31, 0x1, 0, 0, 1)
 
 
 #define MPP32_GPIO        MPP(32, 0x1, 1, 1, 1)
-#define MPP32_UA3_TDX        MPP(32, 0x4, 0, 1, 1)
-#define MPP32_SYSRST_OUTn    MPP(32, 0x5, 0, 1, 1)
-#define MPP32_TDM0_RXQ        MPP(32, 0x6, 0, 1, 1)
+#define MPP32_UA3_TDX        MPP(32, 0x4, 0, 0, 1)
+#define MPP32_SYSRST_OUTn    MPP(32, 0x5, 0, 0, 1)
+#define MPP32_TDM0_RXQ        MPP(32, 0x6, 0, 0, 1)
 #define MPP32_UNUSED        MPP(32, 0x3, 0, 0, 1)
 
 
 #define MPP33_GPIO        MPP(33, 0x1, 1, 1, 1)
-#define MPP33_UA3_RDX        MPP(33, 0x4, 1, 0, 1)
-#define MPP33_TDM0_TXQ        MPP(33, 0x6, 0, 1, 1)
+#define MPP33_UA3_RDX        MPP(33, 0x4, 0, 0, 1)
+#define MPP33_TDM0_TXQ        MPP(33, 0x6, 0, 0, 1)
 #define MPP33_UNUSED        MPP(33, 0x3, 0, 0, 1)
 
 
 
 #define MPP34_GPIO        MPP(34, 0x1, 1, 1, 1)
-#define MPP34_UA2_TDX        MPP(34, 0x4, 0, 1, 1)
-#define MPP34_TDM1_RXQ        MPP(34, 0x6, 0, 1, 1)
+#define MPP34_UA2_TDX        MPP(34, 0x4, 0, 0, 1)
+#define MPP34_TDM1_RXQ        MPP(34, 0x6, 0, 0, 1)
 #define MPP34_UNUSED        MPP(34, 0x3, 0, 0, 1)
 
 
 
 #define MPP35_GPIO        MPP(35, 0x1, 1, 1, 1)
-#define MPP35_UA2_RDX        MPP(35, 0x4, 1, 0, 1)
-#define MPP35_TDM1_TXQ        MPP(35, 0x6, 0, 1, 1)
+#define MPP35_UA2_RDX        MPP(35, 0x4, 0, 0, 1)
+#define MPP35_TDM1_TXQ        MPP(35, 0x6, 0, 0, 1)
 #define MPP35_UNUSED        MPP(35, 0x3, 0, 0, 1)
 
 #define MPP36_GPIO        MPP(36, 0x1, 1, 1, 1)
-#define MPP36_UA0_CTSn        MPP(36, 0x2, 1, 0, 1)
-#define MPP36_UA2_TDX        MPP(36, 0x4, 0, 1, 1)
-#define MPP36_TDM0_SCSn        MPP(36, 0x6, 0, 1, 1)
+#define MPP36_UA0_CTSn        MPP(36, 0x2, 0, 0, 1)
+#define MPP36_UA2_TDX        MPP(36, 0x4, 0, 0, 1)
+#define MPP36_TDM0_SCSn        MPP(36, 0x6, 0, 0, 1)
 #define MPP36_UNUSED        MPP(36, 0x3, 0, 0, 1)
 
 
 #define MPP37_GPIO        MPP(37, 0x1, 1, 1, 1)
-#define MPP37_UA0_RTSn        MPP(37, 0x2, 0, 1, 1)
-#define MPP37_UA2_RXD        MPP(37, 0x4, 1, 0, 1)
-#define MPP37_SYSRST_OUTn    MPP(37, 0x5, 0, 1, 1)
-#define MPP37_TDM_SCLK        MPP(37, 0x6, 0, 1, 1)
+#define MPP37_UA0_RTSn        MPP(37, 0x2, 0, 0, 1)
+#define MPP37_UA2_RXD        MPP(37, 0x4, 0, 0, 1)
+#define MPP37_SYSRST_OUTn    MPP(37, 0x5, 0, 0, 1)
+#define MPP37_TDM_SCLK        MPP(37, 0x6, 0, 0, 1)
 #define MPP37_UNUSED        MPP(37, 0x3, 0, 0, 1)
 
 
 
 
 #define MPP38_GPIO        MPP(38, 0x1, 1, 1, 1)
-#define MPP38_UA1_CTSn        MPP(38, 0x2, 1, 0, 1)
-#define MPP38_UA3_TXD        MPP(38, 0x4, 0, 1, 1)
-#define MPP38_SYSRST_OUTn    MPP(38, 0x5, 0, 1, 1)
-#define MPP38_TDM_SMOSI        MPP(38, 0x6, 0, 1, 1)
+#define MPP38_UA1_CTSn        MPP(38, 0x2, 0, 0, 1)
+#define MPP38_UA3_TXD        MPP(38, 0x4, 0, 0, 1)
+#define MPP38_SYSRST_OUTn    MPP(38, 0x5, 0, 0, 1)
+#define MPP38_TDM_SMOSI        MPP(38, 0x6, 0, 0, 1)
 #define MPP38_UNUSED        MPP(38, 0x3, 0, 0, 1)
 
 
 
 
 #define MPP39_GPIO        MPP(39, 0x1, 1, 1, 1)
-#define MPP39_UA1_RTSn        MPP(39, 0x2, 0, 1, 1)
-#define MPP39_UA3_RXD        MPP(39, 0x4, 1, 0, 1)
-#define MPP39_SYSRST_OUTn    MPP(39, 0x5, 0, 1, 1)
-#define MPP39_TDM_SMISO        MPP(39, 0x6, 1, 0, 1)
+#define MPP39_UA1_RTSn        MPP(39, 0x2, 0, 0, 1)
+#define MPP39_UA3_RXD        MPP(39, 0x4, 0, 0, 1)
+#define MPP39_SYSRST_OUTn    MPP(39, 0x5, 0, 0, 1)
+#define MPP39_TDM_SMISO        MPP(39, 0x6, 0, 0, 1)
 #define MPP39_UNUSED        MPP(39, 0x3, 0, 0, 1)
 
 
 
 #define MPP40_GPIO        MPP(40, 0x1, 1, 1, 1)
-#define MPP40_TDM_INTn        MPP(40, 0x6, 1, 0, 1)
+#define MPP40_TDM_INTn        MPP(40, 0x6, 0, 0, 1)
 #define MPP40_UNUSED        MPP(40, 0x0, 0, 0, 1)
 
 
 
 #define MPP41_GPIO        MPP(41, 0x1, 1, 1, 1)
-#define MPP41_TDM_RSTn        MPP(41, 0x6, 0, 1, 1)
+#define MPP41_TDM_RSTn        MPP(41, 0x6, 0, 0, 1)
 #define MPP41_UNUSED        MPP(41, 0x0, 0, 0, 1)
 
 
 
 #define MPP42_GPIO        MPP(42, 0x1, 1, 1, 1)
-#define MPP42_TDM_PCLK        MPP(42, 0x6, 1, 1, 1)
+#define MPP42_TDM_PCLK        MPP(42, 0x6, 0, 0, 1)
 #define MPP42_UNUSED        MPP(42, 0x0, 0, 0, 1)
 
 
 
 #define MPP43_GPIO        MPP(43, 0x1, 1, 1, 1)
-#define MPP43_TDM_FSYNC        MPP(43, 0x6, 1, 1, 1)
+#define MPP43_TDM_FSYNC        MPP(43, 0x6, 0, 0, 1)
 #define MPP43_UNUSED        MPP(43, 0x0, 0, 0, 1)
 
 
 
 #define MPP44_GPIO        MPP(44, 0x1, 1, 1, 1)
-#define MPP44_TDM_DRX        MPP(44, 0x6, 1, 0, 1)
+#define MPP44_TDM_DRX        MPP(44, 0x6, 0, 0, 1)
 #define MPP44_UNUSED        MPP(44, 0x0, 0, 0, 1)
 
 
 
 #define MPP45_GPIO        MPP(45, 0x1, 1, 1, 1)
-#define MPP45_SATA0_ACTn    MPP(45, 0x3, 0, 1, 1)
-#define MPP45_TDM_DRX        MPP(45, 0x6, 0, 1, 1)
+#define MPP45_SATA0_ACTn    MPP(45, 0x3, 0, 0, 1)
+#define MPP45_TDM_DRX        MPP(45, 0x6, 0, 0, 1)
 #define MPP45_UNUSED        MPP(45, 0x0, 0, 0, 1)
 
 
 #define MPP46_GPIO        MPP(46, 0x1, 1, 1, 1)
-#define MPP46_TDM_SCSn        MPP(46, 0x6, 0, 1, 1)
+#define MPP46_TDM_SCSn        MPP(46, 0x6, 0, 0, 1)
 #define MPP46_UNUSED        MPP(46, 0x0, 0, 0, 1)
 
 
 
 
 #define MPP48_GPIO        MPP(48, 0x1, 1, 1, 1)
-#define MPP48_SATA1_ACTn    MPP(48, 0x3, 0, 1, 1)
+#define MPP48_SATA1_ACTn    MPP(48, 0x3, 0, 0, 1)
 #define MPP48_UNUSED        MPP(48, 0x2, 0, 0, 1)
 
 
 
 #define MPP49_GPIO        MPP(49, 0x1, 1, 1, 1)
-#define MPP49_SATA0_ACTn    MPP(49, 0x3, 0, 1, 1)
-#define MPP49_M_BB        MPP(49, 0x4, 1, 0, 1)
+#define MPP49_SATA0_ACTn    MPP(49, 0x3, 0, 0, 1)
+#define MPP49_M_BB        MPP(49, 0x4, 0, 0, 1)
 #define MPP49_UNUSED        MPP(49, 0x2, 0, 0, 1)
 
 
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
deleted file mode 100644 (file)
index af0c212..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-if ARCH_MX5
-
-# ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single
-# image. So for most time, SOC_IMX50/51/53 should be used.
-
-config ARCH_MX51
-       bool
-
-config ARCH_MX50
-       bool
-
-config ARCH_MX53
-       bool
-
-config SOC_IMX50
-       bool
-       select CPU_V7
-       select ARM_L1_CACHE_SHIFT_6
-       select MXC_TZIC
-       select ARCH_MXC_IOMUX_V3
-       select ARCH_MXC_AUDMUX_V2
-       select ARCH_HAS_CPUFREQ
-       select ARCH_MX50
-
-config SOC_IMX51
-       bool
-       select CPU_V7
-       select ARM_L1_CACHE_SHIFT_6
-       select MXC_TZIC
-       select ARCH_MXC_IOMUX_V3
-       select ARCH_MXC_AUDMUX_V2
-       select ARCH_HAS_CPUFREQ
-       select ARCH_MX51
-
-config SOC_IMX53
-       bool
-       select CPU_V7
-       select ARM_L1_CACHE_SHIFT_6
-       select MXC_TZIC
-       select ARCH_MXC_IOMUX_V3
-       select ARCH_MX53
-
-#comment "i.MX50 machines:"
-
-config MACH_MX50_RDP
-       bool "Support MX50 reference design platform"
-       depends on BROKEN
-       select SOC_IMX50
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       help
-         Include support for MX50 reference design platform (RDP) board. This
-         includes specific configurations for the board and its peripherals.
-
-comment "i.MX51 machines:"
-
-config MACH_IMX51_DT
-       bool "Support i.MX51 platforms from device tree"
-       select SOC_IMX51
-       select USE_OF
-       select MACH_MX51_BABBAGE
-       help
-         Include support for Freescale i.MX51 based platforms
-         using the device tree for discovery
-
-config MACH_MX51_BABBAGE
-       bool "Support MX51 BABBAGE platforms"
-       select SOC_IMX51
-       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_MXC_EHCI
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       help
-         Include support for MX51 Babbage platform, also known as MX51EVK in
-         u-boot. This includes specific configurations for the board and its
-         peripherals.
-
-config MACH_MX51_3DS
-       bool "Support MX51PDK (3DS)"
-       select SOC_IMX51
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMX_KEYPAD
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       select MXC_DEBUG_BOARD
-       help
-         Include support for MX51PDK (3DS) platform. This includes specific
-         configurations for the board and its peripherals.
-
-config MACH_EUKREA_CPUIMX51
-       bool "Support Eukrea CPUIMX51 module"
-       select SOC_IMX51
-       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_MXC_EHCI
-       select IMX_HAVE_PLATFORM_MXC_NAND
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       help
-         Include support for Eukrea CPUIMX51 platform. This includes
-         specific configurations for the module and its peripherals.
-
-choice
-       prompt "Baseboard"
-       depends on MACH_EUKREA_CPUIMX51
-       default MACH_EUKREA_MBIMX51_BASEBOARD
-
-config MACH_EUKREA_MBIMX51_BASEBOARD
-       prompt "Eukrea MBIMX51 development board"
-       bool
-       select IMX_HAVE_PLATFORM_IMX_KEYPAD
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select LEDS_GPIO_REGISTER
-       help
-         This adds board specific devices that can be found on Eukrea's
-         MBIMX51 evaluation board.
-
-endchoice
-
-config MACH_EUKREA_CPUIMX51SD
-       bool "Support Eukrea CPUIMX51SD module"
-       select SOC_IMX51
-       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_MXC_EHCI
-       select IMX_HAVE_PLATFORM_MXC_NAND
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       help
-         Include support for Eukrea CPUIMX51SD platform. This includes
-         specific configurations for the module and its peripherals.
-
-choice
-       prompt "Baseboard"
-       depends on MACH_EUKREA_CPUIMX51SD
-       default MACH_EUKREA_MBIMXSD51_BASEBOARD
-
-config MACH_EUKREA_MBIMXSD51_BASEBOARD
-       prompt "Eukrea MBIMXSD development board"
-       bool
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select LEDS_GPIO_REGISTER
-       help
-         This adds board specific devices that can be found on Eukrea's
-         MBIMXSD evaluation board.
-
-endchoice
-
-config MX51_EFIKA_COMMON
-       bool
-       select SOC_IMX51
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_MXC_EHCI
-       select IMX_HAVE_PLATFORM_PATA_IMX
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       select MXC_ULPI if USB_ULPI
-
-config MACH_MX51_EFIKAMX
-       bool "Support MX51 Genesi Efika MX nettop"
-       select LEDS_GPIO_REGISTER
-       select MX51_EFIKA_COMMON
-       help
-         Include support for Genesi Efika MX nettop. This includes specific
-         configurations for the board and its peripherals.
-
-config MACH_MX51_EFIKASB
-       bool "Support MX51 Genesi Efika Smartbook"
-       select LEDS_GPIO_REGISTER
-       select MX51_EFIKA_COMMON
-       help
-         Include support for Genesi Efika Smartbook. This includes specific
-         configurations for the board and its peripherals.
-
-comment "i.MX53 machines:"
-
-config MACH_IMX53_DT
-       bool "Support i.MX53 platforms from device tree"
-       select SOC_IMX53
-       select USE_OF
-       select MACH_MX53_ARD
-       select MACH_MX53_EVK
-       select MACH_MX53_LOCO
-       select MACH_MX53_SMD
-       help
-         Include support for Freescale i.MX53 based platforms
-         using the device tree for discovery
-
-config MACH_MX53_EVK
-       bool "Support MX53 EVK platforms"
-       select SOC_IMX53
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       select LEDS_GPIO_REGISTER
-       help
-         Include support for MX53 EVK platform. This includes specific
-         configurations for the board and its peripherals.
-
-config MACH_MX53_SMD
-       bool "Support MX53 SMD platforms"
-       select SOC_IMX53
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       help
-         Include support for MX53 SMD platform. This includes specific
-         configurations for the board and its peripherals.
-
-config MACH_MX53_LOCO
-       bool "Support MX53 LOCO platforms"
-       select SOC_IMX53
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_GPIO_KEYS
-       select LEDS_GPIO_REGISTER
-       help
-         Include support for MX53 LOCO platform. This includes specific
-         configurations for the board and its peripherals.
-
-config MACH_MX53_ARD
-       bool "Support MX53 ARD platforms"
-       select SOC_IMX53
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select IMX_HAVE_PLATFORM_GPIO_KEYS
-       help
-         Include support for MX53 ARD platform. This includes specific
-         configurations for the board and its peripherals.
-
-endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
deleted file mode 100644 (file)
index 0fc6080..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
-
-obj-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
-obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
-obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
-obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
-obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
-obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
-obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
-obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
-obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
-obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
-obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
-obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
-obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
-
-obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
-obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot
deleted file mode 100644 (file)
index ca207ca..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-   zreladdr-$(CONFIG_ARCH_MX50)        += 0x70008000
-params_phys-$(CONFIG_ARCH_MX50)        := 0x70000100
-initrd_phys-$(CONFIG_ARCH_MX50)        := 0x70800000
-   zreladdr-$(CONFIG_ARCH_MX51)        += 0x90008000
-params_phys-$(CONFIG_ARCH_MX51)        := 0x90000100
-initrd_phys-$(CONFIG_ARCH_MX51)        := 0x90800000
-   zreladdr-$(CONFIG_ARCH_MX53)        += 0x70008000
-params_phys-$(CONFIG_ARCH_MX53)        := 0x70000100
-initrd_phys-$(CONFIG_ARCH_MX53)        := 0x70800000
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
deleted file mode 100644 (file)
index 944025d..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-
-#define CPUIMX51_USBH1_STP     IMX_GPIO_NR(1, 27)
-#define CPUIMX51_QUARTA_GPIO   IMX_GPIO_NR(3, 28)
-#define CPUIMX51_QUARTB_GPIO   IMX_GPIO_NR(3, 25)
-#define CPUIMX51_QUARTC_GPIO   IMX_GPIO_NR(3, 26)
-#define CPUIMX51_QUARTD_GPIO   IMX_GPIO_NR(3, 27)
-#define CPUIMX51_QUART_XTAL    14745600
-#define CPUIMX51_QUART_REGSHIFT        17
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET         0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN   (1 << 25)
-
-#define        MX51_USB_PLLDIV_12_MHZ          0x00
-#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
-#define        MX51_USB_PLL_DIV_24_MHZ         0x02
-
-static struct plat_serial8250_port serial_platform_data[] = {
-       {
-               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
-               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
-               .irqflags = IRQF_TRIGGER_HIGH,
-               .uartclk = CPUIMX51_QUART_XTAL,
-               .regshift = CPUIMX51_QUART_REGSHIFT,
-               .iotype = UPIO_MEM,
-               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-       }, {
-               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
-               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
-               .irqflags = IRQF_TRIGGER_HIGH,
-               .uartclk = CPUIMX51_QUART_XTAL,
-               .regshift = CPUIMX51_QUART_REGSHIFT,
-               .iotype = UPIO_MEM,
-               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-       }, {
-               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
-               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
-               .irqflags = IRQF_TRIGGER_HIGH,
-               .uartclk = CPUIMX51_QUART_XTAL,
-               .regshift = CPUIMX51_QUART_REGSHIFT,
-               .iotype = UPIO_MEM,
-               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-       }, {
-               .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-               .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
-               .irqflags = IRQF_TRIGGER_HIGH,
-               .uartclk = CPUIMX51_QUART_XTAL,
-               .regshift = CPUIMX51_QUART_REGSHIFT,
-               .iotype = UPIO_MEM,
-               .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-       }, {
-       }
-};
-
-static struct platform_device serial_device = {
-       .name = "serial8250",
-       .id = 0,
-       .dev = {
-               .platform_data = serial_platform_data,
-       },
-};
-
-static struct platform_device *devices[] __initdata = {
-       &serial_device,
-};
-
-static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
-       /* UART1 */
-       MX51_PAD_UART1_RXD__UART1_RXD,
-       MX51_PAD_UART1_TXD__UART1_TXD,
-       MX51_PAD_UART1_RTS__UART1_RTS,
-       MX51_PAD_UART1_CTS__UART1_CTS,
-
-       /* I2C2 */
-       MX51_PAD_GPIO1_2__I2C2_SCL,
-       MX51_PAD_GPIO1_3__I2C2_SDA,
-       MX51_PAD_NANDF_D10__GPIO3_30,
-
-       /* QUART IRQ */
-       MX51_PAD_NANDF_D15__GPIO3_25,
-       MX51_PAD_NANDF_D14__GPIO3_26,
-       MX51_PAD_NANDF_D13__GPIO3_27,
-       MX51_PAD_NANDF_D12__GPIO3_28,
-
-       /* USB HOST1 */
-       MX51_PAD_USBH1_CLK__USBH1_CLK,
-       MX51_PAD_USBH1_DIR__USBH1_DIR,
-       MX51_PAD_USBH1_NXT__USBH1_NXT,
-       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-       MX51_PAD_USBH1_STP__USBH1_STP,
-};
-
-static const struct mxc_nand_platform_data
-               eukrea_cpuimx51_nand_board_info __initconst = {
-       .width          = 1,
-       .hw_ecc         = 1,
-       .flash_bbt      = 1,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const
-struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
-       .bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("pcf8563", 0x51),
-       },
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       /* Set the PHY clock to 19.2MHz */
-       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-       v |= MX51_USB_PLL_DIV_19_2_MHZ;
-       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       /* The clock for the USBH1 ULPI port will come externally from the PHY. */
-       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-                       MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-       .init           = initialize_otg_port,
-       .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-       .operating_mode = FSL_USB2_DR_DEVICE,
-       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-       .init           = initialize_usbh1_port,
-       .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51_otg_mode(char *options)
-{
-       if (!strcmp(options, "host"))
-               otg_mode_host = 1;
-       else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
-       else
-               pr_info("otg_mode neither \"host\" nor \"device\". "
-                       "Defaulting to device\n");
-       return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
-
-/*
- * Board specific initialization.
- */
-static void __init eukrea_cpuimx51_init(void)
-{
-       imx51_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
-                                       ARRAY_SIZE(eukrea_cpuimx51_pads));
-
-       imx51_add_imx_uart(0, &uart_pdata);
-       imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
-
-       gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
-       gpio_direction_input(CPUIMX51_QUARTA_GPIO);
-       gpio_free(CPUIMX51_QUARTA_GPIO);
-       gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
-       gpio_direction_input(CPUIMX51_QUARTB_GPIO);
-       gpio_free(CPUIMX51_QUARTB_GPIO);
-       gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
-       gpio_direction_input(CPUIMX51_QUARTC_GPIO);
-       gpio_free(CPUIMX51_QUARTC_GPIO);
-       gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
-       gpio_direction_input(CPUIMX51_QUARTD_GPIO);
-       gpio_free(CPUIMX51_QUARTD_GPIO);
-
-       imx51_add_fec(NULL);
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-
-       imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
-       i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
-                               ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
-
-       if (otg_mode_host)
-               imx51_add_mxc_ehci_otg(&dr_utmi_config);
-       else {
-               initialize_otg_port(NULL);
-               imx51_add_fsl_usb2_udc(&usb_pdata);
-       }
-       imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
-       eukrea_mbimx51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51_timer_init(void)
-{
-       mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
-       .init   = eukrea_cpuimx51_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
-       /* Maintainer: Eric Bénard <eric@eukrea.com> */
-       .atag_offset = 0x100,
-       .map_io = mx51_map_io,
-       .init_early = imx51_init_early,
-       .init_irq = mx51_init_irq,
-       .handle_irq = imx51_handle_irq,
-       .timer = &mxc_timer,
-       .init_machine = eukrea_cpuimx51_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
deleted file mode 100644 (file)
index 9fbe923..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/i2c-gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/can/platform/mcp251x.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "cpu_op-mx51.h"
-
-#define USBH1_RST              IMX_GPIO_NR(2, 28)
-#define ETH_RST                        IMX_GPIO_NR(2, 31)
-#define TSC2007_IRQGPIO                IMX_GPIO_NR(3, 12)
-#define CAN_IRQGPIO            IMX_GPIO_NR(1, 1)
-#define CAN_RST                        IMX_GPIO_NR(4, 15)
-#define CAN_NCS                        IMX_GPIO_NR(4, 24)
-#define CAN_RXOBF              IMX_GPIO_NR(1, 4)
-#define CAN_RX1BF              IMX_GPIO_NR(1, 6)
-#define CAN_TXORTS             IMX_GPIO_NR(1, 7)
-#define CAN_TX1RTS             IMX_GPIO_NR(1, 8)
-#define CAN_TX2RTS             IMX_GPIO_NR(1, 9)
-#define I2C_SCL                        IMX_GPIO_NR(4, 16)
-#define I2C_SDA                        IMX_GPIO_NR(4, 17)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET         0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN   (1 << 25)
-
-#define        MX51_USB_PLLDIV_12_MHZ          0x00
-#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
-#define        MX51_USB_PLL_DIV_24_MHZ         0x02
-
-static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
-       /* UART1 */
-       MX51_PAD_UART1_RXD__UART1_RXD,
-       MX51_PAD_UART1_TXD__UART1_TXD,
-       MX51_PAD_UART1_RTS__UART1_RTS,
-       MX51_PAD_UART1_CTS__UART1_CTS,
-
-       /* USB HOST1 */
-       MX51_PAD_USBH1_CLK__USBH1_CLK,
-       MX51_PAD_USBH1_DIR__USBH1_DIR,
-       MX51_PAD_USBH1_NXT__USBH1_NXT,
-       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-       MX51_PAD_USBH1_STP__USBH1_STP,
-       MX51_PAD_EIM_CS3__GPIO2_28,             /* PHY nRESET */
-
-       /* FEC */
-       MX51_PAD_EIM_DTACK__GPIO2_31,           /* PHY nRESET */
-
-       /* HSI2C */
-       MX51_PAD_I2C1_CLK__GPIO4_16,
-       MX51_PAD_I2C1_DAT__GPIO4_17,
-
-       /* CAN */
-       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-       MX51_PAD_CSPI1_SS0__GPIO4_24,           /* nCS */
-       MX51_PAD_CSI2_PIXCLK__GPIO4_15,         /* nReset */
-       MX51_PAD_GPIO1_1__GPIO1_1,              /* IRQ */
-       MX51_PAD_GPIO1_4__GPIO1_4,              /* Control signals */
-       MX51_PAD_GPIO1_6__GPIO1_6,
-       MX51_PAD_GPIO1_7__GPIO1_7,
-       MX51_PAD_GPIO1_8__GPIO1_8,
-       MX51_PAD_GPIO1_9__GPIO1_9,
-
-       /* Touchscreen */
-       /* IRQ */
-       NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
-                       PAD_CTL_PKE | PAD_CTL_SRE_FAST |
-                       PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct tsc2007_platform_data tsc2007_info = {
-       .model                  = 2007,
-       .x_plate_ohms           = 180,
-};
-
-static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("pcf8563", 0x51),
-       }, {
-               I2C_BOARD_INFO("tsc2007", 0x49),
-               .type           = "tsc2007",
-               .platform_data  = &tsc2007_info,
-               .irq            = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
-       },
-};
-
-static const struct mxc_nand_platform_data
-               eukrea_cpuimx51sd_nand_board_info __initconst = {
-       .width          = 1,
-       .hw_ecc         = 1,
-       .flash_bbt      = 1,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       /* Set the PHY clock to 19.2MHz */
-       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-       v |= MX51_USB_PLL_DIV_19_2_MHZ;
-       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       /* The clock for the USBH1 ULPI port will come from the PHY. */
-       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
-                       usbother_base + MX51_USB_CTRL_1_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-                       MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-       .init           = initialize_otg_port,
-       .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-       .operating_mode = FSL_USB2_DR_DEVICE,
-       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-       .init           = initialize_usbh1_port,
-       .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51sd_otg_mode(char *options)
-{
-       if (!strcmp(options, "host"))
-               otg_mode_host = 1;
-       else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
-       else
-               pr_info("otg_mode neither \"host\" nor \"device\". "
-                       "Defaulting to device\n");
-       return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
-
-static struct i2c_gpio_platform_data pdata = {
-       .sda_pin                = I2C_SDA,
-       .sda_is_open_drain      = 0,
-       .scl_pin                = I2C_SCL,
-       .scl_is_open_drain      = 0,
-       .udelay                 = 2,
-};
-
-static struct platform_device hsi2c_gpio_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata,
-};
-
-static struct mcp251x_platform_data mcp251x_info = {
-       .oscillator_frequency = 24E6,
-};
-
-static struct spi_board_info cpuimx51sd_spi_device[] = {
-       {
-               .modalias        = "mcp2515",
-               .max_speed_hz    = 10000000,
-               .bus_num         = 0,
-               .mode           = SPI_MODE_0,
-               .chip_select     = 0,
-               .platform_data   = &mcp251x_info,
-               .irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
-       },
-};
-
-static int cpuimx51sd_spi1_cs[] = {
-       CAN_NCS,
-};
-
-static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
-       .chipselect     = cpuimx51sd_spi1_cs,
-       .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-       &hsi2c_gpio_device,
-};
-
-static void __init eukrea_cpuimx51sd_init(void)
-{
-       imx51_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
-                                       ARRAY_SIZE(eukrea_cpuimx51sd_pads));
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-       get_cpu_op = mx51_get_cpu_op;
-#endif
-
-       imx51_add_imx_uart(0, &uart_pdata);
-       imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
-
-       gpio_request(ETH_RST, "eth_rst");
-       gpio_set_value(ETH_RST, 1);
-       imx51_add_fec(NULL);
-
-       gpio_request(CAN_IRQGPIO, "can_irq");
-       gpio_direction_input(CAN_IRQGPIO);
-       gpio_free(CAN_IRQGPIO);
-       gpio_request(CAN_NCS, "can_ncs");
-       gpio_direction_output(CAN_NCS, 1);
-       gpio_free(CAN_NCS);
-       gpio_request(CAN_RST, "can_rst");
-       gpio_direction_output(CAN_RST, 0);
-       msleep(20);
-       gpio_set_value(CAN_RST, 1);
-       imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
-       spi_register_board_info(cpuimx51sd_spi_device,
-                               ARRAY_SIZE(cpuimx51sd_spi_device));
-
-       gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
-       gpio_direction_input(TSC2007_IRQGPIO);
-       gpio_free(TSC2007_IRQGPIO);
-
-       i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
-                       ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
-       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-
-       if (otg_mode_host)
-               imx51_add_mxc_ehci_otg(&dr_utmi_config);
-       else {
-               initialize_otg_port(NULL);
-               imx51_add_fsl_usb2_udc(&usb_pdata);
-       }
-
-       gpio_request(USBH1_RST, "usb_rst");
-       gpio_direction_output(USBH1_RST, 0);
-       msleep(20);
-       gpio_set_value(USBH1_RST, 1);
-       imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
-       eukrea_mbimxsd51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51sd_timer_init(void)
-{
-       mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
-       .init   = eukrea_cpuimx51sd_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
-       /* Maintainer: Eric Bénard <eric@eukrea.com> */
-       .atag_offset = 0x100,
-       .map_io = mx51_map_io,
-       .init_early = imx51_init_early,
-       .init_irq = mx51_init_irq,
-       .handle_irq = imx51_handle_irq,
-       .timer = &mxc_timer,
-       .init_machine = eukrea_cpuimx51sd_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
deleted file mode 100644 (file)
index 42b66e8..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2010 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 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx50.h>
-
-#include <asm/irq.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx50.h"
-
-#define FEC_EN         IMX_GPIO_NR(6, 23)
-#define FEC_RESET_B    IMX_GPIO_NR(4, 12)
-
-static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
-       /* SD1 */
-       MX50_PAD_ECSPI2_SS0__GPIO_4_19,
-       MX50_PAD_EIM_CRE__GPIO_1_27,
-       MX50_PAD_SD1_CMD__SD1_CMD,
-
-       MX50_PAD_SD1_CLK__SD1_CLK,
-       MX50_PAD_SD1_D0__SD1_D0,
-       MX50_PAD_SD1_D1__SD1_D1,
-       MX50_PAD_SD1_D2__SD1_D2,
-       MX50_PAD_SD1_D3__SD1_D3,
-
-       /* SD2 */
-       MX50_PAD_SD2_CD__GPIO_5_17,
-       MX50_PAD_SD2_WP__GPIO_5_16,
-       MX50_PAD_SD2_CMD__SD2_CMD,
-       MX50_PAD_SD2_CLK__SD2_CLK,
-       MX50_PAD_SD2_D0__SD2_D0,
-       MX50_PAD_SD2_D1__SD2_D1,
-       MX50_PAD_SD2_D2__SD2_D2,
-       MX50_PAD_SD2_D3__SD2_D3,
-       MX50_PAD_SD2_D4__SD2_D4,
-       MX50_PAD_SD2_D5__SD2_D5,
-       MX50_PAD_SD2_D6__SD2_D6,
-       MX50_PAD_SD2_D7__SD2_D7,
-
-       /* SD3 */
-       MX50_PAD_SD3_CMD__SD3_CMD,
-       MX50_PAD_SD3_CLK__SD3_CLK,
-       MX50_PAD_SD3_D0__SD3_D0,
-       MX50_PAD_SD3_D1__SD3_D1,
-       MX50_PAD_SD3_D2__SD3_D2,
-       MX50_PAD_SD3_D3__SD3_D3,
-       MX50_PAD_SD3_D4__SD3_D4,
-       MX50_PAD_SD3_D5__SD3_D5,
-       MX50_PAD_SD3_D6__SD3_D6,
-       MX50_PAD_SD3_D7__SD3_D7,
-
-       /* PWR_INT */
-       MX50_PAD_ECSPI2_MISO__GPIO_4_18,
-
-       /* UART pad setting */
-       MX50_PAD_UART1_TXD__UART1_TXD,
-       MX50_PAD_UART1_RXD__UART1_RXD,
-       MX50_PAD_UART1_RTS__UART1_RTS,
-       MX50_PAD_UART2_TXD__UART2_TXD,
-       MX50_PAD_UART2_RXD__UART2_RXD,
-       MX50_PAD_UART2_CTS__UART2_CTS,
-       MX50_PAD_UART2_RTS__UART2_RTS,
-
-       MX50_PAD_I2C1_SCL__I2C1_SCL,
-       MX50_PAD_I2C1_SDA__I2C1_SDA,
-       MX50_PAD_I2C2_SCL__I2C2_SCL,
-       MX50_PAD_I2C2_SDA__I2C2_SDA,
-
-       MX50_PAD_EPITO__USBH1_PWR,
-       /* Need to comment below line if
-        * one needs to debug owire.
-        */
-       MX50_PAD_OWIRE__USBH1_OC,
-       /* using gpio to control otg pwr */
-       MX50_PAD_PWM2__GPIO_6_25,
-       MX50_PAD_I2C3_SCL__USBOTG_OC,
-
-       MX50_PAD_SSI_RXC__FEC_MDIO,
-       MX50_PAD_SSI_RXFS__FEC_MDC,
-       MX50_PAD_DISP_D0__FEC_TXCLK,
-       MX50_PAD_DISP_D1__FEC_RX_ER,
-       MX50_PAD_DISP_D2__FEC_RX_DV,
-       MX50_PAD_DISP_D3__FEC_RXD1,
-       MX50_PAD_DISP_D4__FEC_RXD0,
-       MX50_PAD_DISP_D5__FEC_TX_EN,
-       MX50_PAD_DISP_D6__FEC_TXD1,
-       MX50_PAD_DISP_D7__FEC_TXD0,
-       MX50_PAD_I2C3_SDA__GPIO_6_23,
-       MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
-
-       MX50_PAD_CSPI_SS0__CSPI_SS0,
-       MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
-       MX50_PAD_CSPI_MOSI__CSPI_MOSI,
-       MX50_PAD_CSPI_MISO__CSPI_MISO,
-
-       /* SGTL500_OSC_EN */
-       MX50_PAD_UART1_CTS__GPIO_6_8,
-
-       /* SGTL_AMP_SHDN */
-       MX50_PAD_UART3_RXD__GPIO_6_15,
-
-       /* Keypad */
-       MX50_PAD_KEY_COL0__KEY_COL0,
-       MX50_PAD_KEY_ROW0__KEY_ROW0,
-       MX50_PAD_KEY_COL1__KEY_COL1,
-       MX50_PAD_KEY_ROW1__KEY_ROW1,
-       MX50_PAD_KEY_COL2__KEY_COL2,
-       MX50_PAD_KEY_ROW2__KEY_ROW2,
-       MX50_PAD_KEY_COL3__KEY_COL3,
-       MX50_PAD_KEY_ROW3__KEY_ROW3,
-       MX50_PAD_EIM_DA0__KEY_COL4,
-       MX50_PAD_EIM_DA1__KEY_ROW4,
-       MX50_PAD_EIM_DA2__KEY_COL5,
-       MX50_PAD_EIM_DA3__KEY_ROW5,
-       MX50_PAD_EIM_DA4__KEY_COL6,
-       MX50_PAD_EIM_DA5__KEY_ROW6,
-       MX50_PAD_EIM_DA6__KEY_COL7,
-       MX50_PAD_EIM_DA7__KEY_ROW7,
-       /*EIM pads */
-       MX50_PAD_EIM_DA8__GPIO_1_8,
-       MX50_PAD_EIM_DA9__GPIO_1_9,
-       MX50_PAD_EIM_DA10__GPIO_1_10,
-       MX50_PAD_EIM_DA11__GPIO_1_11,
-       MX50_PAD_EIM_DA12__GPIO_1_12,
-       MX50_PAD_EIM_DA13__GPIO_1_13,
-       MX50_PAD_EIM_DA14__GPIO_1_14,
-       MX50_PAD_EIM_DA15__GPIO_1_15,
-       MX50_PAD_EIM_CS2__GPIO_1_16,
-       MX50_PAD_EIM_CS1__GPIO_1_17,
-       MX50_PAD_EIM_CS0__GPIO_1_18,
-       MX50_PAD_EIM_EB0__GPIO_1_19,
-       MX50_PAD_EIM_EB1__GPIO_1_20,
-       MX50_PAD_EIM_WAIT__GPIO_1_21,
-       MX50_PAD_EIM_BCLK__GPIO_1_22,
-       MX50_PAD_EIM_RDY__GPIO_1_23,
-       MX50_PAD_EIM_OE__GPIO_1_24,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct fec_platform_data fec_data __initconst = {
-       .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static inline void mx50_rdp_fec_reset(void)
-{
-       gpio_request(FEC_EN, "fec-en");
-       gpio_direction_output(FEC_EN, 0);
-       gpio_request(FEC_RESET_B, "fec-reset_b");
-       gpio_direction_output(FEC_RESET_B, 0);
-       msleep(1);
-       gpio_set_value(FEC_RESET_B, 1);
-}
-
-static const struct imxi2c_platform_data i2c_data __initconst = {
-       .bitrate = 100000,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx50_rdp_board_init(void)
-{
-       imx50_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
-                                       ARRAY_SIZE(mx50_rdp_pads));
-
-       imx50_add_imx_uart(0, &uart_pdata);
-       imx50_add_imx_uart(1, &uart_pdata);
-       mx50_rdp_fec_reset();
-       imx50_add_fec(&fec_data);
-       imx50_add_imx_i2c(0, &i2c_data);
-       imx50_add_imx_i2c(1, &i2c_data);
-       imx50_add_imx_i2c(2, &i2c_data);
-}
-
-static void __init mx50_rdp_timer_init(void)
-{
-       mx50_clocks_init(32768, 24000000, 22579200);
-}
-
-static struct sys_timer mx50_rdp_timer = {
-       .init   = mx50_rdp_timer_init,
-};
-
-MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
-       .map_io = mx50_map_io,
-       .init_early = imx50_init_early,
-       .init_irq = mx50_init_irq,
-       .handle_irq = imx50_handle_irq,
-       .timer = &mx50_rdp_timer,
-       .init_machine = mx50_rdp_board_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
deleted file mode 100644 (file)
index 83eab41..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/3ds_debugboard.h>
-
-#include "devices-imx51.h"
-
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(1, 6))
-#define MX51_3DS_ECSPI2_CS     (GPIO_PORTC + 28)
-
-static iomux_v3_cfg_t mx51_3ds_pads[] = {
-       /* UART1 */
-       MX51_PAD_UART1_RXD__UART1_RXD,
-       MX51_PAD_UART1_TXD__UART1_TXD,
-       MX51_PAD_UART1_RTS__UART1_RTS,
-       MX51_PAD_UART1_CTS__UART1_CTS,
-
-       /* UART2 */
-       MX51_PAD_UART2_RXD__UART2_RXD,
-       MX51_PAD_UART2_TXD__UART2_TXD,
-       MX51_PAD_EIM_D25__UART2_CTS,
-       MX51_PAD_EIM_D26__UART2_RTS,
-
-       /* UART3 */
-       MX51_PAD_UART3_RXD__UART3_RXD,
-       MX51_PAD_UART3_TXD__UART3_TXD,
-       MX51_PAD_EIM_D24__UART3_CTS,
-       MX51_PAD_EIM_D27__UART3_RTS,
-
-       /* CPLD PARENT IRQ PIN */
-       MX51_PAD_GPIO1_6__GPIO1_6,
-
-       /* KPP */
-       MX51_PAD_KEY_ROW0__KEY_ROW0,
-       MX51_PAD_KEY_ROW1__KEY_ROW1,
-       MX51_PAD_KEY_ROW2__KEY_ROW2,
-       MX51_PAD_KEY_ROW3__KEY_ROW3,
-       MX51_PAD_KEY_COL0__KEY_COL0,
-       MX51_PAD_KEY_COL1__KEY_COL1,
-       MX51_PAD_KEY_COL2__KEY_COL2,
-       MX51_PAD_KEY_COL3__KEY_COL3,
-       MX51_PAD_KEY_COL4__KEY_COL4,
-       MX51_PAD_KEY_COL5__KEY_COL5,
-
-       /* eCSPI2 */
-       MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
-       MX51_PAD_NANDF_RB3__ECSPI2_MISO,
-       MX51_PAD_NANDF_D15__ECSPI2_MOSI,
-       MX51_PAD_NANDF_D12__GPIO3_28,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mx51_3ds_board_keymap[] = {
-       KEY(0, 0, KEY_1),
-       KEY(0, 1, KEY_2),
-       KEY(0, 2, KEY_3),
-       KEY(0, 3, KEY_F1),
-       KEY(0, 4, KEY_UP),
-       KEY(0, 5, KEY_F2),
-
-       KEY(1, 0, KEY_4),
-       KEY(1, 1, KEY_5),
-       KEY(1, 2, KEY_6),
-       KEY(1, 3, KEY_LEFT),
-       KEY(1, 4, KEY_SELECT),
-       KEY(1, 5, KEY_RIGHT),
-
-       KEY(2, 0, KEY_7),
-       KEY(2, 1, KEY_8),
-       KEY(2, 2, KEY_9),
-       KEY(2, 3, KEY_F3),
-       KEY(2, 4, KEY_DOWN),
-       KEY(2, 5, KEY_F4),
-
-       KEY(3, 0, KEY_0),
-       KEY(3, 1, KEY_OK),
-       KEY(3, 2, KEY_ESC),
-       KEY(3, 3, KEY_ENTER),
-       KEY(3, 4, KEY_MENU),
-       KEY(3, 5, KEY_BACK)
-};
-
-static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
-       .keymap         = mx51_3ds_board_keymap,
-       .keymap_size    = ARRAY_SIZE(mx51_3ds_board_keymap),
-};
-
-static int mx51_3ds_spi2_cs[] = {
-       MXC_SPI_CS(0),
-       MX51_3DS_ECSPI2_CS,
-};
-
-static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
-       .chipselect     = mx51_3ds_spi2_cs,
-       .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs),
-};
-
-static struct spi_board_info mx51_3ds_spi_nor_device[] = {
-       {
-        .modalias = "m25p80",
-        .max_speed_hz = 25000000,      /* max spi clock (SCK) speed in HZ */
-        .bus_num = 1,
-        .chip_select = 1,
-        .mode = SPI_MODE_0,
-        .platform_data = NULL,},
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_3ds_init(void)
-{
-       imx51_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
-                                       ARRAY_SIZE(mx51_3ds_pads));
-
-       imx51_add_imx_uart(0, &uart_pdata);
-       imx51_add_imx_uart(1, &uart_pdata);
-       imx51_add_imx_uart(2, &uart_pdata);
-
-       imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
-       spi_register_board_info(mx51_3ds_spi_nor_device,
-                               ARRAY_SIZE(mx51_3ds_spi_nor_device));
-
-       if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
-               printk(KERN_WARNING "Init of the debugboard failed, all "
-                                   "devices on the board are unusable.\n");
-
-       imx51_add_sdhci_esdhc_imx(0, NULL);
-       imx51_add_imx_keypad(&mx51_3ds_map_data);
-       imx51_add_imx2_wdt(0, NULL);
-}
-
-static void __init mx51_3ds_timer_init(void)
-{
-       mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_3ds_timer = {
-       .init = mx51_3ds_timer_init,
-};
-
-MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
-       /* Maintainer: Freescale Semiconductor, Inc. */
-       .atag_offset = 0x100,
-       .map_io = mx51_map_io,
-       .init_early = imx51_init_early,
-       .init_irq = mx51_init_irq,
-       .handle_irq = imx51_handle_irq,
-       .timer = &mx51_3ds_timer,
-       .init_machine = mx51_3ds_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
deleted file mode 100644 (file)
index e4b822e..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "cpu_op-mx51.h"
-
-#define BABBAGE_USB_HUB_RESET  IMX_GPIO_NR(1, 7)
-#define BABBAGE_USBH1_STP      IMX_GPIO_NR(1, 27)
-#define BABBAGE_USB_PHY_RESET  IMX_GPIO_NR(2, 5)
-#define BABBAGE_FEC_PHY_RESET  IMX_GPIO_NR(2, 14)
-#define BABBAGE_POWER_KEY      IMX_GPIO_NR(2, 21)
-#define BABBAGE_ECSPI1_CS0     IMX_GPIO_NR(4, 24)
-#define BABBAGE_ECSPI1_CS1     IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD2_CD         IMX_GPIO_NR(1, 6)
-#define BABBAGE_SD2_WP         IMX_GPIO_NR(1, 5)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET                 0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN           (1 << 25)
-
-#define        MX51_USB_PLLDIV_12_MHZ          0x00
-#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
-#define        MX51_USB_PLL_DIV_24_MHZ 0x02
-
-static struct gpio_keys_button babbage_buttons[] = {
-       {
-               .gpio           = BABBAGE_POWER_KEY,
-               .code           = BTN_0,
-               .desc           = "PWR",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-};
-
-static const struct gpio_keys_platform_data imx_button_data __initconst = {
-       .buttons        = babbage_buttons,
-       .nbuttons       = ARRAY_SIZE(babbage_buttons),
-};
-
-static iomux_v3_cfg_t mx51babbage_pads[] = {
-       /* UART1 */
-       MX51_PAD_UART1_RXD__UART1_RXD,
-       MX51_PAD_UART1_TXD__UART1_TXD,
-       MX51_PAD_UART1_RTS__UART1_RTS,
-       MX51_PAD_UART1_CTS__UART1_CTS,
-
-       /* UART2 */
-       MX51_PAD_UART2_RXD__UART2_RXD,
-       MX51_PAD_UART2_TXD__UART2_TXD,
-
-       /* UART3 */
-       MX51_PAD_EIM_D25__UART3_RXD,
-       MX51_PAD_EIM_D26__UART3_TXD,
-       MX51_PAD_EIM_D27__UART3_RTS,
-       MX51_PAD_EIM_D24__UART3_CTS,
-
-       /* I2C1 */
-       MX51_PAD_EIM_D16__I2C1_SDA,
-       MX51_PAD_EIM_D19__I2C1_SCL,
-
-       /* I2C2 */
-       MX51_PAD_KEY_COL4__I2C2_SCL,
-       MX51_PAD_KEY_COL5__I2C2_SDA,
-
-       /* HSI2C */
-       MX51_PAD_I2C1_CLK__I2C1_CLK,
-       MX51_PAD_I2C1_DAT__I2C1_DAT,
-
-       /* USB HOST1 */
-       MX51_PAD_USBH1_CLK__USBH1_CLK,
-       MX51_PAD_USBH1_DIR__USBH1_DIR,
-       MX51_PAD_USBH1_NXT__USBH1_NXT,
-       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
-       /* USB HUB reset line*/
-       MX51_PAD_GPIO1_7__GPIO1_7,
-
-       /* USB PHY reset line */
-       MX51_PAD_EIM_D21__GPIO2_5,
-
-       /* FEC */
-       MX51_PAD_EIM_EB2__FEC_MDIO,
-       MX51_PAD_EIM_EB3__FEC_RDATA1,
-       MX51_PAD_EIM_CS2__FEC_RDATA2,
-       MX51_PAD_EIM_CS3__FEC_RDATA3,
-       MX51_PAD_EIM_CS4__FEC_RX_ER,
-       MX51_PAD_EIM_CS5__FEC_CRS,
-       MX51_PAD_NANDF_RB2__FEC_COL,
-       MX51_PAD_NANDF_RB3__FEC_RX_CLK,
-       MX51_PAD_NANDF_D9__FEC_RDATA0,
-       MX51_PAD_NANDF_D8__FEC_TDATA0,
-       MX51_PAD_NANDF_CS2__FEC_TX_ER,
-       MX51_PAD_NANDF_CS3__FEC_MDC,
-       MX51_PAD_NANDF_CS4__FEC_TDATA1,
-       MX51_PAD_NANDF_CS5__FEC_TDATA2,
-       MX51_PAD_NANDF_CS6__FEC_TDATA3,
-       MX51_PAD_NANDF_CS7__FEC_TX_EN,
-       MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
-
-       /* FEC PHY reset line */
-       MX51_PAD_EIM_A20__GPIO2_14,
-
-       /* SD 1 */
-       MX51_PAD_SD1_CMD__SD1_CMD,
-       MX51_PAD_SD1_CLK__SD1_CLK,
-       MX51_PAD_SD1_DATA0__SD1_DATA0,
-       MX51_PAD_SD1_DATA1__SD1_DATA1,
-       MX51_PAD_SD1_DATA2__SD1_DATA2,
-       MX51_PAD_SD1_DATA3__SD1_DATA3,
-       /* CD/WP from controller */
-       MX51_PAD_GPIO1_0__SD1_CD,
-       MX51_PAD_GPIO1_1__SD1_WP,
-
-       /* SD 2 */
-       MX51_PAD_SD2_CMD__SD2_CMD,
-       MX51_PAD_SD2_CLK__SD2_CLK,
-       MX51_PAD_SD2_DATA0__SD2_DATA0,
-       MX51_PAD_SD2_DATA1__SD2_DATA1,
-       MX51_PAD_SD2_DATA2__SD2_DATA2,
-       MX51_PAD_SD2_DATA3__SD2_DATA3,
-       /* CD/WP gpio */
-       MX51_PAD_GPIO1_6__GPIO1_6,
-       MX51_PAD_GPIO1_5__GPIO1_5,
-
-       /* eCSPI1 */
-       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-       MX51_PAD_CSPI1_SS0__GPIO4_24,
-       MX51_PAD_CSPI1_SS1__GPIO4_25,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
-       .bitrate = 100000,
-};
-
-static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
-       .bitrate = 400000,
-};
-
-static struct gpio mx51_babbage_usbh1_gpios[] = {
-       { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
-       { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
-};
-
-static int gpio_usbh1_active(void)
-{
-       iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-       int ret;
-
-       /* Set USBH1_STP to GPIO and toggle it */
-       mxc_iomux_v3_setup_pad(usbh1stp_gpio);
-       ret = gpio_request_array(mx51_babbage_usbh1_gpios,
-                                       ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-
-       if (ret) {
-               pr_debug("failed to get USBH1 pins: %d\n", ret);
-               return ret;
-       }
-
-       msleep(100);
-       gpio_set_value(BABBAGE_USBH1_STP, 1);
-       gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
-       gpio_free_array(mx51_babbage_usbh1_gpios,
-                                       ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-       return 0;
-}
-
-static inline void babbage_usbhub_reset(void)
-{
-       int ret;
-
-       /* Reset USB hub */
-       ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
-                                       GPIOF_OUT_INIT_LOW, "GPIO1_7");
-       if (ret) {
-               printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
-               return;
-       }
-
-       msleep(2);
-       /* Deassert reset */
-       gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
-}
-
-static inline void babbage_fec_reset(void)
-{
-       int ret;
-
-       /* reset FEC PHY */
-       ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
-                                       GPIOF_OUT_INIT_LOW, "fec-phy-reset");
-       if (ret) {
-               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-               return;
-       }
-       msleep(1);
-       gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
-}
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       /* Set the PHY clock to 19.2MHz */
-       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-       v |= MX51_USB_PLL_DIV_19_2_MHZ;
-       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       /* The clock for the USBH1 ULPI port will come externally from the PHY. */
-       v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-                       MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-       .init           = initialize_otg_port,
-       .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-       .operating_mode = FSL_USB2_DR_DEVICE,
-       .phy_mode       = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-       .init           = initialize_usbh1_port,
-       .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init babbage_otg_mode(char *options)
-{
-       if (!strcmp(options, "host"))
-               otg_mode_host = 1;
-       else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
-       else
-               pr_info("otg_mode neither \"host\" nor \"device\". "
-                       "Defaulting to device\n");
-       return 0;
-}
-__setup("otg_mode=", babbage_otg_mode);
-
-static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
-       {
-               .modalias = "mtd_dataflash",
-               .max_speed_hz = 25000000,
-               .bus_num = 0,
-               .chip_select = 1,
-               .mode = SPI_MODE_0,
-               .platform_data = NULL,
-       },
-};
-
-static int mx51_babbage_spi_cs[] = {
-       BABBAGE_ECSPI1_CS0,
-       BABBAGE_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
-       .chipselect     = mx51_babbage_spi_cs,
-       .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-       .cd_type = ESDHC_CD_CONTROLLER,
-       .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
-       .cd_gpio = BABBAGE_SD2_CD,
-       .wp_gpio = BABBAGE_SD2_WP,
-       .cd_type = ESDHC_CD_GPIO,
-       .wp_type = ESDHC_WP_GPIO,
-};
-
-void __init imx51_babbage_common_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
-                                        ARRAY_SIZE(mx51babbage_pads));
-}
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_babbage_init(void)
-{
-       iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-       iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
-               PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
-
-       imx51_soc_init();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-       get_cpu_op = mx51_get_cpu_op;
-#endif
-       imx51_babbage_common_init();
-
-       imx51_add_imx_uart(0, &uart_pdata);
-       imx51_add_imx_uart(1, NULL);
-       imx51_add_imx_uart(2, &uart_pdata);
-
-       babbage_fec_reset();
-       imx51_add_fec(NULL);
-
-       /* Set the PAD settings for the pwr key. */
-       mxc_iomux_v3_setup_pad(power_key);
-       imx_add_gpio_keys(&imx_button_data);
-
-       imx51_add_imx_i2c(0, &babbage_i2c_data);
-       imx51_add_imx_i2c(1, &babbage_i2c_data);
-       imx51_add_hsi2c(&babbage_hsi2c_data);
-
-       if (otg_mode_host)
-               imx51_add_mxc_ehci_otg(&dr_utmi_config);
-       else {
-               initialize_otg_port(NULL);
-               imx51_add_fsl_usb2_udc(&usb_pdata);
-       }
-
-       gpio_usbh1_active();
-       imx51_add_mxc_ehci_hs(1, &usbh1_config);
-       /* setback USBH1_STP to be function */
-       mxc_iomux_v3_setup_pad(usbh1stp);
-       babbage_usbhub_reset();
-
-       imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
-       imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
-
-       spi_register_board_info(mx51_babbage_spi_board_info,
-               ARRAY_SIZE(mx51_babbage_spi_board_info));
-       imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
-       imx51_add_imx2_wdt(0, NULL);
-}
-
-static void __init mx51_babbage_timer_init(void)
-{
-       mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_babbage_timer = {
-       .init = mx51_babbage_timer_init,
-};
-
-MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
-       /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-       .atag_offset = 0x100,
-       .map_io = mx51_map_io,
-       .init_early = imx51_init_early,
-       .init_irq = mx51_init_irq,
-       .handle_irq = imx51_handle_irq,
-       .timer = &mx51_babbage_timer,
-       .init_machine = mx51_babbage_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
deleted file mode 100644 (file)
index 3a5ed2d..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2010 Linaro Limited
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKAMX_PCBID0         IMX_GPIO_NR(3, 16)
-#define EFIKAMX_PCBID1         IMX_GPIO_NR(3, 17)
-#define EFIKAMX_PCBID2         IMX_GPIO_NR(3, 11)
-
-#define EFIKAMX_BLUE_LED       IMX_GPIO_NR(3, 13)
-#define EFIKAMX_GREEN_LED      IMX_GPIO_NR(3, 14)
-#define EFIKAMX_RED_LED                IMX_GPIO_NR(3, 15)
-
-#define EFIKAMX_POWER_KEY      IMX_GPIO_NR(2, 31)
-
-/* board 1.1 doesn't have same reset gpio */
-#define EFIKAMX_RESET1_1       IMX_GPIO_NR(3, 2)
-#define EFIKAMX_RESET          IMX_GPIO_NR(1, 4)
-
-#define EFIKAMX_POWEROFF       IMX_GPIO_NR(4, 13)
-
-#define EFIKAMX_PMIC           IMX_GPIO_NR(1, 6)
-
-/* the pci ids pin have pull up. they're driven low according to board id */
-#define MX51_PAD_PCBID0        IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID1        IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID2        IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PWRKEY        IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-
-static iomux_v3_cfg_t mx51efikamx_pads[] = {
-       /* board id */
-       MX51_PAD_PCBID0,
-       MX51_PAD_PCBID1,
-       MX51_PAD_PCBID2,
-
-       /* leds */
-       MX51_PAD_CSI1_D9__GPIO3_13,
-       MX51_PAD_CSI1_VSYNC__GPIO3_14,
-       MX51_PAD_CSI1_HSYNC__GPIO3_15,
-
-       /* power key */
-       MX51_PAD_PWRKEY,
-
-       /* reset */
-       MX51_PAD_DI1_PIN13__GPIO3_2,
-       MX51_PAD_GPIO1_4__GPIO1_4,
-
-       /* power off */
-       MX51_PAD_CSI2_VSYNC__GPIO4_13,
-};
-
-/*   PCBID2  PCBID1 PCBID0  STATE
-       1       1      1    ER1:rev1.1
-       1       1      0    ER2:rev1.2
-       1       0      1    ER3:rev1.3
-       1       0      0    ER4:rev1.4
-*/
-static void __init mx51_efikamx_board_id(void)
-{
-       int id;
-
-       /* things are taking time to settle */
-       msleep(150);
-
-       gpio_request(EFIKAMX_PCBID0, "pcbid0");
-       gpio_direction_input(EFIKAMX_PCBID0);
-       gpio_request(EFIKAMX_PCBID1, "pcbid1");
-       gpio_direction_input(EFIKAMX_PCBID1);
-       gpio_request(EFIKAMX_PCBID2, "pcbid2");
-       gpio_direction_input(EFIKAMX_PCBID2);
-
-       id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
-       id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
-       id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
-
-       switch (id) {
-       case 7:
-               system_rev = 0x11;
-               break;
-       case 6:
-               system_rev = 0x12;
-               break;
-       case 5:
-               system_rev = 0x13;
-               break;
-       case 4:
-               system_rev = 0x14;
-               break;
-       default:
-               system_rev = 0x10;
-               break;
-       }
-
-       if ((system_rev == 0x10)
-               || (system_rev == 0x12)
-               || (system_rev == 0x14)) {
-               printk(KERN_WARNING
-                       "EfikaMX: Unsupported board revision 1.%u!\n",
-                       system_rev & 0xf);
-       }
-}
-
-static struct gpio_led mx51_efikamx_leds[] __initdata = {
-       {
-               .name = "efikamx:green",
-               .default_trigger = "default-on",
-               .gpio = EFIKAMX_GREEN_LED,
-       },
-       {
-               .name = "efikamx:red",
-               .default_trigger = "ide-disk",
-               .gpio = EFIKAMX_RED_LED,
-       },
-       {
-               .name = "efikamx:blue",
-               .default_trigger = "mmc0",
-               .gpio = EFIKAMX_BLUE_LED,
-       },
-};
-
-static const struct gpio_led_platform_data
-               mx51_efikamx_leds_data __initconst = {
-       .leds = mx51_efikamx_leds,
-       .num_leds = ARRAY_SIZE(mx51_efikamx_leds),
-};
-
-static struct esdhc_platform_data sd_pdata = {
-       .cd_type = ESDHC_CD_CONTROLLER,
-       .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct gpio_keys_button mx51_efikamx_powerkey[] = {
-       {
-               .code = KEY_POWER,
-               .gpio = EFIKAMX_POWER_KEY,
-               .type = EV_PWR,
-               .desc = "Power Button (CM)",
-               .wakeup = 1,
-               .debounce_interval = 10, /* ms */
-       },
-};
-
-static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
-       .buttons = mx51_efikamx_powerkey,
-       .nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
-};
-
-static void mx51_efikamx_restart(char mode, const char *cmd)
-{
-       if (system_rev == 0x11)
-               gpio_direction_output(EFIKAMX_RESET1_1, 0);
-       else
-               gpio_direction_output(EFIKAMX_RESET, 0);
-}
-
-static struct regulator *pwgt1, *pwgt2, *coincell;
-
-static void mx51_efikamx_power_off(void)
-{
-       if (!IS_ERR(coincell))
-               regulator_disable(coincell);
-
-       if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-               regulator_disable(pwgt2);
-               regulator_disable(pwgt1);
-       }
-       gpio_direction_output(EFIKAMX_POWEROFF, 1);
-}
-
-static int __init mx51_efikamx_power_init(void)
-{
-       if (machine_is_mx51_efikamx()) {
-               pwgt1 = regulator_get(NULL, "pwgt1");
-               pwgt2 = regulator_get(NULL, "pwgt2");
-               if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-                       regulator_enable(pwgt1);
-                       regulator_enable(pwgt2);
-               }
-               gpio_request(EFIKAMX_POWEROFF, "poweroff");
-               pm_power_off = mx51_efikamx_power_off;
-
-               /* enable coincell charger. maybe need a small power driver ? */
-               coincell = regulator_get(NULL, "coincell");
-               if (!IS_ERR(coincell)) {
-                       regulator_set_voltage(coincell, 3000000, 3000000);
-                       regulator_enable(coincell);
-               }
-
-               regulator_has_full_constraints();
-       }
-
-       return 0;
-}
-late_initcall(mx51_efikamx_power_init);
-
-static void __init mx51_efikamx_init(void)
-{
-       imx51_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
-                                       ARRAY_SIZE(mx51efikamx_pads));
-       efika_board_common_init();
-
-       mx51_efikamx_board_id();
-
-       /* on < 1.2 boards both SD controllers are used */
-       if (system_rev < 0x12) {
-               imx51_add_sdhci_esdhc_imx(0, NULL);
-               imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
-               mx51_efikamx_leds[2].default_trigger = "mmc1";
-       } else
-               imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
-
-       gpio_led_register_device(-1, &mx51_efikamx_leds_data);
-       imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
-
-       if (system_rev == 0x11) {
-               gpio_request(EFIKAMX_RESET1_1, "reset");
-               gpio_direction_output(EFIKAMX_RESET1_1, 1);
-       } else {
-               gpio_request(EFIKAMX_RESET, "reset");
-               gpio_direction_output(EFIKAMX_RESET, 1);
-       }
-
-       /*
-        * enable wifi by default only on mx
-        * sb and mx have same wlan pin but the value to enable it are
-        * different :/
-        */
-       gpio_request(EFIKA_WLAN_EN, "wlan_en");
-       gpio_direction_output(EFIKA_WLAN_EN, 0);
-       msleep(10);
-
-       gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
-       gpio_direction_output(EFIKA_WLAN_RESET, 0);
-       msleep(10);
-       gpio_set_value(EFIKA_WLAN_RESET, 1);
-}
-
-static void __init mx51_efikamx_timer_init(void)
-{
-       mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikamx_timer = {
-       .init = mx51_efikamx_timer_init,
-};
-
-MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
-       /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
-       .atag_offset = 0x100,
-       .map_io = mx51_map_io,
-       .init_early = imx51_init_early,
-       .init_irq = mx51_init_irq,
-       .handle_irq = imx51_handle_irq,
-       .timer = &mx51_efikamx_timer,
-       .init_machine = mx51_efikamx_init,
-       .restart = mx51_efikamx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
deleted file mode 100644 (file)
index ea5f65b..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKASB_USBH2_STP      IMX_GPIO_NR(2, 20)
-#define EFIKASB_GREEN_LED      IMX_GPIO_NR(1, 3)
-#define EFIKASB_WHITE_LED      IMX_GPIO_NR(2, 25)
-#define EFIKASB_PCBID0         IMX_GPIO_NR(2, 28)
-#define EFIKASB_PCBID1         IMX_GPIO_NR(2, 29)
-#define EFIKASB_PWRKEY         IMX_GPIO_NR(2, 31)
-#define EFIKASB_LID            IMX_GPIO_NR(3, 14)
-#define EFIKASB_POWEROFF       IMX_GPIO_NR(4, 13)
-#define EFIKASB_RFKILL         IMX_GPIO_NR(3, 1)
-
-#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-#define MX51_PAD_SD1_CD        IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-
-static iomux_v3_cfg_t mx51efikasb_pads[] = {
-       /* USB HOST2 */
-       MX51_PAD_EIM_D16__USBH2_DATA0,
-       MX51_PAD_EIM_D17__USBH2_DATA1,
-       MX51_PAD_EIM_D18__USBH2_DATA2,
-       MX51_PAD_EIM_D19__USBH2_DATA3,
-       MX51_PAD_EIM_D20__USBH2_DATA4,
-       MX51_PAD_EIM_D21__USBH2_DATA5,
-       MX51_PAD_EIM_D22__USBH2_DATA6,
-       MX51_PAD_EIM_D23__USBH2_DATA7,
-       MX51_PAD_EIM_A24__USBH2_CLK,
-       MX51_PAD_EIM_A25__USBH2_DIR,
-       MX51_PAD_EIM_A26__USBH2_STP,
-       MX51_PAD_EIM_A27__USBH2_NXT,
-
-       /* leds */
-       MX51_PAD_EIM_CS0__GPIO2_25,
-       MX51_PAD_GPIO1_3__GPIO1_3,
-
-       /* pcb id */
-       MX51_PAD_EIM_CS3__GPIO2_28,
-       MX51_PAD_EIM_CS4__GPIO2_29,
-
-       /* lid */
-       MX51_PAD_CSI1_VSYNC__GPIO3_14,
-
-       /* power key*/
-       MX51_PAD_PWRKEY,
-
-       /* wifi/bt button */
-       MX51_PAD_DI1_PIN12__GPIO3_1,
-
-       /* power off */
-       MX51_PAD_CSI2_VSYNC__GPIO4_13,
-
-       /* wdog reset */
-       MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
-
-       /* BT */
-       MX51_PAD_EIM_A17__GPIO2_11,
-
-       MX51_PAD_SD1_CD,
-};
-
-static int initialize_usbh2_port(struct platform_device *pdev)
-{
-       iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
-       iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
-
-       mxc_iomux_v3_setup_pad(usbh2gpio);
-       gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
-       gpio_direction_output(EFIKASB_USBH2_STP, 0);
-       msleep(1);
-       gpio_set_value(EFIKASB_USBH2_STP, 1);
-       msleep(1);
-
-       gpio_free(EFIKASB_USBH2_STP);
-       mxc_iomux_v3_setup_pad(usbh2stp);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh2_config __initdata = {
-       .init   = initialize_usbh2_port,
-       .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void __init mx51_efikasb_usb(void)
-{
-       usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
-                       ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-       if (usbh2_config.otg)
-               imx51_add_mxc_ehci_hs(2, &usbh2_config);
-}
-
-static const struct gpio_led mx51_efikasb_leds[] __initconst = {
-       {
-               .name = "efikasb:green",
-               .default_trigger = "default-on",
-               .gpio = EFIKASB_GREEN_LED,
-               .active_low = 1,
-       },
-       {
-               .name = "efikasb:white",
-               .default_trigger = "caps",
-               .gpio = EFIKASB_WHITE_LED,
-       },
-};
-
-static const struct gpio_led_platform_data
-               mx51_efikasb_leds_data __initconst = {
-       .leds = mx51_efikasb_leds,
-       .num_leds = ARRAY_SIZE(mx51_efikasb_leds),
-};
-
-static struct gpio_keys_button mx51_efikasb_keys[] = {
-       {
-               .code = KEY_POWER,
-               .gpio = EFIKASB_PWRKEY,
-               .type = EV_KEY,
-               .desc = "Power Button",
-               .wakeup = 1,
-               .active_low = 1,
-       },
-       {
-               .code = SW_LID,
-               .gpio = EFIKASB_LID,
-               .type = EV_SW,
-               .desc = "Lid Switch",
-               .active_low = 1,
-       },
-       {
-               .code = KEY_RFKILL,
-               .gpio = EFIKASB_RFKILL,
-               .type = EV_KEY,
-               .desc = "rfkill",
-               .active_low = 1,
-       },
-};
-
-static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
-       .buttons = mx51_efikasb_keys,
-       .nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
-};
-
-static struct esdhc_platform_data sd0_pdata = {
-#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27)
-       .cd_gpio = EFIKASB_SD1_CD,
-       .cd_type = ESDHC_CD_GPIO,
-       .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct esdhc_platform_data sd1_pdata = {
-       .cd_type = ESDHC_CD_CONTROLLER,
-       .wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct regulator *pwgt1, *pwgt2;
-
-static void mx51_efikasb_power_off(void)
-{
-       gpio_set_value(EFIKA_USB_PHY_RESET, 0);
-
-       if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-               regulator_disable(pwgt2);
-               regulator_disable(pwgt1);
-       }
-       gpio_direction_output(EFIKASB_POWEROFF, 1);
-}
-
-static int __init mx51_efikasb_power_init(void)
-{
-       if (machine_is_mx51_efikasb()) {
-               pwgt1 = regulator_get(NULL, "pwgt1");
-               pwgt2 = regulator_get(NULL, "pwgt2");
-               if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-                       regulator_enable(pwgt1);
-                       regulator_enable(pwgt2);
-               }
-               gpio_request(EFIKASB_POWEROFF, "poweroff");
-               pm_power_off = mx51_efikasb_power_off;
-
-               regulator_has_full_constraints();
-       }
-
-       return 0;
-}
-late_initcall(mx51_efikasb_power_init);
-
-/* 01     R1.3 board
-   10     R2.0 board */
-static void __init mx51_efikasb_board_id(void)
-{
-       int id;
-
-       gpio_request(EFIKASB_PCBID0, "pcb id0");
-       gpio_direction_input(EFIKASB_PCBID0);
-       gpio_request(EFIKASB_PCBID1, "pcb id1");
-       gpio_direction_input(EFIKASB_PCBID1);
-
-       id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
-       id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
-
-       switch (id) {
-       default:
-               break;
-       case 1:
-               system_rev = 0x13;
-               break;
-       case 2:
-               system_rev = 0x20;
-               break;
-       }
-}
-
-static void __init efikasb_board_init(void)
-{
-       imx51_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
-                                       ARRAY_SIZE(mx51efikasb_pads));
-       efika_board_common_init();
-
-       mx51_efikasb_board_id();
-       mx51_efikasb_usb();
-       imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
-       imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
-
-       gpio_led_register_device(-1, &mx51_efikasb_leds_data);
-       imx_add_gpio_keys(&mx51_efikasb_keys_data);
-}
-
-static void __init mx51_efikasb_timer_init(void)
-{
-       mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikasb_timer = {
-       .init   = mx51_efikasb_timer_init,
-};
-
-MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
-       .atag_offset = 0x100,
-       .map_io = mx51_map_io,
-       .init_early = imx51_init_early,
-       .init_irq = mx51_init_irq,
-       .handle_irq = imx51_handle_irq,
-       .init_machine =  efikasb_board_init,
-       .timer = &mx51_efikasb_timer,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
deleted file mode 100644 (file)
index 5f224f1..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 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 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/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define ARD_ETHERNET_INT_B     IMX_GPIO_NR(2, 31)
-#define ARD_SD1_CD             IMX_GPIO_NR(1, 1)
-#define ARD_SD1_WP             IMX_GPIO_NR(1, 9)
-#define ARD_I2CPORTEXP_B       IMX_GPIO_NR(2, 3)
-#define ARD_VOLUMEDOWN         IMX_GPIO_NR(4, 0)
-#define ARD_HOME                       IMX_GPIO_NR(5, 10)
-#define ARD_BACK                       IMX_GPIO_NR(5, 11)
-#define ARD_PROG                       IMX_GPIO_NR(5, 12)
-#define ARD_VOLUMEUP           IMX_GPIO_NR(5, 13)
-
-static iomux_v3_cfg_t mx53_ard_pads[] = {
-       /* UART1 */
-       MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
-       MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
-       /* WEIM for CS1 */
-       MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
-       MX53_PAD_EIM_D16__EMI_WEIM_D_16,
-       MX53_PAD_EIM_D17__EMI_WEIM_D_17,
-       MX53_PAD_EIM_D18__EMI_WEIM_D_18,
-       MX53_PAD_EIM_D19__EMI_WEIM_D_19,
-       MX53_PAD_EIM_D20__EMI_WEIM_D_20,
-       MX53_PAD_EIM_D21__EMI_WEIM_D_21,
-       MX53_PAD_EIM_D22__EMI_WEIM_D_22,
-       MX53_PAD_EIM_D23__EMI_WEIM_D_23,
-       MX53_PAD_EIM_D24__EMI_WEIM_D_24,
-       MX53_PAD_EIM_D25__EMI_WEIM_D_25,
-       MX53_PAD_EIM_D26__EMI_WEIM_D_26,
-       MX53_PAD_EIM_D27__EMI_WEIM_D_27,
-       MX53_PAD_EIM_D28__EMI_WEIM_D_28,
-       MX53_PAD_EIM_D29__EMI_WEIM_D_29,
-       MX53_PAD_EIM_D30__EMI_WEIM_D_30,
-       MX53_PAD_EIM_D31__EMI_WEIM_D_31,
-       MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
-       MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
-       MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
-       MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
-       MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
-       MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
-       MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
-       MX53_PAD_EIM_OE__EMI_WEIM_OE,
-       MX53_PAD_EIM_RW__EMI_WEIM_RW,
-       MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
-       /* SDHC1 */
-       MX53_PAD_SD1_CMD__ESDHC1_CMD,
-       MX53_PAD_SD1_CLK__ESDHC1_CLK,
-       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-       MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
-       MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
-       MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
-       MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
-       MX53_PAD_GPIO_1__GPIO1_1,
-       MX53_PAD_GPIO_9__GPIO1_9,
-       /* I2C2 */
-       MX53_PAD_EIM_EB2__I2C2_SCL,
-       MX53_PAD_KEY_ROW3__I2C2_SDA,
-       /* I2C3 */
-       MX53_PAD_GPIO_3__I2C3_SCL,
-       MX53_PAD_GPIO_16__I2C3_SDA,
-       /* GPIO */
-       MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */
-       MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */
-       MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */
-       MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */
-       MX53_PAD_GPIO_10__GPIO4_0,              /* vol down */
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)   \
-{                                                      \
-       .gpio           = gpio_num,                             \
-       .type           = EV_KEY,                               \
-       .code           = ev_code,                              \
-       .active_low     = act_low,                              \
-       .desc           = "btn " descr,                 \
-       .wakeup         = wake,                                 \
-}
-
-static struct gpio_keys_button ard_buttons[] = {
-       GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
-       GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
-       GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
-       GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
-       GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data ard_button_data __initconst = {
-       .buttons        = ard_buttons,
-       .nbuttons       = ARRAY_SIZE(ard_buttons),
-};
-
-static struct resource ard_smsc911x_resources[] = {
-       {
-               .start = MX53_CS1_64MB_BASE_ADDR,
-               .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
-               .end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct smsc911x_platform_config ard_smsc911x_config = {
-       .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-       .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
-       .flags = SMSC911X_USE_32BIT,
-};
-
-static struct platform_device ard_smsc_lan9220_device = {
-       .name = "smsc911x",
-       .id = -1,
-       .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
-       .resource = ard_smsc911x_resources,
-       .dev = {
-               .platform_data = &ard_smsc911x_config,
-       },
-};
-
-static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
-       .cd_gpio = ARD_SD1_CD,
-       .wp_gpio = ARD_SD1_WP,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c2_data = {
-       .bitrate = 50000,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c3_data = {
-       .bitrate = 400000,
-};
-
-static void __init mx53_ard_io_init(void)
-{
-       gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
-       gpio_direction_input(ARD_ETHERNET_INT_B);
-
-       gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
-       gpio_direction_output(ARD_I2CPORTEXP_B, 1);
-}
-
-/* Config CS1 settings for ethernet controller */
-static int weim_cs_config(void)
-{
-       u32 reg;
-       void __iomem *weim_base, *iomuxc_base;
-
-       weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
-       if (!weim_base)
-               return -ENOMEM;
-
-       iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
-       if (!iomuxc_base)
-               return -ENOMEM;
-
-       /* CS1 timings for LAN9220 */
-       writel(0x20001, (weim_base + 0x18));
-       writel(0x0, (weim_base + 0x1C));
-       writel(0x16000202, (weim_base + 0x20));
-       writel(0x00000002, (weim_base + 0x24));
-       writel(0x16002082, (weim_base + 0x28));
-       writel(0x00000000, (weim_base + 0x2C));
-       writel(0x00000000, (weim_base + 0x90));
-
-       /* specify 64 MB on CS1 and CS0 on GPR1 */
-       reg = readl(iomuxc_base + 0x4);
-       reg &= ~0x3F;
-       reg |= 0x1B;
-       writel(reg, (iomuxc_base + 0x4));
-
-       iounmap(iomuxc_base);
-       iounmap(weim_base);
-
-       return 0;
-}
-
-void __init imx53_ard_common_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
-                                        ARRAY_SIZE(mx53_ard_pads));
-       weim_cs_config();
-}
-
-static struct platform_device *devices[] __initdata = {
-       &ard_smsc_lan9220_device,
-};
-
-static void __init mx53_ard_board_init(void)
-{
-       imx53_soc_init();
-       imx53_add_imx_uart(0, NULL);
-
-       imx53_ard_common_init();
-       mx53_ard_io_init();
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-
-       imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
-       imx53_add_imx2_wdt(0, NULL);
-       imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
-       imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
-       imx_add_gpio_keys(&ard_button_data);
-       imx53_add_ahci_imx();
-}
-
-static void __init mx53_ard_timer_init(void)
-{
-       mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_ard_timer = {
-       .init   = mx53_ard_timer_init,
-};
-
-MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
-       .map_io = mx53_map_io,
-       .init_early = imx53_init_early,
-       .init_irq = mx53_init_irq,
-       .handle_irq = imx53_handle_irq,
-       .timer = &mx53_ard_timer,
-       .init_machine = mx53_ard_board_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
deleted file mode 100644 (file)
index d6ce137..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/iomux-mx53.h>
-
-#define MX53_EVK_FEC_PHY_RST   IMX_GPIO_NR(7, 6)
-#define EVK_ECSPI1_CS0         IMX_GPIO_NR(2, 30)
-#define EVK_ECSPI1_CS1         IMX_GPIO_NR(3, 19)
-#define MX53EVK_LED            IMX_GPIO_NR(7, 7)
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-static iomux_v3_cfg_t mx53_evk_pads[] = {
-       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
-       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
-       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-       MX53_PAD_PATA_DIOR__UART2_RTS,
-       MX53_PAD_PATA_INTRQ__UART2_CTS,
-
-       MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
-       MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-
-       MX53_PAD_EIM_D16__ECSPI1_SCLK,
-       MX53_PAD_EIM_D17__ECSPI1_MISO,
-       MX53_PAD_EIM_D18__ECSPI1_MOSI,
-
-       /* ecspi chip select lines */
-       MX53_PAD_EIM_EB2__GPIO2_30,
-       MX53_PAD_EIM_D19__GPIO3_19,
-       /* LED */
-       MX53_PAD_PATA_DA_1__GPIO7_7,
-};
-
-static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct gpio_led mx53evk_leds[] __initconst = {
-       {
-               .name                   = "green",
-               .default_trigger        = "heartbeat",
-               .gpio                   = MX53EVK_LED,
-       },
-};
-
-static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
-       .leds           = mx53evk_leds,
-       .num_leds       = ARRAY_SIZE(mx53evk_leds),
-};
-
-static inline void mx53_evk_init_uart(void)
-{
-       imx53_add_imx_uart(0, NULL);
-       imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
-       imx53_add_imx_uart(2, NULL);
-}
-
-static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
-       .bitrate = 100000,
-};
-
-static inline void mx53_evk_fec_reset(void)
-{
-       int ret;
-
-       /* reset FEC PHY */
-       ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
-                                                       "fec-phy-reset");
-       if (ret) {
-               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-               return;
-       }
-       msleep(1);
-       gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
-       .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
-       {
-               .modalias = "mtd_dataflash",
-               .max_speed_hz = 25000000,
-               .bus_num = 0,
-               .chip_select = 1,
-               .mode = SPI_MODE_0,
-               .platform_data = NULL,
-       },
-};
-
-static int mx53_evk_spi_cs[] = {
-       EVK_ECSPI1_CS0,
-       EVK_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx53_evk_spi_data __initconst = {
-       .chipselect     = mx53_evk_spi_cs,
-       .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
-};
-
-void __init imx53_evk_common_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
-                                        ARRAY_SIZE(mx53_evk_pads));
-}
-
-static void __init mx53_evk_board_init(void)
-{
-       imx53_soc_init();
-       imx53_evk_common_init();
-
-       mx53_evk_init_uart();
-       mx53_evk_fec_reset();
-       imx53_add_fec(&mx53_evk_fec_pdata);
-
-       imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
-       imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
-
-       imx53_add_sdhci_esdhc_imx(0, NULL);
-       imx53_add_sdhci_esdhc_imx(1, NULL);
-
-       spi_register_board_info(mx53_evk_spi_board_info,
-               ARRAY_SIZE(mx53_evk_spi_board_info));
-       imx53_add_ecspi(0, &mx53_evk_spi_data);
-       imx53_add_imx2_wdt(0, NULL);
-       gpio_led_register_device(-1, &mx53evk_leds_data);
-}
-
-static void __init mx53_evk_timer_init(void)
-{
-       mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_evk_timer = {
-       .init   = mx53_evk_timer_init,
-};
-
-MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
-       .map_io = mx53_map_io,
-       .init_early = imx53_init_early,
-       .init_irq = mx53_init_irq,
-       .handle_irq = imx53_handle_irq,
-       .timer = &mx53_evk_timer,
-       .init_machine = mx53_evk_board_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
deleted file mode 100644 (file)
index fd8b524..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 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 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/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define MX53_LOCO_POWER                        IMX_GPIO_NR(1, 8)
-#define MX53_LOCO_UI1                  IMX_GPIO_NR(2, 14)
-#define MX53_LOCO_UI2                  IMX_GPIO_NR(2, 15)
-#define LOCO_FEC_PHY_RST               IMX_GPIO_NR(7, 6)
-#define LOCO_LED                       IMX_GPIO_NR(7, 7)
-#define LOCO_SD3_CD                    IMX_GPIO_NR(3, 11)
-#define LOCO_SD3_WP                    IMX_GPIO_NR(3, 12)
-#define LOCO_SD1_CD                    IMX_GPIO_NR(3, 13)
-#define LOCO_ACCEL_EN                  IMX_GPIO_NR(6, 14)
-
-static iomux_v3_cfg_t mx53_loco_pads[] = {
-       /* FEC */
-       MX53_PAD_FEC_MDC__FEC_MDC,
-       MX53_PAD_FEC_MDIO__FEC_MDIO,
-       MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
-       MX53_PAD_FEC_RX_ER__FEC_RX_ER,
-       MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
-       MX53_PAD_FEC_RXD1__FEC_RDATA_1,
-       MX53_PAD_FEC_RXD0__FEC_RDATA_0,
-       MX53_PAD_FEC_TX_EN__FEC_TX_EN,
-       MX53_PAD_FEC_TXD1__FEC_TDATA_1,
-       MX53_PAD_FEC_TXD0__FEC_TDATA_0,
-       /* FEC_nRST */
-       MX53_PAD_PATA_DA_0__GPIO7_6,
-       /* FEC_nINT */
-       MX53_PAD_PATA_DATA4__GPIO2_4,
-       /* AUDMUX5 */
-       MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
-       MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
-       MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
-       MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
-       /* I2C1 */
-       MX53_PAD_CSI0_DAT8__I2C1_SDA,
-       MX53_PAD_CSI0_DAT9__I2C1_SCL,
-       MX53_PAD_NANDF_CS1__GPIO6_14,   /* Accelerometer Enable */
-       /* I2C2 */
-       MX53_PAD_KEY_COL3__I2C2_SCL,
-       MX53_PAD_KEY_ROW3__I2C2_SDA,
-       /* SD1 */
-       MX53_PAD_SD1_CMD__ESDHC1_CMD,
-       MX53_PAD_SD1_CLK__ESDHC1_CLK,
-       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-       /* SD1_CD */
-       MX53_PAD_EIM_DA13__GPIO3_13,
-       /* SD3 */
-       MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
-       MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
-       MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
-       MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
-       MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
-       MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
-       MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
-       MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
-       MX53_PAD_PATA_IORDY__ESDHC3_CLK,
-       MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-       /* SD3_CD */
-       MX53_PAD_EIM_DA11__GPIO3_11,
-       /* SD3_WP */
-       MX53_PAD_EIM_DA12__GPIO3_12,
-       /* VGA */
-       MX53_PAD_EIM_OE__IPU_DI1_PIN7,
-       MX53_PAD_EIM_RW__IPU_DI1_PIN8,
-       /* DISPLB */
-       MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
-       MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
-       MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
-       MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
-       /* DISP0_POWER_EN */
-       MX53_PAD_EIM_D24__GPIO3_24,
-       /* DISP0 DET INT */
-       MX53_PAD_EIM_D31__GPIO3_31,
-       /* LVDS */
-       MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
-       MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
-       MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
-       MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
-       MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
-       MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
-       MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
-       MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
-       MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
-       MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
-       /* I2C1 */
-       MX53_PAD_CSI0_DAT8__I2C1_SDA,
-       MX53_PAD_CSI0_DAT9__I2C1_SCL,
-       /* UART1 */
-       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-       /* CSI0 */
-       MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
-       MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
-       MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
-       MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
-       MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
-       MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
-       MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
-       MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
-       MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
-       MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
-       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
-       /* DISPLAY */
-       MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
-       MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
-       MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
-       MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
-       MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
-       MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
-       MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
-       MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
-       MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
-       MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
-       MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
-       MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
-       MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
-       MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
-       MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
-       MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
-       MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
-       MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
-       MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
-       MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
-       MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
-       MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
-       MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
-       MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
-       MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
-       MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
-       MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
-       MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
-       /* Audio CLK*/
-       MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
-       /* PWM */
-       MX53_PAD_GPIO_1__PWM2_PWMO,
-       /* SPDIF */
-       MX53_PAD_GPIO_7__SPDIF_PLOCK,
-       MX53_PAD_GPIO_17__SPDIF_OUT1,
-       /* GPIO */
-       MX53_PAD_PATA_DA_1__GPIO7_7,            /* LED */
-       MX53_PAD_PATA_DA_2__GPIO7_8,
-       MX53_PAD_PATA_DATA5__GPIO2_5,
-       MX53_PAD_PATA_DATA6__GPIO2_6,
-       MX53_PAD_PATA_DATA14__GPIO2_14,
-       MX53_PAD_PATA_DATA15__GPIO2_15,
-       MX53_PAD_PATA_INTRQ__GPIO7_2,
-       MX53_PAD_EIM_WAIT__GPIO5_0,
-       MX53_PAD_NANDF_WP_B__GPIO6_9,
-       MX53_PAD_NANDF_RB0__GPIO6_10,
-       MX53_PAD_NANDF_CS1__GPIO6_14,
-       MX53_PAD_NANDF_CS2__GPIO6_15,
-       MX53_PAD_NANDF_CS3__GPIO6_16,
-       MX53_PAD_GPIO_5__GPIO1_5,
-       MX53_PAD_GPIO_16__GPIO7_11,
-       MX53_PAD_GPIO_8__GPIO1_8,
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)   \
-{                                                              \
-       .gpio           = gpio_num,                             \
-       .type           = EV_KEY,                               \
-       .code           = ev_code,                              \
-       .active_low     = act_low,                              \
-       .desc           = "btn " descr,                         \
-       .wakeup         = wake,                                 \
-}
-
-static struct gpio_keys_button loco_buttons[] = {
-       GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
-       GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
-       GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data loco_button_data __initconst = {
-       .buttons        = loco_buttons,
-       .nbuttons       = ARRAY_SIZE(loco_buttons),
-};
-
-static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
-       .cd_gpio = LOCO_SD1_CD,
-       .cd_type = ESDHC_CD_GPIO,
-       .wp_type = ESDHC_WP_NONE,
-};
-
-static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
-       .cd_gpio = LOCO_SD3_CD,
-       .wp_gpio = LOCO_SD3_WP,
-       .cd_type = ESDHC_CD_GPIO,
-       .wp_type = ESDHC_WP_GPIO,
-};
-
-static inline void mx53_loco_fec_reset(void)
-{
-       int ret;
-
-       /* reset FEC PHY */
-       ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
-       if (ret) {
-               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-               return;
-       }
-       gpio_direction_output(LOCO_FEC_PHY_RST, 0);
-       msleep(1);
-       gpio_set_value(LOCO_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_loco_fec_data __initconst = {
-       .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
-       .bitrate = 100000,
-};
-
-static const struct gpio_led mx53loco_leds[] __initconst = {
-       {
-               .name                   = "green",
-               .default_trigger        = "heartbeat",
-               .gpio                   = LOCO_LED,
-       },
-};
-
-static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
-       .leds           = mx53loco_leds,
-       .num_leds       = ARRAY_SIZE(mx53loco_leds),
-};
-
-void __init imx53_qsb_common_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
-                                        ARRAY_SIZE(mx53_loco_pads));
-}
-
-static struct i2c_board_info mx53loco_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("mma8450", 0x1C),
-       },
-};
-
-static void __init mx53_loco_board_init(void)
-{
-       int ret;
-       imx53_soc_init();
-       imx53_qsb_common_init();
-
-       imx53_add_imx_uart(0, NULL);
-       mx53_loco_fec_reset();
-       imx53_add_fec(&mx53_loco_fec_data);
-       imx53_add_imx2_wdt(0, NULL);
-
-       ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
-       if (ret)
-               pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
-
-       i2c_register_board_info(0, mx53loco_i2c_devices,
-                               ARRAY_SIZE(mx53loco_i2c_devices));
-       imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
-       imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
-       imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
-       imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
-       imx_add_gpio_keys(&loco_button_data);
-       gpio_led_register_device(-1, &mx53loco_leds_data);
-       imx53_add_ahci_imx();
-}
-
-static void __init mx53_loco_timer_init(void)
-{
-       mx53_clocks_init(32768, 24000000, 0, 0);
-}
-
-static struct sys_timer mx53_loco_timer = {
-       .init   = mx53_loco_timer_init,
-};
-
-MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
-       .map_io = mx53_map_io,
-       .init_early = imx53_init_early,
-       .init_irq = mx53_init_irq,
-       .handle_irq = imx53_handle_irq,
-       .timer = &mx53_loco_timer,
-       .init_machine = mx53_loco_board_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
deleted file mode 100644 (file)
index 22c53c9..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 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 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/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define SMD_FEC_PHY_RST                IMX_GPIO_NR(7, 6)
-#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
-
-static iomux_v3_cfg_t mx53_smd_pads[] = {
-       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
-       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
-       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-
-       MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
-       MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-       MX53_PAD_PATA_DA_1__UART3_CTS,
-       MX53_PAD_PATA_DA_2__UART3_RTS,
-       /* I2C1 */
-       MX53_PAD_CSI0_DAT8__I2C1_SDA,
-       MX53_PAD_CSI0_DAT9__I2C1_SCL,
-       /* SD1 */
-       MX53_PAD_SD1_CMD__ESDHC1_CMD,
-       MX53_PAD_SD1_CLK__ESDHC1_CLK,
-       MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-       MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-       MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-       MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-       /* SD2 */
-       MX53_PAD_SD2_CMD__ESDHC2_CMD,
-       MX53_PAD_SD2_CLK__ESDHC2_CLK,
-       MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
-       MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
-       MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
-       MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
-       /* SD3 */
-       MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
-       MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
-       MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
-       MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
-       MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
-       MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
-       MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
-       MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
-       MX53_PAD_PATA_IORDY__ESDHC3_CLK,
-       MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-};
-
-static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mx53_smd_init_uart(void)
-{
-       imx53_add_imx_uart(0, NULL);
-       imx53_add_imx_uart(1, NULL);
-       imx53_add_imx_uart(2, &mx53_smd_uart_data);
-}
-
-static inline void mx53_smd_fec_reset(void)
-{
-       int ret;
-
-       /* reset FEC PHY */
-       ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
-       if (ret) {
-               printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-               return;
-       }
-       gpio_direction_output(SMD_FEC_PHY_RST, 0);
-       msleep(1);
-       gpio_set_value(SMD_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_smd_fec_data __initconst = {
-       .phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
-       .bitrate = 100000,
-};
-
-static inline void mx53_smd_ahci_pwr_on(void)
-{
-       int ret;
-
-       /* Enable SATA PWR */
-       ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
-                       GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
-       if (ret) {
-               pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
-               return;
-       }
-}
-
-void __init imx53_smd_common_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
-                                        ARRAY_SIZE(mx53_smd_pads));
-}
-
-static void __init mx53_smd_board_init(void)
-{
-       imx53_soc_init();
-       imx53_smd_common_init();
-
-       mx53_smd_init_uart();
-       mx53_smd_fec_reset();
-       imx53_add_fec(&mx53_smd_fec_data);
-       imx53_add_imx2_wdt(0, NULL);
-       imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
-       imx53_add_sdhci_esdhc_imx(0, NULL);
-       imx53_add_sdhci_esdhc_imx(1, NULL);
-       imx53_add_sdhci_esdhc_imx(2, NULL);
-       mx53_smd_ahci_pwr_on();
-       imx53_add_ahci_imx();
-}
-
-static void __init mx53_smd_timer_init(void)
-{
-       mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_smd_timer = {
-       .init   = mx53_smd_timer_init,
-};
-
-MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
-       .map_io = mx53_map_io,
-       .init_early = imx53_init_early,
-       .init_irq = mx53_init_irq,
-       .handle_irq = imx53_handle_irq,
-       .timer = &mx53_smd_timer,
-       .init_machine = mx53_smd_board_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
deleted file mode 100644 (file)
index 4cb2769..0000000
+++ /dev/null
@@ -1,1675 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/of.h>
-
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/clock.h>
-
-#include "crm_regs.h"
-
-/* External clock values passed-in by the board code */
-static unsigned long external_high_reference, external_low_reference;
-static unsigned long oscillator_reference, ckih2_reference;
-
-static struct clk osc_clk;
-static struct clk pll1_main_clk;
-static struct clk pll1_sw_clk;
-static struct clk pll2_sw_clk;
-static struct clk pll3_sw_clk;
-static struct clk mx53_pll4_sw_clk;
-static struct clk lp_apm_clk;
-static struct clk periph_apm_clk;
-static struct clk ahb_clk;
-static struct clk ipg_clk;
-static struct clk usboh3_clk;
-static struct clk emi_fast_clk;
-static struct clk ipu_clk;
-static struct clk mipi_hsc1_clk;
-static struct clk esdhc1_clk;
-static struct clk esdhc2_clk;
-static struct clk esdhc3_mx53_clk;
-
-#define MAX_DPLL_WAIT_TRIES    1000 /* 1000 * udelay(1) = 1ms */
-
-/* calculate best pre and post dividers to get the required divider */
-static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
-       u32 max_pre, u32 max_post)
-{
-       if (div >= max_pre * max_post) {
-               *pre = max_pre;
-               *post = max_post;
-       } else if (div >= max_pre) {
-               u32 min_pre, temp_pre, old_err, err;
-               min_pre = DIV_ROUND_UP(div, max_post);
-               old_err = max_pre;
-               for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
-                       err = div % temp_pre;
-                       if (err == 0) {
-                               *pre = temp_pre;
-                               break;
-                       }
-                       err = temp_pre - err;
-                       if (err < old_err) {
-                               old_err = err;
-                               *pre = temp_pre;
-                       }
-               }
-               *post = DIV_ROUND_UP(div, *pre);
-       } else {
-               *pre = div;
-               *post = 1;
-       }
-}
-
-static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
-{
-       u32 reg = __raw_readl(clk->enable_reg);
-
-       reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-       reg |= mode << clk->enable_shift;
-
-       __raw_writel(reg, clk->enable_reg);
-}
-
-static int _clk_ccgr_enable(struct clk *clk)
-{
-       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
-       return 0;
-}
-
-static void _clk_ccgr_disable(struct clk *clk)
-{
-       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
-}
-
-static int _clk_ccgr_enable_inrun(struct clk *clk)
-{
-       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-       return 0;
-}
-
-static void _clk_ccgr_disable_inwait(struct clk *clk)
-{
-       _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-}
-
-/*
- * For the 4-to-1 muxed input clock
- */
-static inline u32 _get_mux(struct clk *parent, struct clk *m0,
-                          struct clk *m1, struct clk *m2, struct clk *m3)
-{
-       if (parent == m0)
-               return 0;
-       else if (parent == m1)
-               return 1;
-       else if (parent == m2)
-               return 2;
-       else if (parent == m3)
-               return 3;
-       else
-               BUG();
-
-       return -EINVAL;
-}
-
-static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
-{
-       if (pll == &pll1_main_clk)
-               return MX51_DPLL1_BASE;
-       else if (pll == &pll2_sw_clk)
-               return MX51_DPLL2_BASE;
-       else if (pll == &pll3_sw_clk)
-               return MX51_DPLL3_BASE;
-       else
-               BUG();
-
-       return NULL;
-}
-
-static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
-{
-       if (pll == &pll1_main_clk)
-               return MX53_DPLL1_BASE;
-       else if (pll == &pll2_sw_clk)
-               return MX53_DPLL2_BASE;
-       else if (pll == &pll3_sw_clk)
-               return MX53_DPLL3_BASE;
-       else if (pll == &mx53_pll4_sw_clk)
-               return MX53_DPLL4_BASE;
-       else
-               BUG();
-
-       return NULL;
-}
-
-static inline void __iomem *_get_pll_base(struct clk *pll)
-{
-       if (cpu_is_mx51())
-               return _mx51_get_pll_base(pll);
-       else
-               return _mx53_get_pll_base(pll);
-}
-
-static unsigned long clk_pll_get_rate(struct clk *clk)
-{
-       long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
-       unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
-       void __iomem *pllbase;
-       s64 temp;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       pllbase = _get_pll_base(clk);
-
-       dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-       pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-       dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
-
-       if (pll_hfsm == 0) {
-               dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
-               dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
-               dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
-       } else {
-               dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
-               dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
-               dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
-       }
-       pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
-       mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
-       mfi = (mfi <= 5) ? 5 : mfi;
-       mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
-       mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
-       /* Sign extend to 32-bits */
-       if (mfn >= 0x04000000) {
-               mfn |= 0xFC000000;
-               mfn_abs = -mfn;
-       }
-
-       ref_clk = 2 * parent_rate;
-       if (dbl != 0)
-               ref_clk *= 2;
-
-       ref_clk /= (pdf + 1);
-       temp = (u64) ref_clk * mfn_abs;
-       do_div(temp, mfd + 1);
-       if (mfn < 0)
-               temp = -temp;
-       temp = (ref_clk * mfi) + temp;
-
-       return temp;
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
-       u32 reg;
-       void __iomem *pllbase;
-
-       long mfi, pdf, mfn, mfd = 999999;
-       s64 temp64;
-       unsigned long quad_parent_rate;
-       unsigned long pll_hfsm, dp_ctl;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       pllbase = _get_pll_base(clk);
-
-       quad_parent_rate = 4 * parent_rate;
-       pdf = mfi = -1;
-       while (++pdf < 16 && mfi < 5)
-               mfi = rate * (pdf+1) / quad_parent_rate;
-       if (mfi > 15)
-               return -EINVAL;
-       pdf--;
-
-       temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
-       do_div(temp64, quad_parent_rate/1000000);
-       mfn = (long)temp64;
-
-       dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-       /* use dpdck0_2 */
-       __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
-       pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-       if (pll_hfsm == 0) {
-               reg = mfi << 4 | pdf;
-               __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
-               __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
-               __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
-       } else {
-               reg = mfi << 4 | pdf;
-               __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
-               __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
-               __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
-       }
-
-       return 0;
-}
-
-static int _clk_pll_enable(struct clk *clk)
-{
-       u32 reg;
-       void __iomem *pllbase;
-       int i = 0;
-
-       pllbase = _get_pll_base(clk);
-       reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-       if (reg & MXC_PLL_DP_CTL_UPEN)
-               return 0;
-
-       reg |= MXC_PLL_DP_CTL_UPEN;
-       __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-
-       /* Wait for lock */
-       do {
-               reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-               if (reg & MXC_PLL_DP_CTL_LRF)
-                       break;
-
-               udelay(1);
-       } while (++i < MAX_DPLL_WAIT_TRIES);
-
-       if (i == MAX_DPLL_WAIT_TRIES) {
-               pr_err("MX5: pll locking failed\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void _clk_pll_disable(struct clk *clk)
-{
-       u32 reg;
-       void __iomem *pllbase;
-
-       pllbase = _get_pll_base(clk);
-       reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
-       __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-}
-
-static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg, step;
-
-       reg = __raw_readl(MXC_CCM_CCSR);
-
-       /* When switching from pll_main_clk to a bypass clock, first select a
-        * multiplexed clock in 'step_sel', then shift the glitchless mux
-        * 'pll1_sw_clk_sel'.
-        *
-        * When switching back, do it in reverse order
-        */
-       if (parent == &pll1_main_clk) {
-               /* Switch to pll1_main_clk */
-               reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-               __raw_writel(reg, MXC_CCM_CCSR);
-               /* step_clk mux switched to lp_apm, to save power. */
-               reg = __raw_readl(MXC_CCM_CCSR);
-               reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-               reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
-                               MXC_CCM_CCSR_STEP_SEL_OFFSET);
-       } else {
-               if (parent == &lp_apm_clk) {
-                       step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-               } else  if (parent == &pll2_sw_clk) {
-                       step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-               } else  if (parent == &pll3_sw_clk) {
-                       step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
-               } else
-                       return -EINVAL;
-
-               reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-               reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
-
-               __raw_writel(reg, MXC_CCM_CCSR);
-               /* Switch to step_clk */
-               reg = __raw_readl(MXC_CCM_CCSR);
-               reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-       }
-       __raw_writel(reg, MXC_CCM_CCSR);
-       return 0;
-}
-
-static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
-{
-       u32 reg, div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       reg = __raw_readl(MXC_CCM_CCSR);
-
-       if (clk->parent == &pll2_sw_clk) {
-               div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
-                      MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-       } else if (clk->parent == &pll3_sw_clk) {
-               div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
-                      MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
-       } else
-               div = 1;
-       return parent_rate / div;
-}
-
-static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CCSR);
-
-       if (parent == &pll2_sw_clk)
-               reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-       else
-               reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-
-       __raw_writel(reg, MXC_CCM_CCSR);
-       return 0;
-}
-
-static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       if (parent == &osc_clk)
-               reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
-       else
-               return -EINVAL;
-
-       __raw_writel(reg, MXC_CCM_CCSR);
-
-       return 0;
-}
-
-static unsigned long clk_cpu_get_rate(struct clk *clk)
-{
-       u32 cacrr, div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-       cacrr = __raw_readl(MXC_CCM_CACRR);
-       div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
-
-       return parent_rate / div;
-}
-
-static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
-{
-       u32 reg, cpu_podf;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-       cpu_podf = parent_rate / rate - 1;
-       /* use post divider to change freq */
-       reg = __raw_readl(MXC_CCM_CACRR);
-       reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
-       reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
-       __raw_writel(reg, MXC_CCM_CACRR);
-
-       return 0;
-}
-
-static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg, mux;
-       int i = 0;
-
-       mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
-
-       reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
-       reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
-       __raw_writel(reg, MXC_CCM_CBCMR);
-
-       /* Wait for lock */
-       do {
-               reg = __raw_readl(MXC_CCM_CDHIPR);
-               if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
-                       break;
-
-               udelay(1);
-       } while (++i < MAX_DPLL_WAIT_TRIES);
-
-       if (i == MAX_DPLL_WAIT_TRIES) {
-               pr_err("MX5: Set parent for periph_apm clock failed\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-
-       if (parent == &pll2_sw_clk)
-               reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-       else if (parent == &periph_apm_clk)
-               reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-       else
-               return -EINVAL;
-
-       __raw_writel(reg, MXC_CCM_CBCDR);
-
-       return 0;
-}
-
-static struct clk main_bus_clk = {
-       .parent = &pll2_sw_clk,
-       .set_parent = _clk_main_bus_set_parent,
-};
-
-static unsigned long clk_ahb_get_rate(struct clk *clk)
-{
-       u32 reg, div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
-              MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
-       return parent_rate / div;
-}
-
-
-static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
-{
-       u32 reg, div;
-       unsigned long parent_rate;
-       int i = 0;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       div = parent_rate / rate;
-       if (div > 8 || div < 1 || ((parent_rate / div) != rate))
-               return -EINVAL;
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
-       reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
-       __raw_writel(reg, MXC_CCM_CBCDR);
-
-       /* Wait for lock */
-       do {
-               reg = __raw_readl(MXC_CCM_CDHIPR);
-               if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
-                       break;
-
-               udelay(1);
-       } while (++i < MAX_DPLL_WAIT_TRIES);
-
-       if (i == MAX_DPLL_WAIT_TRIES) {
-               pr_err("MX5: clk_ahb_set_rate failed\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static unsigned long _clk_ahb_round_rate(struct clk *clk,
-                                               unsigned long rate)
-{
-       u32 div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       div = parent_rate / rate;
-       if (div > 8)
-               div = 8;
-       else if (div == 0)
-               div++;
-       return parent_rate / div;
-}
-
-
-static int _clk_max_enable(struct clk *clk)
-{
-       u32 reg;
-
-       _clk_ccgr_enable(clk);
-
-       /* Handshake with MAX when LPM is entered. */
-       reg = __raw_readl(MXC_CCM_CLPCR);
-       if (cpu_is_mx51())
-               reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-       else if (cpu_is_mx53())
-               reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-       __raw_writel(reg, MXC_CCM_CLPCR);
-
-       return 0;
-}
-
-static void _clk_max_disable(struct clk *clk)
-{
-       u32 reg;
-
-       _clk_ccgr_disable_inwait(clk);
-
-       /* No Handshake with MAX when LPM is entered as its disabled. */
-       reg = __raw_readl(MXC_CCM_CLPCR);
-       if (cpu_is_mx51())
-               reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-       else if (cpu_is_mx53())
-               reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-       __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static unsigned long clk_ipg_get_rate(struct clk *clk)
-{
-       u32 reg, div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
-              MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
-
-       return parent_rate / div;
-}
-
-static unsigned long clk_ipg_per_get_rate(struct clk *clk)
-{
-       u32 reg, prediv1, prediv2, podf;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
-               /* the main_bus_clk is the one before the DVFS engine */
-               reg = __raw_readl(MXC_CCM_CBCDR);
-               prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
-                          MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
-               prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
-                          MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
-               podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
-                       MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
-               return parent_rate / (prediv1 * prediv2 * podf);
-       } else if (clk->parent == &ipg_clk)
-               return parent_rate;
-       else
-               BUG();
-}
-
-static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CBCMR);
-
-       reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-       reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-
-       if (parent == &ipg_clk)
-               reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-       else if (parent == &lp_apm_clk)
-               reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-       else if (parent != &main_bus_clk)
-               return -EINVAL;
-
-       __raw_writel(reg, MXC_CCM_CBCMR);
-
-       return 0;
-}
-
-#define clk_nfc_set_parent     NULL
-
-static unsigned long clk_nfc_get_rate(struct clk *clk)
-{
-       unsigned long rate;
-       u32 reg, div;
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
-              MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
-       rate = clk_get_rate(clk->parent) / div;
-       WARN_ON(rate == 0);
-       return rate;
-}
-
-static unsigned long clk_nfc_round_rate(struct clk *clk,
-                                               unsigned long rate)
-{
-       u32 div;
-       unsigned long parent_rate = clk_get_rate(clk->parent);
-
-       if (!rate)
-               return -EINVAL;
-
-       div = parent_rate / rate;
-
-       if (parent_rate % rate)
-               div++;
-
-       if (div > 8)
-               return -EINVAL;
-
-       return parent_rate / div;
-
-}
-
-static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
-{
-       u32 reg, div;
-
-       div = clk_get_rate(clk->parent) / rate;
-       if (div == 0)
-               div++;
-       if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
-               return -EINVAL;
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
-       reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
-       __raw_writel(reg, MXC_CCM_CBCDR);
-
-       while (__raw_readl(MXC_CCM_CDHIPR) &
-                       MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
-       }
-
-       return 0;
-}
-
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
-{
-       return external_high_reference;
-}
-
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
-{
-       return external_low_reference;
-}
-
-static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
-{
-       return oscillator_reference;
-}
-
-static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
-{
-       return ckih2_reference;
-}
-
-static unsigned long clk_emi_slow_get_rate(struct clk *clk)
-{
-       u32 reg, div;
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
-              MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
-
-       return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
-{
-       unsigned long rate;
-       u32 reg, div;
-
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
-               MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
-       rate = clk_get_rate(clk->parent) / div;
-
-       return rate;
-}
-
-/* External high frequency clock */
-static struct clk ckih_clk = {
-       .get_rate = get_high_reference_clock_rate,
-};
-
-static struct clk ckih2_clk = {
-       .get_rate = get_ckih2_reference_clock_rate,
-};
-
-static struct clk osc_clk = {
-       .get_rate = get_oscillator_reference_clock_rate,
-};
-
-/* External low frequency (32kHz) clock */
-static struct clk ckil_clk = {
-       .get_rate = get_low_reference_clock_rate,
-};
-
-static struct clk pll1_main_clk = {
-       .parent = &osc_clk,
-       .get_rate = clk_pll_get_rate,
-       .enable = _clk_pll_enable,
-       .disable = _clk_pll_disable,
-};
-
-/* Clock tree block diagram (WIP):
- *     CCM: Clock Controller Module
- *
- * PLL output -> |
- *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
- * PLL bypass -> |
- *
- */
-
-/* PLL1 SW supplies to ARM core */
-static struct clk pll1_sw_clk = {
-       .parent = &pll1_main_clk,
-       .set_parent = _clk_pll1_sw_set_parent,
-       .get_rate = clk_pll1_sw_get_rate,
-};
-
-/* PLL2 SW supplies to AXI/AHB/IP buses */
-static struct clk pll2_sw_clk = {
-       .parent = &osc_clk,
-       .get_rate = clk_pll_get_rate,
-       .set_rate = _clk_pll_set_rate,
-       .set_parent = _clk_pll2_sw_set_parent,
-       .enable = _clk_pll_enable,
-       .disable = _clk_pll_disable,
-};
-
-/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
-static struct clk pll3_sw_clk = {
-       .parent = &osc_clk,
-       .set_rate = _clk_pll_set_rate,
-       .get_rate = clk_pll_get_rate,
-       .enable = _clk_pll_enable,
-       .disable = _clk_pll_disable,
-};
-
-/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
-static struct clk mx53_pll4_sw_clk = {
-       .parent = &osc_clk,
-       .set_rate = _clk_pll_set_rate,
-       .enable = _clk_pll_enable,
-       .disable = _clk_pll_disable,
-};
-
-/* Low-power Audio Playback Mode clock */
-static struct clk lp_apm_clk = {
-       .parent = &osc_clk,
-       .set_parent = _clk_lp_apm_set_parent,
-};
-
-static struct clk periph_apm_clk = {
-       .parent = &pll1_sw_clk,
-       .set_parent = _clk_periph_apm_set_parent,
-};
-
-static struct clk cpu_clk = {
-       .parent = &pll1_sw_clk,
-       .get_rate = clk_cpu_get_rate,
-       .set_rate = clk_cpu_set_rate,
-};
-
-static struct clk ahb_clk = {
-       .parent = &main_bus_clk,
-       .get_rate = clk_ahb_get_rate,
-       .set_rate = _clk_ahb_set_rate,
-       .round_rate = _clk_ahb_round_rate,
-};
-
-static struct clk iim_clk = {
-       .parent = &ipg_clk,
-       .enable_reg = MXC_CCM_CCGR0,
-       .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
-};
-
-/* Main IP interface clock for access to registers */
-static struct clk ipg_clk = {
-       .parent = &ahb_clk,
-       .get_rate = clk_ipg_get_rate,
-};
-
-static struct clk ipg_perclk = {
-       .parent = &lp_apm_clk,
-       .get_rate = clk_ipg_per_get_rate,
-       .set_parent = _clk_ipg_per_set_parent,
-};
-
-static struct clk ahb_max_clk = {
-       .parent = &ahb_clk,
-       .enable_reg = MXC_CCM_CCGR0,
-       .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-       .enable = _clk_max_enable,
-       .disable = _clk_max_disable,
-};
-
-static struct clk aips_tz1_clk = {
-       .parent = &ahb_clk,
-       .secondary = &ahb_max_clk,
-       .enable_reg = MXC_CCM_CCGR0,
-       .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk aips_tz2_clk = {
-       .parent = &ahb_clk,
-       .secondary = &ahb_max_clk,
-       .enable_reg = MXC_CCM_CCGR0,
-       .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk gpc_dvfs_clk = {
-       .enable_reg = MXC_CCM_CCGR5,
-       .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable,
-};
-
-static struct clk gpt_32k_clk = {
-       .id = 0,
-       .parent = &ckil_clk,
-};
-
-static struct clk dummy_clk = {
-       .id = 0,
-};
-
-static struct clk emi_slow_clk = {
-       .parent = &pll2_sw_clk,
-       .enable_reg = MXC_CCM_CCGR5,
-       .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable_inwait,
-       .get_rate = clk_emi_slow_get_rate,
-};
-
-static int clk_ipu_enable(struct clk *clk)
-{
-       u32 reg;
-
-       _clk_ccgr_enable(clk);
-
-       /* Enable handshake with IPU when certain clock rates are changed */
-       reg = __raw_readl(MXC_CCM_CCDR);
-       reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
-       __raw_writel(reg, MXC_CCM_CCDR);
-
-       /* Enable handshake with IPU when LPM is entered */
-       reg = __raw_readl(MXC_CCM_CLPCR);
-       reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
-       __raw_writel(reg, MXC_CCM_CLPCR);
-
-       return 0;
-}
-
-static void clk_ipu_disable(struct clk *clk)
-{
-       u32 reg;
-
-       _clk_ccgr_disable(clk);
-
-       /* Disable handshake with IPU whe dividers are changed */
-       reg = __raw_readl(MXC_CCM_CCDR);
-       reg |= MXC_CCM_CCDR_IPU_HS_MASK;
-       __raw_writel(reg, MXC_CCM_CCDR);
-
-       /* Disable handshake with IPU when LPM is entered */
-       reg = __raw_readl(MXC_CCM_CLPCR);
-       reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
-       __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk ahbmux1_clk = {
-       .parent = &ahb_clk,
-       .secondary = &ahb_max_clk,
-       .enable_reg = MXC_CCM_CCGR0,
-       .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk ipu_sec_clk = {
-       .parent = &emi_fast_clk,
-       .secondary = &ahbmux1_clk,
-};
-
-static struct clk ddr_hf_clk = {
-       .parent = &pll1_sw_clk,
-       .get_rate = _clk_ddr_hf_get_rate,
-};
-
-static struct clk ddr_clk = {
-       .parent = &ddr_hf_clk,
-};
-
-/* clock definitions for MIPI HSC unit which has been removed
- * from documentation, but not from hardware
- */
-static int _clk_hsc_enable(struct clk *clk)
-{
-       u32 reg;
-
-       _clk_ccgr_enable(clk);
-       /* Handshake with IPU when certain clock rates are changed. */
-       reg = __raw_readl(MXC_CCM_CCDR);
-       reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
-       __raw_writel(reg, MXC_CCM_CCDR);
-
-       reg = __raw_readl(MXC_CCM_CLPCR);
-       reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
-       __raw_writel(reg, MXC_CCM_CLPCR);
-
-       return 0;
-}
-
-static void _clk_hsc_disable(struct clk *clk)
-{
-       u32 reg;
-
-       _clk_ccgr_disable(clk);
-       /* No handshake with HSC as its not enabled. */
-       reg = __raw_readl(MXC_CCM_CCDR);
-       reg |= MXC_CCM_CCDR_HSC_HS_MASK;
-       __raw_writel(reg, MXC_CCM_CCDR);
-
-       reg = __raw_readl(MXC_CCM_CLPCR);
-       reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
-       __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk mipi_hsp_clk = {
-       .parent = &ipu_clk,
-       .enable_reg = MXC_CCM_CCGR4,
-       .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
-       .enable = _clk_hsc_enable,
-       .disable = _clk_hsc_disable,
-       .secondary = &mipi_hsc1_clk,
-};
-
-#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)  \
-       static struct clk name = {                      \
-               .id             = i,                    \
-               .enable_reg     = er,                   \
-               .enable_shift   = es,                   \
-               .get_rate       = pfx##_get_rate,       \
-               .set_rate       = pfx##_set_rate,       \
-               .round_rate     = pfx##_round_rate,     \
-               .set_parent     = pfx##_set_parent,     \
-               .enable         = _clk_ccgr_enable,     \
-               .disable        = _clk_ccgr_disable,    \
-               .parent         = p,                    \
-               .secondary      = s,                    \
-       }
-
-#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)   \
-       static struct clk name = {                      \
-               .id             = i,                    \
-               .enable_reg     = er,                   \
-               .enable_shift   = es,                   \
-               .get_rate       = pfx##_get_rate,       \
-               .set_rate       = pfx##_set_rate,       \
-               .set_parent     = pfx##_set_parent,     \
-               .enable         = _clk_max_enable,      \
-               .disable        = _clk_max_disable,     \
-               .parent         = p,                    \
-               .secondary      = s,                    \
-       }
-
-#define CLK_GET_RATE(name, nr, bitsname)                               \
-static unsigned long clk_##name##_get_rate(struct clk *clk)            \
-{                                                                      \
-       u32 reg, pred, podf;                                            \
-                                                                       \
-       reg = __raw_readl(MXC_CCM_CSCDR##nr);                           \
-       pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)   \
-               >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;    \
-       podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)   \
-               >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;    \
-                                                                       \
-       return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),             \
-                       (pred + 1) * (podf + 1));                       \
-}
-
-#define CLK_SET_PARENT(name, nr, bitsname)                             \
-static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)        \
-{                                                                      \
-       u32 reg, mux;                                                   \
-                                                                       \
-       mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,              \
-                       &pll3_sw_clk, &lp_apm_clk);                     \
-       reg = __raw_readl(MXC_CCM_CSCMR##nr) &                          \
-               ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;         \
-       reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;  \
-       __raw_writel(reg, MXC_CCM_CSCMR##nr);                           \
-                                                                       \
-       return 0;                                                       \
-}
-
-#define CLK_SET_RATE(name, nr, bitsname)                               \
-static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)  \
-{                                                                      \
-       u32 reg, div, parent_rate;                                      \
-       u32 pre = 0, post = 0;                                          \
-                                                                       \
-       parent_rate = clk_get_rate(clk->parent);                        \
-       div = parent_rate / rate;                                       \
-                                                                       \
-       if ((parent_rate / div) != rate)                                \
-               return -EINVAL;                                         \
-                                                                       \
-       __calc_pre_post_dividers(div, &pre, &post,                      \
-               (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>      \
-               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,  \
-               (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>      \
-               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
-                                                                       \
-       /* Set sdhc1 clock divider */                                   \
-       reg = __raw_readl(MXC_CCM_CSCDR##nr) &                          \
-               ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK        \
-               | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);      \
-       reg |= (post - 1) <<                                            \
-               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;       \
-       reg |= (pre - 1) <<                                             \
-               MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;       \
-       __raw_writel(reg, MXC_CCM_CSCDR##nr);                           \
-                                                                       \
-       return 0;                                                       \
-}
-
-/* UART */
-CLK_GET_RATE(uart, 1, UART)
-CLK_SET_PARENT(uart, 1, UART)
-
-static struct clk uart_root_clk = {
-       .parent = &pll2_sw_clk,
-       .get_rate = clk_uart_get_rate,
-       .set_parent = clk_uart_set_parent,
-};
-
-/* USBOH3 */
-CLK_GET_RATE(usboh3, 1, USBOH3)
-CLK_SET_PARENT(usboh3, 1, USBOH3)
-
-static struct clk usboh3_clk = {
-       .parent = &pll2_sw_clk,
-       .get_rate = clk_usboh3_get_rate,
-       .set_parent = clk_usboh3_set_parent,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable,
-       .enable_reg = MXC_CCM_CCGR2,
-       .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-};
-
-static struct clk usb_ahb_clk = {
-       .parent = &ipg_clk,
-       .enable = _clk_ccgr_enable,
-       .disable = _clk_ccgr_disable,
-       .enable_reg = MXC_CCM_CCGR2,
-       .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-};
-
-static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
-
-       if (parent == &pll3_sw_clk)
-               reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
-
-       __raw_writel(reg, MXC_CCM_CSCMR1);
-
-       return 0;
-}
-
-static struct clk usb_phy1_clk = {
-       .parent = &pll3_sw_clk,
-       .set_parent = clk_usb_phy1_set_parent,
-       .enable = _clk_ccgr_enable,
-       .enable_reg = MXC_CCM_CCGR2,
-       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
-       .disable = _clk_ccgr_disable,
-};
-
-/* eCSPI */
-CLK_GET_RATE(ecspi, 2, CSPI)
-CLK_SET_PARENT(ecspi, 1, CSPI)
-
-static struct clk ecspi_main_clk = {
-       .parent = &pll3_sw_clk,
-       .get_rate = clk_ecspi_get_rate,
-       .set_parent = clk_ecspi_set_parent,
-};
-
-/* eSDHC */
-CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-
-/* mx51 specific */
-CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-
-static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CSCMR1);
-       if (parent == &esdhc1_clk)
-               reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
-       else if (parent == &esdhc2_clk)
-               reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
-       else
-               return -EINVAL;
-       __raw_writel(reg, MXC_CCM_CSCMR1);
-
-       return 0;
-}
-
-static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CSCMR1);
-       if (parent == &esdhc1_clk)
-               reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-       else if (parent == &esdhc2_clk)
-               reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-       else
-               return -EINVAL;
-       __raw_writel(reg, MXC_CCM_CSCMR1);
-
-       return 0;
-}
-
-/* mx53 specific */
-static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CSCMR1);
-       if (parent == &esdhc1_clk)
-               reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
-       else if (parent == &esdhc3_mx53_clk)
-               reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
-       else
-               return -EINVAL;
-       __raw_writel(reg, MXC_CCM_CSCMR1);
-
-       return 0;
-}
-
-CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-
-static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(MXC_CCM_CSCMR1);
-       if (parent == &esdhc1_clk)
-               reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-       else if (parent == &esdhc3_mx53_clk)
-               reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-       else
-               return -EINVAL;
-       __raw_writel(reg, MXC_CCM_CSCMR1);
-
-       return 0;
-}
-
-#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)         \
-       static struct clk name = {                                      \
-               .id             = i,                                    \
-               .enable_reg     = er,                                   \
-               .enable_shift   = es,                                   \
-               .get_rate       = gr,                                   \
-               .set_rate       = sr,                                   \
-               .enable         = e,                                    \
-               .disable        = d,                                    \
-               .parent         = p,                                    \
-               .secondary      = s,                                    \
-       }
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)                    \
-       DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
-
-/* Shared peripheral bus arbiter */
-DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
-       NULL,  NULL, &ipg_clk, NULL);
-
-/* UART */
-DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
-       NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
-       NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
-       NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
-       NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
-       NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
-       NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
-       NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
-       NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
-DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
-       NULL,  NULL, &uart_root_clk, &uart4_ipg_clk);
-DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
-       NULL,  NULL, &uart_root_clk, &uart5_ipg_clk);
-
-/* GPT */
-DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
-       NULL,  NULL, &ipg_clk, NULL);
-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_perclk, NULL);
-DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-       NULL, NULL, &ipg_perclk, NULL);
-
-/* I2C */
-DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
-       NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
-       NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
-       NULL, NULL, &ipg_perclk, NULL);
-
-/* FEC */
-DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
-       NULL,  NULL, &ipg_clk, NULL);
-
-/* NFC */
-DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
-       clk_nfc, &emi_slow_clk, NULL);
-
-/* SSI */
-DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
-       NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
-DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
-       NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
-DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
-       NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
-
-/* eCSPI */
-DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-               NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-               &ipg_clk, &spba_clk);
-DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
-               NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
-DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
-               NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-               &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
-               NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
-
-/* CSPI */
-DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-               NULL, NULL, &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
-               NULL, NULL, &ipg_clk, &cspi_ipg_clk);
-
-/* SDMA */
-DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
-               NULL, NULL, &ahb_clk, NULL);
-
-/* eSDHC */
-DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
-       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
-       clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
-DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
-       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
-       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
-       NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-
-/* mx51 specific */
-DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
-       clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc3_clk = {
-       .id = 2,
-       .parent = &esdhc1_clk,
-       .set_parent = clk_esdhc3_set_parent,
-       .enable_reg = MXC_CCM_CCGR3,
-       .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
-       .enable  = _clk_max_enable,
-       .disable = _clk_max_disable,
-       .secondary = &esdhc3_ipg_clk,
-};
-static struct clk esdhc4_clk = {
-       .id = 3,
-       .parent = &esdhc1_clk,
-       .set_parent = clk_esdhc4_set_parent,
-       .enable_reg = MXC_CCM_CCGR3,
-       .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
-       .enable  = _clk_max_enable,
-       .disable = _clk_max_disable,
-       .secondary = &esdhc4_ipg_clk,
-};
-
-/* mx53 specific */
-static struct clk esdhc2_mx53_clk = {
-       .id = 2,
-       .parent = &esdhc1_clk,
-       .set_parent = clk_esdhc2_mx53_set_parent,
-       .enable_reg = MXC_CCM_CCGR3,
-       .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
-       .enable  = _clk_max_enable,
-       .disable = _clk_max_disable,
-       .secondary = &esdhc3_ipg_clk,
-};
-
-DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
-       clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc4_mx53_clk = {
-       .id = 3,
-       .parent = &esdhc1_clk,
-       .set_parent = clk_esdhc4_mx53_set_parent,
-       .enable_reg = MXC_CCM_CCGR3,
-       .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
-       .enable  = _clk_max_enable,
-       .disable = _clk_max_disable,
-       .secondary = &esdhc4_ipg_clk,
-};
-
-static struct clk sata_clk = {
-       .parent = &ipg_clk,
-       .enable = _clk_max_enable,
-       .enable_reg = MXC_CCM_CCGR4,
-       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
-       .disable = _clk_max_disable,
-};
-
-static struct clk ahci_phy_clk = {
-       .parent = &usb_phy1_clk,
-};
-
-static struct clk ahci_dma_clk = {
-       .parent = &ahb_clk,
-};
-
-DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
-
-/* IPU */
-DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
-       NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
-
-DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
-               NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
-               &ddr_clk, NULL);
-
-DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
-               NULL, NULL, &pll3_sw_clk, NULL);
-DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
-               NULL, NULL, &pll3_sw_clk, NULL);
-
-/* PATA */
-DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
-               NULL, NULL, &ipg_clk, &spba_clk);
-
-#define _REGISTER_CLOCK(d, n, c) \
-       { \
-               .dev_id = d, \
-               .con_id = n, \
-               .clk = &c,   \
-       },
-
-static struct clk_lookup mx51_lookups[] = {
-       /* i.mx51 has the i.mx21 type uart */
-       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
-       _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-       /* i.mx51 has the i.mx27 type fec */
-       _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
-       _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
-       _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
-       _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-       _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
-       _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
-       _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
-       _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
-       _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
-       _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
-       _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
-       _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
-       _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
-       _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-       _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
-       _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
-       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-       /* i.mx51 has the i.mx35 type sdma */
-       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
-       _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
-       _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
-       _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
-       _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
-       _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-       /* i.mx51 has the i.mx35 type cspi */
-       _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
-       _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
-       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
-       _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
-       _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-       _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
-       _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
-       _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
-       _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
-       _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
-       _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
-};
-
-static struct clk_lookup mx53_lookups[] = {
-       /* i.mx53 has the i.mx21 type uart */
-       _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
-       _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
-       _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
-       _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
-       _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
-       _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-       /* i.mx53 has the i.mx25 type fec */
-       _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
-       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
-       _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-       _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
-       /* i.mx53 has the i.mx51 type ecspi */
-       _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
-       _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-       /* i.mx53 has the i.mx25 type cspi */
-       _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
-       _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
-       _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
-       _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-       /* i.mx53 has the i.mx35 type sdma */
-       _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
-       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-       _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
-       _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
-       _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
-       _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
-       _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
-};
-
-static void clk_tree_init(void)
-{
-       u32 reg;
-
-       ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
-
-       /*
-        * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
-        * 8MHz, its derived from lp_apm.
-        *
-        * FIXME: Verify if true for all boards
-        */
-       reg = __raw_readl(MXC_CCM_CBCDR);
-       reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
-       reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
-       reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
-       reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
-       __raw_writel(reg, MXC_CCM_CBCDR);
-}
-
-int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
-                       unsigned long ckih1, unsigned long ckih2)
-{
-       int i;
-
-       external_low_reference = ckil;
-       external_high_reference = ckih1;
-       ckih2_reference = ckih2;
-       oscillator_reference = osc;
-
-       for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
-               clkdev_add(&mx51_lookups[i]);
-
-       clk_tree_init();
-
-       clk_enable(&cpu_clk);
-       clk_enable(&main_bus_clk);
-
-       clk_enable(&iim_clk);
-       imx_print_silicon_rev("i.MX51", mx51_revision());
-       clk_disable(&iim_clk);
-
-       /* move usb_phy_clk to 24MHz */
-       clk_set_parent(&usb_phy1_clk, &osc_clk);
-
-       /* set the usboh3_clk parent to pll2_sw_clk */
-       clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-
-       /* Set SDHC parents to be PLL2 */
-       clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-       clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
-
-       /* set SDHC root clock as 166.25MHZ*/
-       clk_set_rate(&esdhc1_clk, 166250000);
-       clk_set_rate(&esdhc2_clk, 166250000);
-
-       /* System timer */
-       mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-               MX51_INT_GPT);
-       return 0;
-}
-
-int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
-                       unsigned long ckih1, unsigned long ckih2)
-{
-       int i;
-
-       external_low_reference = ckil;
-       external_high_reference = ckih1;
-       ckih2_reference = ckih2;
-       oscillator_reference = osc;
-
-       for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
-               clkdev_add(&mx53_lookups[i]);
-
-       clk_tree_init();
-
-       clk_set_parent(&uart_root_clk, &pll3_sw_clk);
-       clk_enable(&cpu_clk);
-       clk_enable(&main_bus_clk);
-
-       clk_enable(&iim_clk);
-       imx_print_silicon_rev("i.MX53", mx53_revision());
-       clk_disable(&iim_clk);
-
-       /* Set SDHC parents to be PLL2 */
-       clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-       clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
-
-       /* set SDHC root clock as 200MHZ*/
-       clk_set_rate(&esdhc1_clk, 200000000);
-       clk_set_rate(&esdhc3_mx53_clk, 200000000);
-
-       /* System timer */
-       mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
-               MX53_INT_GPT);
-       return 0;
-}
-
-#ifdef CONFIG_OF
-static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
-                                  unsigned long *ckih1, unsigned long *ckih2)
-{
-       struct device_node *np;
-
-       /* retrieve the freqency of fixed clocks from device tree */
-       for_each_compatible_node(np, NULL, "fixed-clock") {
-               u32 rate;
-               if (of_property_read_u32(np, "clock-frequency", &rate))
-                       continue;
-
-               if (of_device_is_compatible(np, "fsl,imx-ckil"))
-                       *ckil = rate;
-               else if (of_device_is_compatible(np, "fsl,imx-osc"))
-                       *osc = rate;
-               else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
-                       *ckih1 = rate;
-               else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
-                       *ckih2 = rate;
-       }
-}
-
-int __init mx51_clocks_init_dt(void)
-{
-       unsigned long ckil, osc, ckih1, ckih2;
-
-       clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
-       return mx51_clocks_init(ckil, osc, ckih1, ckih2);
-}
-
-int __init mx53_clocks_init_dt(void)
-{
-       unsigned long ckil, osc, ckih1, ckih2;
-
-       clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
-       return mx53_clocks_init(ckil, osc, ckih1, ckih2);
-}
-#endif
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
deleted file mode 100644 (file)
index 5e2e7a8..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * This file contains the CPU initialization code.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-static int mx5_cpu_rev = -1;
-
-#define IIM_SREV 0x24
-#define MX50_HW_ADADIG_DIGPROG 0xB0
-
-static int get_mx51_srev(void)
-{
-       void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
-       u32 rev = readl(iim_base + IIM_SREV) & 0xff;
-
-       switch (rev) {
-       case 0x0:
-               return IMX_CHIP_REVISION_2_0;
-       case 0x10:
-               return IMX_CHIP_REVISION_3_0;
-       default:
-               return IMX_CHIP_REVISION_UNKNOWN;
-       }
-}
-
-/*
- * Returns:
- *     the silicon revision of the cpu
- *     -EINVAL - not a mx51
- */
-int mx51_revision(void)
-{
-       if (!cpu_is_mx51())
-               return -EINVAL;
-
-       if (mx5_cpu_rev == -1)
-               mx5_cpu_rev = get_mx51_srev();
-
-       return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx51_revision);
-
-#ifdef CONFIG_NEON
-
-/*
- * All versions of the silicon before Rev. 3 have broken NEON implementations.
- * Dependent on link order - so the assumption is that vfp_init is called
- * before us.
- */
-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)) {
-               elf_hwcap &= ~HWCAP_NEON;
-               pr_info("Turning off NEON support, detected broken NEON implementation\n");
-       }
-       return 0;
-}
-
-late_initcall(mx51_neon_fixup);
-#endif
-
-static int get_mx53_srev(void)
-{
-       void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
-       u32 rev = readl(iim_base + IIM_SREV) & 0xff;
-
-       switch (rev) {
-       case 0x0:
-               return IMX_CHIP_REVISION_1_0;
-       case 0x2:
-               return IMX_CHIP_REVISION_2_0;
-       case 0x3:
-               return IMX_CHIP_REVISION_2_1;
-       default:
-               return IMX_CHIP_REVISION_UNKNOWN;
-       }
-}
-
-/*
- * Returns:
- *     the silicon revision of the cpu
- *     -EINVAL - not a mx53
- */
-int mx53_revision(void)
-{
-       if (!cpu_is_mx53())
-               return -EINVAL;
-
-       if (mx5_cpu_rev == -1)
-               mx5_cpu_rev = get_mx53_srev();
-
-       return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx53_revision);
-
-static int get_mx50_srev(void)
-{
-       void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
-       u32 rev;
-
-       if (!anatop) {
-               mx5_cpu_rev = -EINVAL;
-               return 0;
-       }
-
-       rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
-       rev &= 0xff;
-
-       iounmap(anatop);
-       if (rev == 0x0)
-               return IMX_CHIP_REVISION_1_0;
-       else if (rev == 0x1)
-               return IMX_CHIP_REVISION_1_1;
-       return 0;
-}
-
-/*
- * Returns:
- *     the silicon revision of the cpu
- *     -EINVAL - not a mx50
- */
-int mx50_revision(void)
-{
-       if (!cpu_is_mx50())
-               return -EINVAL;
-
-       if (mx5_cpu_rev == -1)
-               mx5_cpu_rev = get_mx50_srev();
-
-       return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx50_revision);
-
-static int __init post_cpu_init(void)
-{
-       unsigned int reg;
-       void __iomem *base;
-
-       if (cpu_is_mx51() || cpu_is_mx53()) {
-               if (cpu_is_mx51())
-                       base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
-               else
-                       base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
-
-               __raw_writel(0x0, base + 0x40);
-               __raw_writel(0x0, base + 0x44);
-               __raw_writel(0x0, base + 0x48);
-               __raw_writel(0x0, base + 0x4C);
-               reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-               __raw_writel(reg, base + 0x50);
-
-               if (cpu_is_mx51())
-                       base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
-               else
-                       base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
-
-               __raw_writel(0x0, base + 0x40);
-               __raw_writel(0x0, base + 0x44);
-               __raw_writel(0x0, base + 0x48);
-               __raw_writel(0x0, base + 0x4C);
-               reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-               __raw_writel(reg, base + 0x50);
-       }
-
-       return 0;
-}
-
-postcore_initcall(post_cpu_init);
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.c b/arch/arm/mach-mx5/cpu_op-mx51.c
deleted file mode 100644 (file)
index 9d34c3d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/types.h>
-#include <mach/hardware.h>
-#include <linux/kernel.h>
-
-static struct cpu_op mx51_cpu_op[] = {
-       {
-       .cpu_rate = 160000000,},
-       {
-       .cpu_rate = 800000000,},
-};
-
-struct cpu_op *mx51_get_cpu_op(int *op)
-{
-       *op = ARRAY_SIZE(mx51_cpu_op);
-       return mx51_cpu_op;
-}
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h
deleted file mode 100644 (file)
index 97477fe..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-extern struct cpu_op *mx51_get_cpu_op(int *op);
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
deleted file mode 100644 (file)
index 5e11ba7..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-
-#define MX51_CCM_BASE          MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
-#define MX51_DPLL1_BASE                MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
-#define MX51_DPLL2_BASE                MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
-#define MX51_DPLL3_BASE                MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
-#define MX51_CORTEXA8_BASE     MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
-#define MX51_GPC_BASE          MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
-
-/*MX53*/
-#define MX53_CCM_BASE          MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
-#define MX53_DPLL1_BASE                MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
-#define MX53_DPLL2_BASE                MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
-#define MX53_DPLL3_BASE                MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-#define MX53_DPLL4_BASE                MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-
-/* PLL Register Offsets */
-#define MXC_PLL_DP_CTL                 0x00
-#define MXC_PLL_DP_CONFIG              0x04
-#define MXC_PLL_DP_OP                  0x08
-#define MXC_PLL_DP_MFD                 0x0C
-#define MXC_PLL_DP_MFN                 0x10
-#define MXC_PLL_DP_MFNMINUS            0x14
-#define MXC_PLL_DP_MFNPLUS             0x18
-#define MXC_PLL_DP_HFS_OP              0x1C
-#define MXC_PLL_DP_HFS_MFD             0x20
-#define MXC_PLL_DP_HFS_MFN             0x24
-#define MXC_PLL_DP_MFN_TOGC            0x28
-#define MXC_PLL_DP_DESTAT              0x2c
-
-/* PLL Register Bit definitions */
-#define MXC_PLL_DP_CTL_MUL_CTRL                0x2000
-#define MXC_PLL_DP_CTL_DPDCK0_2_EN     0x1000
-#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12
-#define MXC_PLL_DP_CTL_ADE             0x800
-#define MXC_PLL_DP_CTL_REF_CLK_DIV     0x400
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK        (3 << 8)
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET      8
-#define MXC_PLL_DP_CTL_HFSM            0x80
-#define MXC_PLL_DP_CTL_PRE             0x40
-#define MXC_PLL_DP_CTL_UPEN            0x20
-#define MXC_PLL_DP_CTL_RST             0x10
-#define MXC_PLL_DP_CTL_RCP             0x8
-#define MXC_PLL_DP_CTL_PLM             0x4
-#define MXC_PLL_DP_CTL_BRM0            0x2
-#define MXC_PLL_DP_CTL_LRF             0x1
-
-#define MXC_PLL_DP_CONFIG_BIST         0x8
-#define MXC_PLL_DP_CONFIG_SJC_CE       0x4
-#define MXC_PLL_DP_CONFIG_AREN         0x2
-#define MXC_PLL_DP_CONFIG_LDREQ                0x1
-
-#define MXC_PLL_DP_OP_MFI_OFFSET       4
-#define MXC_PLL_DP_OP_MFI_MASK         (0xF << 4)
-#define MXC_PLL_DP_OP_PDF_OFFSET       0
-#define MXC_PLL_DP_OP_PDF_MASK         0xF
-
-#define MXC_PLL_DP_MFD_OFFSET          0
-#define MXC_PLL_DP_MFD_MASK            0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_OFFSET          0x0
-#define MXC_PLL_DP_MFN_MASK            0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_TOGC_TOG_DIS    (1 << 17)
-#define MXC_PLL_DP_MFN_TOGC_TOG_EN     (1 << 16)
-#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0
-#define MXC_PLL_DP_MFN_TOGC_CNT_MASK   0xFFFF
-
-#define MXC_PLL_DP_DESTAT_TOG_SEL      (1 << 31)
-#define MXC_PLL_DP_DESTAT_MFN          0x07FFFFFF
-
-/* Register addresses of CCM*/
-#define MXC_CCM_CCR            (MX51_CCM_BASE + 0x00)
-#define MXC_CCM_CCDR           (MX51_CCM_BASE + 0x04)
-#define MXC_CCM_CSR            (MX51_CCM_BASE + 0x08)
-#define MXC_CCM_CCSR           (MX51_CCM_BASE + 0x0C)
-#define MXC_CCM_CACRR          (MX51_CCM_BASE + 0x10)
-#define MXC_CCM_CBCDR          (MX51_CCM_BASE + 0x14)
-#define MXC_CCM_CBCMR          (MX51_CCM_BASE + 0x18)
-#define MXC_CCM_CSCMR1         (MX51_CCM_BASE + 0x1C)
-#define MXC_CCM_CSCMR2         (MX51_CCM_BASE + 0x20)
-#define MXC_CCM_CSCDR1         (MX51_CCM_BASE + 0x24)
-#define MXC_CCM_CS1CDR         (MX51_CCM_BASE + 0x28)
-#define MXC_CCM_CS2CDR         (MX51_CCM_BASE + 0x2C)
-#define MXC_CCM_CDCDR          (MX51_CCM_BASE + 0x30)
-#define MXC_CCM_CHSCDR         (MX51_CCM_BASE + 0x34)
-#define MXC_CCM_CSCDR2         (MX51_CCM_BASE + 0x38)
-#define MXC_CCM_CSCDR3         (MX51_CCM_BASE + 0x3C)
-#define MXC_CCM_CSCDR4         (MX51_CCM_BASE + 0x40)
-#define MXC_CCM_CWDR           (MX51_CCM_BASE + 0x44)
-#define MXC_CCM_CDHIPR         (MX51_CCM_BASE + 0x48)
-#define MXC_CCM_CDCR           (MX51_CCM_BASE + 0x4C)
-#define MXC_CCM_CTOR           (MX51_CCM_BASE + 0x50)
-#define MXC_CCM_CLPCR          (MX51_CCM_BASE + 0x54)
-#define MXC_CCM_CISR           (MX51_CCM_BASE + 0x58)
-#define MXC_CCM_CIMR           (MX51_CCM_BASE + 0x5C)
-#define MXC_CCM_CCOSR          (MX51_CCM_BASE + 0x60)
-#define MXC_CCM_CGPR           (MX51_CCM_BASE + 0x64)
-#define MXC_CCM_CCGR0          (MX51_CCM_BASE + 0x68)
-#define MXC_CCM_CCGR1          (MX51_CCM_BASE + 0x6C)
-#define MXC_CCM_CCGR2          (MX51_CCM_BASE + 0x70)
-#define MXC_CCM_CCGR3          (MX51_CCM_BASE + 0x74)
-#define MXC_CCM_CCGR4          (MX51_CCM_BASE + 0x78)
-#define MXC_CCM_CCGR5          (MX51_CCM_BASE + 0x7C)
-#define MXC_CCM_CCGR6          (MX51_CCM_BASE + 0x80)
-#define MXC_CCM_CCGR7          (MX51_CCM_BASE + 0x84)
-
-#define MXC_CCM_CMEOR          (MX51_CCM_BASE + 0x84)
-
-/* Define the bits in register CCR */
-#define MXC_CCM_CCR_COSC_EN            (1 << 12)
-#define MXC_CCM_CCR_FPM_MULT_MASK      (1 << 11)
-#define MXC_CCM_CCR_CAMP2_EN           (1 << 10)
-#define MXC_CCM_CCR_CAMP1_EN           (1 << 9)
-#define MXC_CCM_CCR_FPM_EN             (1 << 8)
-#define MXC_CCM_CCR_OSCNT_OFFSET       (0)
-#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
-
-/* Define the bits in register CCDR */
-#define MXC_CCM_CCDR_HSC_HS_MASK       (0x1 << 18)
-#define MXC_CCM_CCDR_IPU_HS_MASK       (0x1 << 17)
-#define MXC_CCM_CCDR_EMI_HS_MASK       (0x1 << 16)
-
-/* Define the bits in register CSR */
-#define MXC_CCM_CSR_COSR_READY (1 << 5)
-#define MXC_CCM_CSR_LVS_VALUE  (1 << 4)
-#define MXC_CCM_CSR_CAMP2_READY        (1 << 3)
-#define MXC_CCM_CSR_CAMP1_READY        (1 << 2)
-#define MXC_CCM_CSR_FPM_READY  (1 << 1)
-#define MXC_CCM_CSR_REF_EN_B   (1 << 0)
-
-/* Define the bits in register CCSR */
-#define MXC_CCM_CCSR_LP_APM_SEL                (0x1 << 9)
-#define MXC_CCM_CCSR_STEP_SEL_OFFSET   (7)
-#define MXC_CCM_CCSR_STEP_SEL_MASK     (0x3 << 7)
-#define MXC_CCM_CCSR_STEP_SEL_LP_APM      0
-#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS  1 /* Only when JTAG connected? */
-#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
-#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
-#define MXC_CCM_CCSR_PLL2_PODF_OFFSET  (5)
-#define MXC_CCM_CCSR_PLL2_PODF_MASK    (0x3 << 5)
-#define MXC_CCM_CCSR_PLL3_PODF_OFFSET  (3)
-#define MXC_CCM_CCSR_PLL3_PODF_MASK    (0x3 << 3)
-#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL   (1 << 2) /* 0: pll1_main_clk,
-                                                   1: step_clk */
-#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL   (1 << 1)
-#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL   (1 << 0)
-
-/* Define the bits in register CACRR */
-#define MXC_CCM_CACRR_ARM_PODF_OFFSET  (0)
-#define MXC_CCM_CACRR_ARM_PODF_MASK    (0x7)
-
-/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL              (0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL           (0x1 << 25)
-#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET                (30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL               (0x1 << 30)
-#define MXC_CCM_CBCDR_DDR_PODF_OFFSET          (27)
-#define MXC_CCM_CBCDR_DDR_PODF_MASK            (0x7 << 27)
-#define MXC_CCM_CBCDR_EMI_PODF_OFFSET          (22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK            (0x7 << 22)
-#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET                (19)
-#define MXC_CCM_CBCDR_AXI_B_PODF_MASK          (0x7 << 19)
-#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET                (16)
-#define MXC_CCM_CBCDR_AXI_A_PODF_MASK          (0x7 << 16)
-#define MXC_CCM_CBCDR_NFC_PODF_OFFSET          (13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK            (0x7 << 13)
-#define MXC_CCM_CBCDR_AHB_PODF_OFFSET          (10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK            (0x7 << 10)
-#define MXC_CCM_CBCDR_IPG_PODF_OFFSET          (8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK            (0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET      (6)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK                (0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET      (3)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK                (0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET       (0)
-#define MXC_CCM_CBCDR_PERCLK_PODF_MASK         (0x7)
-
-/* Define the bits in register CBCMR */
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET   (14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK     (0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET    (12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK      (0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET       (10)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK         (0x3 << 10)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET   (8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK     (0x3 << 8)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET   (6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK     (0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET       (4)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK         (0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET     (14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK       (0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL    (0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL       (0x1 << 0)
-
-/* Define the bits in register CSCMR1 */
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET         (30)
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK           (0x3 << 30)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET         (28)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK           (0x3 << 28)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET          (26)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL                 (0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET             (24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK               (0x3 << 24)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET           (22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK             (0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET     (20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK       (0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL                  (0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL       (0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL                  (0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET     (16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK       (0x3 << 16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET      (16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK                (0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET             (14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK               (0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET             (12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK               (0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL                    (0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL                    (0x1 << 10)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET          (8)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK            (0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL                     (0x1 << 7)
-#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL                 (0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET             (4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK               (0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET            (2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK              (0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL            (0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL            (0x1)
-
-/* Define the bits in register CSCMR2 */
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)            (26+n*3)
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)              (0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET                (24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK          (0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET                (22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK          (0x3 << 22)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET              (20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK                        (0x3 << 20)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET             (18)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK               (0x3 << 18)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET             (16)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK               (0x3 << 16)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET            (14)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK              (0x3 << 14)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET             (12)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK               (0x3 << 12)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET              (10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK                        (0x3 << 10)
-#define MXC_CCM_CSCMR2_SLIMBUS_COM                     (0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET          (6)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK            (0x7 << 6)
-#define MXC_CCM_CSCMR2_SPDIF1_COM                      (1 << 5)
-#define MXC_CCM_CSCMR2_SPDIF0_COM                      (1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET           (2)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK             (0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET           (0)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK             (0x3)
-
-/* Define the bits in register CSCDR1 */
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET    (22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK      (0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET    (19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK      (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET     (22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK       (0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET     (19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK       (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET    (16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK      (0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET             (14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK               (0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET    (11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK      (0x7 << 11)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET          (8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK            (0x7 << 8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET          (6)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK            (0x3 << 6)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET            (3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK              (0x7 << 3)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET            (0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK              (0x7)
-
-/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET                (22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK          (0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET                (16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK          (0x3F << 16)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET            (6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK              (0x7 << 6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET            (0)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK              (0x3F)
-
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET                (22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK          (0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET                (16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK          (0x3F << 16)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET            (6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK              (0x7 << 6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET            (0)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK              (0x3F)
-
-/* Define the bits in register CDCDR */
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET              (28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK                        (0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET           (25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK             (0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET           (19)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK             (0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET           (16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK             (0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET           (9)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK             (0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET               (6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK                 (0x7 << 6)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET              (3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK                        (0x7 << 3)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET              (0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK                        (0x7)
-
-/* Define the bits in register CHSCCDR */
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET            (12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK              (0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET            (6)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK              (0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET           (3)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK             (0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET           (0)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK             (0x7)
-
-/* Define the bits in register CSCDR2 */
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET            (25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK              (0x7 << 25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET            (19)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK              (0x3F << 19)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET             (16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK               (0x7 << 16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET             (9)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK               (0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET         (6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK               (0x7 << 6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET             (0)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK               (0x3F)
-
-/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET           (16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK             (0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET           (9)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK             (0x3F << 9)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET            (6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK              (0x7 << 6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET            (0)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK              (0x3F)
-
-/* Define the bits in register CSCDR4 */
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET       (16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK         (0x7 << 16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET       (9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK         (0x3F << 9)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET       (6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK         (0x7 << 6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET       (0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK         (0x3F)
-
-/* Define the bits in register CDHIPR */
-#define MXC_CCM_CDHIPR_ARM_PODF_BUSY                   (1 << 16)
-#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY             (1 << 8)
-#define MXC_CCM_CDHIPR_DDR_PODF_BUSY                   (1 << 7)
-#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY                        (1 << 6)
-#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY             (1 << 5)
-#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY       (1 << 4)
-#define MXC_CCM_CDHIPR_AHB_PODF_BUSY                   (1 << 3)
-#define MXC_CCM_CDHIPR_EMI_PODF_BUSY                   (1 << 2)
-#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY                 (1 << 1)
-#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY                 (1 << 0)
-
-/* Define the bits in register CDCR */
-#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER            (0x1 << 2)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET       (0)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK         (0x3)
-
-/* Define the bits in register CLPCR */
-#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS                (0x1 << 23)
-#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS                (0x1 << 22)
-#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS               (0x1 << 21)
-#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS               (0x1 << 25)
-#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS       (0x1 << 20)
-#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS                (0x1 << 19)
-#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS                (0x1 << 18)
-#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS       (0x1 << 17)
-#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS       (0x1 << 16)
-#define MXC_CCM_CLPCR_COSC_PWRDOWN             (0x1 << 11)
-#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET                (9)
-#define MXC_CCM_CLPCR_STBY_COUNT_MASK          (0x3 << 9)
-#define MXC_CCM_CLPCR_VSTBY                    (0x1 << 8)
-#define MXC_CCM_CLPCR_DIS_REF_OSC              (0x1 << 7)
-#define MXC_CCM_CLPCR_SBYOS                    (0x1 << 6)
-#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM       (0x1 << 5)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET      (3)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK                (0x3 << 3)
-#define MXC_CCM_CLPCR_LPM_OFFSET               (0)
-#define MXC_CCM_CLPCR_LPM_MASK                 (0x3)
-
-/* Define the bits in register CISR */
-#define MXC_CCM_CISR_ARM_PODF_LOADED                   (0x1 << 25)
-#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED       (0x1 << 21)
-#define MXC_CCM_CISR_AHB_PODF_LOADED                   (0x1 << 20)
-#define MXC_CCM_CISR_EMI_PODF_LOADED                   (0x1 << 19)
-#define MXC_CCM_CISR_AXI_B_PODF_LOADED                 (0x1 << 18)
-#define MXC_CCM_CISR_AXI_A_PODF_LOADED                 (0x1 << 17)
-#define MXC_CCM_CISR_DIVIDER_LOADED                    (0x1 << 16)
-#define MXC_CCM_CISR_COSC_READY                                (0x1 << 6)
-#define MXC_CCM_CISR_CKIH2_READY                       (0x1 << 5)
-#define MXC_CCM_CISR_CKIH_READY                                (0x1 << 4)
-#define MXC_CCM_CISR_FPM_READY                         (0x1 << 3)
-#define MXC_CCM_CISR_LRF_PLL3                          (0x1 << 2)
-#define MXC_CCM_CISR_LRF_PLL2                          (0x1 << 1)
-#define MXC_CCM_CISR_LRF_PLL1                          (0x1)
-
-/* Define the bits in register CIMR */
-#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED              (0x1 << 25)
-#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED  (0x1 << 21)
-#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED              (0x1 << 20)
-#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED            (0x1 << 19)
-#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED            (0x1 << 18)
-#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED            (0x1 << 17)
-#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED               (0x1 << 16)
-#define MXC_CCM_CIMR_MASK_COSC_READY                   (0x1 << 5)
-#define MXC_CCM_CIMR_MASK_CKIH_READY                   (0x1 << 4)
-#define MXC_CCM_CIMR_MASK_FPM_READY                    (0x1 << 3)
-#define MXC_CCM_CIMR_MASK_LRF_PLL3                     (0x1 << 2)
-#define MXC_CCM_CIMR_MASK_LRF_PLL2                     (0x1 << 1)
-#define MXC_CCM_CIMR_MASK_LRF_PLL1                     (0x1)
-
-/* Define the bits in register CCOSR */
-#define MXC_CCM_CCOSR_CKO2_EN_OFFSET                   (0x1 << 24)
-#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET                  (21)
-#define MXC_CCM_CCOSR_CKO2_DIV_MASK                    (0x7 << 21)
-#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET                  (16)
-#define MXC_CCM_CCOSR_CKO2_SEL_MASK                    (0x1F << 16)
-#define MXC_CCM_CCOSR_CKOL_EN                          (0x1 << 7)
-#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET                  (4)
-#define MXC_CCM_CCOSR_CKOL_DIV_MASK                    (0x7 << 4)
-#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET                  (0)
-#define MXC_CCM_CCOSR_CKOL_SEL_MASK                    (0xF)
-
-/* Define the bits in registers CGPR */
-#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE            (0x1 << 4)
-#define MXC_CCM_CGPR_FPM_SEL                           (0x1 << 3)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET           (0)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK             (0x7)
-
-/* Define the bits in registers CCGRx */
-#define MXC_CCM_CCGRx_CG_MASK                          0x3
-#define MXC_CCM_CCGRx_MOD_OFF                          0x0
-#define MXC_CCM_CCGRx_MOD_ON                           0x3
-#define MXC_CCM_CCGRx_MOD_IDLE                         0x1
-
-#define MXC_CCM_CCGRx_CG15_MASK                                (0x3 << 30)
-#define MXC_CCM_CCGRx_CG14_MASK                                (0x3 << 28)
-#define MXC_CCM_CCGRx_CG13_MASK                                (0x3 << 26)
-#define MXC_CCM_CCGRx_CG12_MASK                                (0x3 << 24)
-#define MXC_CCM_CCGRx_CG11_MASK                                (0x3 << 22)
-#define MXC_CCM_CCGRx_CG10_MASK                                (0x3 << 20)
-#define MXC_CCM_CCGRx_CG9_MASK                         (0x3 << 18)
-#define MXC_CCM_CCGRx_CG8_MASK                         (0x3 << 16)
-#define MXC_CCM_CCGRx_CG5_MASK                         (0x3 << 10)
-#define MXC_CCM_CCGRx_CG4_MASK                         (0x3 << 8)
-#define MXC_CCM_CCGRx_CG3_MASK                         (0x3 << 6)
-#define MXC_CCM_CCGRx_CG2_MASK                         (0x3 << 4)
-#define MXC_CCM_CCGRx_CG1_MASK                         (0x3 << 2)
-#define MXC_CCM_CCGRx_CG0_MASK                         (0x3 << 0)
-
-#define MXC_CCM_CCGRx_CG15_OFFSET                      30
-#define MXC_CCM_CCGRx_CG14_OFFSET                      28
-#define MXC_CCM_CCGRx_CG13_OFFSET                      26
-#define MXC_CCM_CCGRx_CG12_OFFSET                      24
-#define MXC_CCM_CCGRx_CG11_OFFSET                      22
-#define MXC_CCM_CCGRx_CG10_OFFSET                      20
-#define MXC_CCM_CCGRx_CG9_OFFSET                       18
-#define MXC_CCM_CCGRx_CG8_OFFSET                       16
-#define MXC_CCM_CCGRx_CG7_OFFSET                       14
-#define MXC_CCM_CCGRx_CG6_OFFSET                       12
-#define MXC_CCM_CCGRx_CG5_OFFSET                       10
-#define MXC_CCM_CCGRx_CG4_OFFSET                       8
-#define MXC_CCM_CCGRx_CG3_OFFSET                       6
-#define MXC_CCM_CCGRx_CG2_OFFSET                       4
-#define MXC_CCM_CCGRx_CG1_OFFSET                       2
-#define MXC_CCM_CCGRx_CG0_OFFSET                       0
-
-#define MXC_DPTC_LP_BASE       (MX51_GPC_BASE + 0x80)
-#define MXC_DPTC_GP_BASE       (MX51_GPC_BASE + 0x100)
-#define MXC_DVFS_CORE_BASE     (MX51_GPC_BASE + 0x180)
-#define MXC_DPTC_PER_BASE      (MX51_GPC_BASE + 0x1C0)
-#define MXC_PGC_IPU_BASE       (MX51_GPC_BASE + 0x220)
-#define MXC_PGC_VPU_BASE       (MX51_GPC_BASE + 0x240)
-#define MXC_PGC_GPU_BASE       (MX51_GPC_BASE + 0x260)
-#define MXC_SRPG_NEON_BASE     (MX51_GPC_BASE + 0x280)
-#define MXC_SRPG_ARM_BASE      (MX51_GPC_BASE + 0x2A0)
-#define MXC_SRPG_EMPGC0_BASE   (MX51_GPC_BASE + 0x2C0)
-#define MXC_SRPG_EMPGC1_BASE   (MX51_GPC_BASE + 0x2D0)
-#define MXC_SRPG_MEGAMIX_BASE  (MX51_GPC_BASE + 0x2E0)
-#define MXC_SRPG_EMI_BASE      (MX51_GPC_BASE + 0x300)
-
-/* CORTEXA8 platform */
-#define MXC_CORTEXA8_PLAT_PVID         (MX51_CORTEXA8_BASE + 0x0)
-#define MXC_CORTEXA8_PLAT_GPC          (MX51_CORTEXA8_BASE + 0x4)
-#define MXC_CORTEXA8_PLAT_PIC          (MX51_CORTEXA8_BASE + 0x8)
-#define MXC_CORTEXA8_PLAT_LPC          (MX51_CORTEXA8_BASE + 0xC)
-#define MXC_CORTEXA8_PLAT_NEON_LPC     (MX51_CORTEXA8_BASE + 0x10)
-#define MXC_CORTEXA8_PLAT_ICGC         (MX51_CORTEXA8_BASE + 0x14)
-#define MXC_CORTEXA8_PLAT_AMC          (MX51_CORTEXA8_BASE + 0x18)
-#define MXC_CORTEXA8_PLAT_NMC          (MX51_CORTEXA8_BASE + 0x20)
-#define MXC_CORTEXA8_PLAT_NMS          (MX51_CORTEXA8_BASE + 0x24)
-
-/* DVFS CORE */
-#define MXC_DVFSTHRS           (MXC_DVFS_CORE_BASE + 0x00)
-#define MXC_DVFSCOUN           (MXC_DVFS_CORE_BASE + 0x04)
-#define MXC_DVFSSIG1           (MXC_DVFS_CORE_BASE + 0x08)
-#define MXC_DVFSSIG0           (MXC_DVFS_CORE_BASE + 0x0C)
-#define MXC_DVFSGPC0           (MXC_DVFS_CORE_BASE + 0x10)
-#define MXC_DVFSGPC1           (MXC_DVFS_CORE_BASE + 0x14)
-#define MXC_DVFSGPBT           (MXC_DVFS_CORE_BASE + 0x18)
-#define MXC_DVFSEMAC           (MXC_DVFS_CORE_BASE + 0x1C)
-#define MXC_DVFSCNTR           (MXC_DVFS_CORE_BASE + 0x20)
-#define MXC_DVFSLTR0_0         (MXC_DVFS_CORE_BASE + 0x24)
-#define MXC_DVFSLTR0_1         (MXC_DVFS_CORE_BASE + 0x28)
-#define MXC_DVFSLTR1_0         (MXC_DVFS_CORE_BASE + 0x2C)
-#define MXC_DVFSLTR1_1         (MXC_DVFS_CORE_BASE + 0x30)
-#define MXC_DVFSPT0            (MXC_DVFS_CORE_BASE + 0x34)
-#define MXC_DVFSPT1            (MXC_DVFS_CORE_BASE + 0x38)
-#define MXC_DVFSPT2            (MXC_DVFS_CORE_BASE + 0x3C)
-#define MXC_DVFSPT3            (MXC_DVFS_CORE_BASE + 0x40)
-
-/* GPC */
-#define MXC_GPC_CNTR           (MX51_GPC_BASE + 0x0)
-#define MXC_GPC_PGR            (MX51_GPC_BASE + 0x4)
-#define MXC_GPC_VCR            (MX51_GPC_BASE + 0x8)
-#define MXC_GPC_ALL_PU         (MX51_GPC_BASE + 0xC)
-#define MXC_GPC_NEON           (MX51_GPC_BASE + 0x10)
-#define MXC_GPC_PGR_ARMPG_OFFSET       8
-#define MXC_GPC_PGR_ARMPG_MASK         (3 << 8)
-
-/* PGC */
-#define MXC_PGC_IPU_PGCR       (MXC_PGC_IPU_BASE + 0x0)
-#define MXC_PGC_IPU_PGSR       (MXC_PGC_IPU_BASE + 0xC)
-#define MXC_PGC_VPU_PGCR       (MXC_PGC_VPU_BASE + 0x0)
-#define MXC_PGC_VPU_PGSR       (MXC_PGC_VPU_BASE + 0xC)
-#define MXC_PGC_GPU_PGCR       (MXC_PGC_GPU_BASE + 0x0)
-#define MXC_PGC_GPU_PGSR       (MXC_PGC_GPU_BASE + 0xC)
-
-#define MXC_PGCR_PCR           1
-#define MXC_SRPGCR_PCR         1
-#define MXC_EMPGCR_PCR         1
-#define MXC_PGSR_PSR           1
-
-
-#define MXC_CORTEXA8_PLAT_LPC_DSM      (1 << 0)
-#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM  (1 << 1)
-
-/* SRPG */
-#define MXC_SRPG_NEON_SRPGCR   (MXC_SRPG_NEON_BASE + 0x0)
-#define MXC_SRPG_NEON_PUPSCR   (MXC_SRPG_NEON_BASE + 0x4)
-#define MXC_SRPG_NEON_PDNSCR   (MXC_SRPG_NEON_BASE + 0x8)
-
-#define MXC_SRPG_ARM_SRPGCR    (MXC_SRPG_ARM_BASE + 0x0)
-#define MXC_SRPG_ARM_PUPSCR    (MXC_SRPG_ARM_BASE + 0x4)
-#define MXC_SRPG_ARM_PDNSCR    (MXC_SRPG_ARM_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0)
-#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4)
-#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0)
-#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4)
-#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8)
-
-#define MXC_SRPG_MEGAMIX_SRPGCR                (MXC_SRPG_MEGAMIX_BASE + 0x0)
-#define MXC_SRPG_MEGAMIX_PUPSCR                (MXC_SRPG_MEGAMIX_BASE + 0x4)
-#define MXC_SRPG_MEGAMIX_PDNSCR                (MXC_SRPG_MEGAMIX_BASE + 0x8)
-
-#define MXC_SRPGC_EMI_SRPGCR   (MXC_SRPGC_EMI_BASE + 0x0)
-#define MXC_SRPGC_EMI_PUPSCR   (MXC_SRPGC_EMI_BASE + 0x4)
-#define MXC_SRPGC_EMI_PDNSCR   (MXC_SRPGC_EMI_BASE + 0x8)
-
-#endif                         /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx5/devices-imx50.h b/arch/arm/mach-mx5/devices-imx50.h
deleted file mode 100644 (file)
index 7216667..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010 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 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 <mach/mx50.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
-#define imx50_add_imx_uart(id, pdata)  \
-       imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
-
-extern const struct imx_fec_data imx50_fec_data;
-#define imx50_add_fec(pdata)   \
-       imx_add_fec(&imx50_fec_data, pdata)
-
-extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
-#define imx50_add_imx_i2c(id, pdata)   \
-       imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
deleted file mode 100644 (file)
index af488bc..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx51.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx51_fec_data;
-#define imx51_add_fec(pdata)   \
-       imx_add_fec(&imx51_fec_data, pdata)
-
-extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
-#define imx51_add_fsl_usb2_udc(pdata)  \
-       imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
-
-extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
-#define imx51_add_imx_i2c(id, pdata)   \
-       imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
-#define imx51_add_hsi2c(pdata) \
-       imx51_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
-#define imx51_add_imx_ssi(id, pdata)   \
-       imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
-#define imx51_add_imx_uart(id, pdata)  \
-       imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
-
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
-#define imx51_add_mxc_ehci_otg(pdata)  \
-       imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
-#define imx51_add_mxc_ehci_hs(id, pdata)       \
-       imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
-
-extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
-#define imx51_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
-#define imx51_add_sdhci_esdhc_imx(id, pdata)   \
-       imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx51_cspi_data;
-#define imx51_add_cspi(pdata)  \
-       imx_add_spi_imx(&imx51_cspi_data, pdata)
-
-extern const struct imx_spi_imx_data imx51_ecspi_data[];
-#define imx51_add_ecspi(id, pdata)     \
-       imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id, pdata)  \
-       imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
-
-extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
-#define imx51_add_mxc_pwm(id)  \
-       imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
-
-extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
-#define imx51_add_imx_keypad(pdata)    \
-       imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx51_pata_imx_data;
-#define imx51_add_pata_imx() \
-       imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
deleted file mode 100644 (file)
index 6e1e5d1..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
- *
- * 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 <mach/mx53.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx53_fec_data;
-#define imx53_add_fec(pdata)   \
-       imx_add_fec(&imx53_fec_data, pdata)
-
-extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
-#define imx53_add_imx_uart(id, pdata)  \
-       imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
-
-
-extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
-#define imx53_add_imx_i2c(id, pdata)   \
-       imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
-#define imx53_add_sdhci_esdhc_imx(id, pdata)   \
-       imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx53_ecspi_data[];
-#define imx53_add_ecspi(id, pdata)     \
-       imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
-#define imx53_add_imx2_wdt(id, pdata)  \
-       imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
-
-extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
-#define imx53_add_imx_ssi(id, pdata)   \
-       imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
-#define imx53_add_imx_keypad(pdata)    \
-       imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx53_pata_imx_data;
-#define imx53_add_pata_imx() \
-       imx_add_pata_imx(&imx53_pata_imx_data)
-
-extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-mx5/efika.h b/arch/arm/mach-mx5/efika.h
deleted file mode 100644 (file)
index 014aa98..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _EFIKA_H
-#define _EFIKA_H
-
-#define EFIKA_WLAN_EN          IMX_GPIO_NR(2, 16)
-#define EFIKA_WLAN_RESET       IMX_GPIO_NR(2, 10)
-#define EFIKA_USB_PHY_RESET    IMX_GPIO_NR(2, 9)
-
-void __init efika_board_common_init(void);
-
-#endif
diff --git a/arch/arm/mach-mx5/ehci.c b/arch/arm/mach-mx5/ehci.c
deleted file mode 100644 (file)
index c17fa13..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, 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.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
-
-#define MXC_OTG_OFFSET                 0
-#define MXC_H1_OFFSET                  0x200
-#define MXC_H2_OFFSET                  0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT         (1 << 27)       /* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT          (1 << 24)       /* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT         (1 << 12)       /* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT         (1 << 11)       /* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)               /* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT     (1 << 8)        /* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_DIS_BIT              (1 << 5)        /* UH1 Disable Overcurrent Event */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT         (1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT         (1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT          (1 << 4)
-
-#define MXC_USBCMD_OFFSET              0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
-
-int mx51_initialize_usb_hw(int port, unsigned int flags)
-{
-       unsigned int v;
-       void __iomem *usb_base;
-       void __iomem *usbotg_base;
-       void __iomem *usbother_base;
-       int ret = 0;
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base) {
-               printk(KERN_ERR "%s(): ioremap failed\n", __func__);
-               return -ENOMEM;
-       }
-
-       switch (port) {
-       case 0: /* OTG port */
-               usbotg_base = usb_base + MXC_OTG_OFFSET;
-               break;
-       case 1: /* Host 1 port */
-               usbotg_base = usb_base + MXC_H1_OFFSET;
-               break;
-       case 2: /* Host 2 port */
-               usbotg_base = usb_base + MXC_H2_OFFSET;
-               break;
-       default:
-               printk(KERN_ERR"%s no such port %d\n", __func__, port);
-               ret = -ENOENT;
-               goto error;
-       }
-       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-       switch (port) {
-       case 0: /*OTG port */
-               if (flags & MXC_EHCI_INTERNAL_PHY) {
-                       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-                       if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-                               /* OC/USBPWR is not used */
-                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-                       } else {
-                               /* OC/USBPWR is used */
-                               v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
-                       }
-                       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-                       v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-                       if (flags & MXC_EHCI_WAKEUP_ENABLED)
-                               v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
-                       else
-                               v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
-                       if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                               v |= MXC_OTG_UCTRL_OPM_BIT;
-                       else
-                               v &= ~MXC_OTG_UCTRL_OPM_BIT;
-                       __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-               }
-               break;
-       case 1: /* Host 1 */
-               /*Host ULPI */
-               v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-               if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-                       /* HOST1 wakeup/ULPI intr enable */
-                       v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-               } else {
-                       /* HOST1 wakeup/ULPI intr disable */
-                       v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-               }
-
-               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-               else
-                       v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-               __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
-               v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
-               else
-                       v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
-               __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-               v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
-               if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
-                       /* Interrupt Threshold Control:Immediate (no threshold) */
-                       v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
-               __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
-               break;
-       case 2: /* Host 2 ULPI */
-               v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
-               if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-                       /* HOST1 wakeup/ULPI intr enable */
-                       v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-               } else {
-                       /* HOST1 wakeup/ULPI intr disable */
-                       v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-               }
-
-               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-               else
-                       v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-               __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
-               break;
-       }
-
-error:
-       iounmap(usb_base);
-       return ret;
-}
-
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
deleted file mode 100644 (file)
index a6a3ab8..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/leds.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/mach/arch.h>
-
-#include "devices-imx51.h"
-
-#define MBIMX51_TSC2007_GPIO   IMX_GPIO_NR(3, 30)
-#define MBIMX51_LED0           IMX_GPIO_NR(3, 5)
-#define MBIMX51_LED1           IMX_GPIO_NR(3, 6)
-#define MBIMX51_LED2           IMX_GPIO_NR(3, 7)
-#define MBIMX51_LED3           IMX_GPIO_NR(3, 8)
-
-static const struct gpio_led mbimx51_leds[] __initconst = {
-       {
-               .name                   = "led0",
-               .default_trigger        = "heartbeat",
-               .active_low             = 1,
-               .gpio                   = MBIMX51_LED0,
-       },
-       {
-               .name                   = "led1",
-               .default_trigger        = "nand-disk",
-               .active_low             = 1,
-               .gpio                   = MBIMX51_LED1,
-       },
-       {
-               .name                   = "led2",
-               .default_trigger        = "mmc0",
-               .active_low             = 1,
-               .gpio                   = MBIMX51_LED2,
-       },
-       {
-               .name                   = "led3",
-               .default_trigger        = "default-on",
-               .active_low             = 1,
-               .gpio                   = MBIMX51_LED3,
-       },
-};
-
-static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
-       .leds           = mbimx51_leds,
-       .num_leds       = ARRAY_SIZE(mbimx51_leds),
-};
-
-static iomux_v3_cfg_t mbimx51_pads[] = {
-       /* UART2 */
-       MX51_PAD_UART2_RXD__UART2_RXD,
-       MX51_PAD_UART2_TXD__UART2_TXD,
-
-       /* UART3 */
-       MX51_PAD_UART3_RXD__UART3_RXD,
-       MX51_PAD_UART3_TXD__UART3_TXD,
-       MX51_PAD_KEY_COL4__UART3_RTS,
-       MX51_PAD_KEY_COL5__UART3_CTS,
-
-       /* TSC2007 IRQ */
-       MX51_PAD_NANDF_D10__GPIO3_30,
-
-       /* LEDS */
-       MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
-       MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
-       MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
-       MX51_PAD_DISPB2_SER_RS__GPIO3_8,
-
-       /* KPP */
-       MX51_PAD_KEY_ROW0__KEY_ROW0,
-       MX51_PAD_KEY_ROW1__KEY_ROW1,
-       MX51_PAD_KEY_ROW2__KEY_ROW2,
-       MX51_PAD_KEY_ROW3__KEY_ROW3,
-       MX51_PAD_KEY_COL0__KEY_COL0,
-       MX51_PAD_KEY_COL1__KEY_COL1,
-       MX51_PAD_KEY_COL2__KEY_COL2,
-       MX51_PAD_KEY_COL3__KEY_COL3,
-
-       /* SD 1 */
-       MX51_PAD_SD1_CMD__SD1_CMD,
-       MX51_PAD_SD1_CLK__SD1_CLK,
-       MX51_PAD_SD1_DATA0__SD1_DATA0,
-       MX51_PAD_SD1_DATA1__SD1_DATA1,
-       MX51_PAD_SD1_DATA2__SD1_DATA2,
-       MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-       /* SD 2 */
-       MX51_PAD_SD2_CMD__SD2_CMD,
-       MX51_PAD_SD2_CLK__SD2_CLK,
-       MX51_PAD_SD2_DATA0__SD2_DATA0,
-       MX51_PAD_SD2_DATA1__SD2_DATA1,
-       MX51_PAD_SD2_DATA2__SD2_DATA2,
-       MX51_PAD_SD2_DATA3__SD2_DATA3,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mbimx51_keymap[] = {
-       KEY(0, 0, KEY_1),
-       KEY(0, 1, KEY_2),
-       KEY(0, 2, KEY_3),
-       KEY(0, 3, KEY_UP),
-
-       KEY(1, 0, KEY_4),
-       KEY(1, 1, KEY_5),
-       KEY(1, 2, KEY_6),
-       KEY(1, 3, KEY_LEFT),
-
-       KEY(2, 0, KEY_7),
-       KEY(2, 1, KEY_8),
-       KEY(2, 2, KEY_9),
-       KEY(2, 3, KEY_RIGHT),
-
-       KEY(3, 0, KEY_0),
-       KEY(3, 1, KEY_DOWN),
-       KEY(3, 2, KEY_ESC),
-       KEY(3, 3, KEY_ENTER),
-};
-
-static const struct matrix_keymap_data mbimx51_map_data __initconst = {
-       .keymap         = mbimx51_keymap,
-       .keymap_size    = ARRAY_SIZE(mbimx51_keymap),
-};
-
-static int tsc2007_get_pendown_state(void)
-{
-       return !gpio_get_value(MBIMX51_TSC2007_GPIO);
-}
-
-struct tsc2007_platform_data tsc2007_data = {
-       .model = 2007,
-       .x_plate_ohms = 180,
-       .get_pendown_state = tsc2007_get_pendown_state,
-};
-
-static struct i2c_board_info mbimx51_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("tsc2007", 0x49),
-               .irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
-               .platform_data = &tsc2007_data,
-       }, {
-               I2C_BOARD_INFO("tlv320aic23", 0x1a),
-       },
-};
-
-/*
- * baseboard initialization.
- */
-void __init eukrea_mbimx51_baseboard_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
-                                       ARRAY_SIZE(mbimx51_pads));
-
-       imx51_add_imx_uart(1, NULL);
-       imx51_add_imx_uart(2, &uart_pdata);
-
-       gpio_request(MBIMX51_LED0, "LED0");
-       gpio_direction_output(MBIMX51_LED0, 1);
-       gpio_free(MBIMX51_LED0);
-       gpio_request(MBIMX51_LED1, "LED1");
-       gpio_direction_output(MBIMX51_LED1, 1);
-       gpio_free(MBIMX51_LED1);
-       gpio_request(MBIMX51_LED2, "LED2");
-       gpio_direction_output(MBIMX51_LED2, 1);
-       gpio_free(MBIMX51_LED2);
-       gpio_request(MBIMX51_LED3, "LED3");
-       gpio_direction_output(MBIMX51_LED3, 1);
-       gpio_free(MBIMX51_LED3);
-
-       gpio_led_register_device(-1, &mbimx51_leds_info);
-
-       imx51_add_imx_keypad(&mbimx51_map_data);
-
-       gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
-       gpio_direction_input(MBIMX51_TSC2007_GPIO);
-       irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
-                                       IRQF_TRIGGER_FALLING);
-       i2c_register_board_info(1, mbimx51_i2c_devices,
-                               ARRAY_SIZE(mbimx51_i2c_devices));
-
-       imx51_add_sdhci_esdhc_imx(0, NULL);
-       imx51_add_sdhci_esdhc_imx(1, NULL);
-}
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
deleted file mode 100644 (file)
index d817fc8..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2010 Eric Benard - eric@eukrea.com
- *
- * Based on pcm970-baseboard.c which is :
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/audmux.h>
-
-#include "devices-imx51.h"
-
-static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
-       /* LED */
-       MX51_PAD_NANDF_D10__GPIO3_30,
-       /* SWITCH */
-       NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
-                       PAD_CTL_PKE | PAD_CTL_SRE_FAST |
-                       PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-       /* UART2 */
-       MX51_PAD_UART2_RXD__UART2_RXD,
-       MX51_PAD_UART2_TXD__UART2_TXD,
-       /* UART 3 */
-       MX51_PAD_UART3_RXD__UART3_RXD,
-       MX51_PAD_UART3_TXD__UART3_TXD,
-       MX51_PAD_KEY_COL4__UART3_RTS,
-       MX51_PAD_KEY_COL5__UART3_CTS,
-       /* SD */
-       MX51_PAD_SD1_CMD__SD1_CMD,
-       MX51_PAD_SD1_CLK__SD1_CLK,
-       MX51_PAD_SD1_DATA0__SD1_DATA0,
-       MX51_PAD_SD1_DATA1__SD1_DATA1,
-       MX51_PAD_SD1_DATA2__SD1_DATA2,
-       MX51_PAD_SD1_DATA3__SD1_DATA3,
-       /* SD1 CD */
-       NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
-                       PAD_CTL_PKE | PAD_CTL_SRE_FAST |
-                       PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-};
-
-#define GPIO_LED1      IMX_GPIO_NR(3, 30)
-#define GPIO_SWITCH1   IMX_GPIO_NR(3, 31)
-
-static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
-       {
-               .name                   = "led1",
-               .default_trigger        = "heartbeat",
-               .active_low             = 1,
-               .gpio                   = GPIO_LED1,
-       },
-};
-
-static const struct gpio_led_platform_data
-               eukrea_mbimxsd_led_info __initconst = {
-       .leds           = eukrea_mbimxsd_leds,
-       .num_leds       = ARRAY_SIZE(eukrea_mbimxsd_leds),
-};
-
-static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
-       {
-               .gpio           = GPIO_SWITCH1,
-               .code           = BTN_0,
-               .desc           = "BP1",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-};
-
-static const struct gpio_keys_platform_data
-               eukrea_mbimxsd_button_data __initconst = {
-       .buttons        = eukrea_mbimxsd_gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("tlv320aic23", 0x1a),
-       },
-};
-
-/*
- * system init for baseboard usage. Will be called by cpuimx51sd init.
- *
- * Add platform devices present on this baseboard and init
- * them from CPU side as far as required to use them later on
- */
-void __init eukrea_mbimxsd51_baseboard_init(void)
-{
-       if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
-                       ARRAY_SIZE(eukrea_mbimxsd_pads)))
-               printk(KERN_ERR "error setting mbimxsd pads !\n");
-
-       imx51_add_imx_uart(1, NULL);
-       imx51_add_imx_uart(2, &uart_pdata);
-
-       imx51_add_sdhci_esdhc_imx(0, NULL);
-
-       gpio_request(GPIO_LED1, "LED1");
-       gpio_direction_output(GPIO_LED1, 1);
-       gpio_free(GPIO_LED1);
-
-       gpio_request(GPIO_SWITCH1, "SWITCH1");
-       gpio_direction_input(GPIO_SWITCH1);
-       gpio_free(GPIO_SWITCH1);
-
-       i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
-                               ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
-
-       gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
-       imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
-}
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
deleted file mode 100644 (file)
index e6bad17..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx51.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-       { /* sentinel */ }
-};
-
-static int __init imx51_tzic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_simple(np, 0);
-       return 0;
-}
-
-static int __init imx51_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_simple(np, gpio_irq_base);
-
-       return 0;
-}
-
-static const struct of_device_id imx51_irq_match[] __initconst = {
-       { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
-       { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
-static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
-       { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
-       { /* sentinel */ }
-};
-
-static void __init imx51_dt_init(void)
-{
-       struct device_node *node;
-       const struct of_device_id *of_id;
-       void (*func)(void);
-
-       of_irq_init(imx51_irq_match);
-
-       node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
-       if (node) {
-               of_id = of_match_node(imx51_iomuxc_of_match, node);
-               func = of_id->data;
-               func();
-               of_node_put(node);
-       }
-
-       of_platform_populate(NULL, of_default_bus_match_table,
-                            imx51_auxdata_lookup, NULL);
-}
-
-static void __init imx51_timer_init(void)
-{
-       mx51_clocks_init_dt();
-}
-
-static struct sys_timer imx51_timer = {
-       .init = imx51_timer_init,
-};
-
-static const char *imx51_dt_board_compat[] __initdata = {
-       "fsl,imx51-babbage",
-       NULL
-};
-
-DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
-       .map_io         = mx51_map_io,
-       .init_early     = imx51_init_early,
-       .init_irq       = mx51_init_irq,
-       .handle_irq     = imx51_handle_irq,
-       .timer          = &imx51_timer,
-       .init_machine   = imx51_dt_init,
-       .dt_compat      = imx51_dt_board_compat,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c
deleted file mode 100644 (file)
index 05ebb3e..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx53.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-       { /* sentinel */ }
-};
-
-static int __init imx53_tzic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_simple(np, 0);
-       return 0;
-}
-
-static int __init imx53_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_simple(np, gpio_irq_base);
-
-       return 0;
-}
-
-static const struct of_device_id imx53_irq_match[] __initconst = {
-       { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
-       { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
-static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
-       { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
-       { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
-       { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
-       { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
-       { /* sentinel */ }
-};
-
-static void __init imx53_dt_init(void)
-{
-       struct device_node *node;
-       const struct of_device_id *of_id;
-       void (*func)(void);
-
-       of_irq_init(imx53_irq_match);
-
-       node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
-       if (node) {
-               of_id = of_match_node(imx53_iomuxc_of_match, node);
-               func = of_id->data;
-               func();
-               of_node_put(node);
-       }
-
-       of_platform_populate(NULL, of_default_bus_match_table,
-                            imx53_auxdata_lookup, NULL);
-}
-
-static void __init imx53_timer_init(void)
-{
-       mx53_clocks_init_dt();
-}
-
-static struct sys_timer imx53_timer = {
-       .init = imx53_timer_init,
-};
-
-static const char *imx53_dt_board_compat[] __initdata = {
-       "fsl,imx53-ard",
-       "fsl,imx53-evk",
-       "fsl,imx53-qsb",
-       "fsl,imx53-smd",
-       NULL
-};
-
-DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
-       .map_io         = mx53_map_io,
-       .init_early     = imx53_init_early,
-       .init_irq       = mx53_init_irq,
-       .handle_irq     = imx53_handle_irq,
-       .timer          = &imx53_timer,
-       .init_machine   = imx53_dt_init,
-       .dt_compat      = imx53_dt_board_compat,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
deleted file mode 100644 (file)
index bc17dfe..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/iomux-v3.h>
-
-static struct clk *gpc_dvfs_clk;
-
-static void imx5_idle(void)
-{
-       if (!need_resched()) {
-               /* gpc clock is needed for SRPG */
-               if (gpc_dvfs_clk == NULL) {
-                       gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-                       if (IS_ERR(gpc_dvfs_clk))
-                               goto err0;
-               }
-               clk_enable(gpc_dvfs_clk);
-               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-               if (tzic_enable_wake())
-                       goto err1;
-               cpu_do_idle();
-err1:
-               clk_disable(gpc_dvfs_clk);
-       }
-err0:
-       local_irq_enable();
-}
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
-       imx_map_entry(MX50, TZIC, MT_DEVICE),
-       imx_map_entry(MX50, SPBA0, MT_DEVICE),
-       imx_map_entry(MX50, AIPS1, MT_DEVICE),
-       imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX51 memory map.
- */
-static struct map_desc mx51_io_desc[] __initdata = {
-       imx_map_entry(MX51, TZIC, MT_DEVICE),
-       imx_map_entry(MX51, IRAM, MT_DEVICE),
-       imx_map_entry(MX51, AIPS1, MT_DEVICE),
-       imx_map_entry(MX51, SPBA0, MT_DEVICE),
-       imx_map_entry(MX51, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX53 memory map.
- */
-static struct map_desc mx53_io_desc[] __initdata = {
-       imx_map_entry(MX53, TZIC, MT_DEVICE),
-       imx_map_entry(MX53, AIPS1, MT_DEVICE),
-       imx_map_entry(MX53, SPBA0, MT_DEVICE),
-       imx_map_entry(MX53, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx50_map_io(void)
-{
-       iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
-void __init mx51_map_io(void)
-{
-       iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
-}
-
-void __init mx53_map_io(void)
-{
-       iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
-}
-
-void __init imx50_init_early(void)
-{
-       mxc_set_cpu_type(MXC_CPU_MX50);
-       mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
-       mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
-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));
-       pm_idle = imx5_idle;
-}
-
-void __init imx53_init_early(void)
-{
-       mxc_set_cpu_type(MXC_CPU_MX53);
-       mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
-       mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
-}
-
-void __init mx50_init_irq(void)
-{
-       tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init mx51_init_irq(void)
-{
-       tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
-}
-
-void __init mx53_init_irq(void)
-{
-       tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
-       .ap_2_ap_addr = 642,
-       .uart_2_mcu_addr = 817,
-       .mcu_2_app_addr = 747,
-       .mcu_2_shp_addr = 961,
-       .ata_2_mcu_addr = 1473,
-       .mcu_2_ata_addr = 1392,
-       .app_2_per_addr = 1033,
-       .app_2_mcu_addr = 683,
-       .shp_2_per_addr = 1251,
-       .shp_2_mcu_addr = 892,
-};
-
-static struct sdma_platform_data imx51_sdma_pdata __initdata = {
-       .fw_name = "sdma-imx51.bin",
-       .script_addrs = &imx51_sdma_script,
-};
-
-static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
-       .ap_2_ap_addr = 642,
-       .app_2_mcu_addr = 683,
-       .mcu_2_app_addr = 747,
-       .uart_2_mcu_addr = 817,
-       .shp_2_mcu_addr = 891,
-       .mcu_2_shp_addr = 960,
-       .uartsh_2_mcu_addr = 1032,
-       .spdif_2_mcu_addr = 1100,
-       .mcu_2_spdif_addr = 1134,
-       .firi_2_mcu_addr = 1193,
-       .mcu_2_firi_addr = 1290,
-};
-
-static struct sdma_platform_data imx53_sdma_pdata __initdata = {
-       .fw_name = "sdma-imx53.bin",
-       .script_addrs = &imx53_sdma_script,
-};
-
-void __init imx50_soc_init(void)
-{
-       /* i.mx50 has the i.mx31 type gpio */
-       mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
-       mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
-       mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
-       mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
-       mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
-       mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
-
-void __init imx51_soc_init(void)
-{
-       /* i.mx51 has the i.mx31 type gpio */
-       mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
-       mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
-       mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
-       mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
-
-       /* i.mx51 has the i.mx35 type sdma */
-       imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
-}
-
-void __init imx53_soc_init(void)
-{
-       /* i.mx53 has the i.mx31 type gpio */
-       mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
-       mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
-       mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
-       mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
-       mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
-       mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
-       mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
-
-       /* i.mx53 has the i.mx35 type sdma */
-       imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
-}
diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c
deleted file mode 100644 (file)
index ec6ca91..0000000
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-#include "cpu_op-mx51.h"
-
-#define MX51_USB_CTRL_1_OFFSET          0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
-#define        MX51_USB_PLL_DIV_19_2_MHZ       0x01
-
-#define EFIKAMX_USB_HUB_RESET  IMX_GPIO_NR(1, 5)
-#define EFIKAMX_USBH1_STP      IMX_GPIO_NR(1, 27)
-
-#define EFIKAMX_SPI_CS0                IMX_GPIO_NR(4, 24)
-#define EFIKAMX_SPI_CS1                IMX_GPIO_NR(4, 25)
-
-#define EFIKAMX_PMIC           IMX_GPIO_NR(1, 6)
-
-static iomux_v3_cfg_t mx51efika_pads[] = {
-       /* UART1 */
-       MX51_PAD_UART1_RXD__UART1_RXD,
-       MX51_PAD_UART1_TXD__UART1_TXD,
-       MX51_PAD_UART1_RTS__UART1_RTS,
-       MX51_PAD_UART1_CTS__UART1_CTS,
-
-       /* SD 1 */
-       MX51_PAD_SD1_CMD__SD1_CMD,
-       MX51_PAD_SD1_CLK__SD1_CLK,
-       MX51_PAD_SD1_DATA0__SD1_DATA0,
-       MX51_PAD_SD1_DATA1__SD1_DATA1,
-       MX51_PAD_SD1_DATA2__SD1_DATA2,
-       MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-       /* SD 2 */
-       MX51_PAD_SD2_CMD__SD2_CMD,
-       MX51_PAD_SD2_CLK__SD2_CLK,
-       MX51_PAD_SD2_DATA0__SD2_DATA0,
-       MX51_PAD_SD2_DATA1__SD2_DATA1,
-       MX51_PAD_SD2_DATA2__SD2_DATA2,
-       MX51_PAD_SD2_DATA3__SD2_DATA3,
-
-       /* SD/MMC WP/CD */
-       MX51_PAD_GPIO1_0__SD1_CD,
-       MX51_PAD_GPIO1_1__SD1_WP,
-       MX51_PAD_GPIO1_7__SD2_WP,
-       MX51_PAD_GPIO1_8__SD2_CD,
-
-       /* spi */
-       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-       MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-       MX51_PAD_CSPI1_SS0__GPIO4_24,
-       MX51_PAD_CSPI1_SS1__GPIO4_25,
-       MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
-       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-       MX51_PAD_GPIO1_6__GPIO1_6,
-
-       /* USB HOST1 */
-       MX51_PAD_USBH1_CLK__USBH1_CLK,
-       MX51_PAD_USBH1_DIR__USBH1_DIR,
-       MX51_PAD_USBH1_NXT__USBH1_NXT,
-       MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-       MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-       MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-       MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-       MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-       MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-       MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-       MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
-       /* USB HUB RESET */
-       MX51_PAD_GPIO1_5__GPIO1_5,
-
-       /* WLAN */
-       MX51_PAD_EIM_A22__GPIO2_16,
-       MX51_PAD_EIM_A16__GPIO2_10,
-
-       /* USB PHY RESET */
-       MX51_PAD_EIM_D27__GPIO2_9,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
- * be different for other Freescale SoCs, thus a common bitmask is not
- * possible and cannot get place in /plat-mxc/ehci.c.
- */
-static int initialize_otg_port(struct platform_device *pdev)
-{
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *usbother_base;
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       if (!usb_base)
-               return -ENOMEM;
-       usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-       /* Set the PHY clock to 19.2MHz */
-       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-       v |= MX51_USB_PLL_DIV_19_2_MHZ;
-       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-       iounmap(usb_base);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-       .init   = initialize_otg_port,
-       .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-       iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-       iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-       u32 v;
-       void __iomem *usb_base;
-       void __iomem *socregs_base;
-
-       mxc_iomux_v3_setup_pad(usbh1gpio);
-       gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
-       gpio_direction_output(EFIKAMX_USBH1_STP, 0);
-       msleep(1);
-       gpio_set_value(EFIKAMX_USBH1_STP, 1);
-       msleep(1);
-
-       usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-       socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-       /* The clock for the USBH1 ULPI port will come externally */
-       /* from the PHY. */
-       v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
-       __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
-                       socregs_base + MX51_USB_CTRL_1_OFFSET);
-
-       iounmap(usb_base);
-
-       gpio_free(EFIKAMX_USBH1_STP);
-       mxc_iomux_v3_setup_pad(usbh1stp);
-
-       mdelay(10);
-
-       return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh1_config __initdata = {
-       .init   = initialize_usbh1_port,
-       .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void mx51_efika_hubreset(void)
-{
-       gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
-       gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
-       msleep(1);
-       gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
-       msleep(1);
-       gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
-}
-
-static void __init mx51_efika_usb(void)
-{
-       mx51_efika_hubreset();
-
-       /* pulling it low, means no USB at all... */
-       gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
-       gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
-       msleep(1);
-       gpio_set_value(EFIKA_USB_PHY_RESET, 1);
-
-       usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
-                       ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-
-       imx51_add_mxc_ehci_otg(&dr_utmi_config);
-       if (usbh1_config.otg)
-               imx51_add_mxc_ehci_hs(1, &usbh1_config);
-}
-
-static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
-       {
-        .name = "u-boot",
-        .offset = 0,
-        .size = SZ_256K,
-       },
-       {
-         .name = "config",
-         .offset = MTDPART_OFS_APPEND,
-         .size = SZ_64K,
-       },
-};
-
-static struct flash_platform_data mx51_efika_spi_flash_data = {
-       .name           = "spi_flash",
-       .parts          = mx51_efika_spi_nor_partitions,
-       .nr_parts       = ARRAY_SIZE(mx51_efika_spi_nor_partitions),
-       .type           = "sst25vf032b",
-};
-
-static struct regulator_consumer_supply sw1_consumers[] = {
-       {
-               .supply = "cpu_vcc",
-       }
-};
-
-static struct regulator_consumer_supply vdig_consumers[] = {
-       /* sgtl5000 */
-       REGULATOR_SUPPLY("VDDA", "1-000a"),
-       REGULATOR_SUPPLY("VDDD", "1-000a"),
-};
-
-static struct regulator_consumer_supply vvideo_consumers[] = {
-       /* sgtl5000 */
-       REGULATOR_SUPPLY("VDDIO", "1-000a"),
-};
-
-static struct regulator_consumer_supply vsd_consumers[] = {
-       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
-       REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
-};
-
-static struct regulator_consumer_supply pwgt1_consumer[] = {
-       {
-               .supply = "pwgt1",
-       }
-};
-
-static struct regulator_consumer_supply pwgt2_consumer[] = {
-       {
-               .supply = "pwgt2",
-       }
-};
-
-static struct regulator_consumer_supply coincell_consumer[] = {
-       {
-               .supply = "coincell",
-       }
-};
-
-static struct regulator_init_data sw1_init = {
-       .constraints = {
-               .name = "SW1",
-               .min_uV = 600000,
-               .max_uV = 1375000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-               .valid_modes_mask = 0,
-               .always_on = 1,
-               .boot_on = 1,
-               .state_mem = {
-                       .uV = 850000,
-                       .mode = REGULATOR_MODE_NORMAL,
-                       .enabled = 1,
-               },
-       },
-       .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
-       .consumer_supplies = sw1_consumers,
-};
-
-static struct regulator_init_data sw2_init = {
-       .constraints = {
-               .name = "SW2",
-               .min_uV = 900000,
-               .max_uV = 1850000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-               .always_on = 1,
-               .boot_on = 1,
-               .state_mem = {
-                       .uV = 950000,
-                       .mode = REGULATOR_MODE_NORMAL,
-                       .enabled = 1,
-               },
-       }
-};
-
-static struct regulator_init_data sw3_init = {
-       .constraints = {
-               .name = "SW3",
-               .min_uV = 1100000,
-               .max_uV = 1850000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-               .always_on = 1,
-               .boot_on = 1,
-       }
-};
-
-static struct regulator_init_data sw4_init = {
-       .constraints = {
-               .name = "SW4",
-               .min_uV = 1100000,
-               .max_uV = 1850000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-               .always_on = 1,
-               .boot_on = 1,
-       }
-};
-
-static struct regulator_init_data viohi_init = {
-       .constraints = {
-               .name = "VIOHI",
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data vusb_init = {
-       .constraints = {
-               .name = "VUSB",
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data swbst_init = {
-       .constraints = {
-               .name = "SWBST",
-       }
-};
-
-static struct regulator_init_data vdig_init = {
-       .constraints = {
-               .name = "VDIG",
-               .min_uV = 1050000,
-               .max_uV = 1800000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-               .always_on = 1,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
-       .consumer_supplies = vdig_consumers,
-};
-
-static struct regulator_init_data vpll_init = {
-       .constraints = {
-               .name = "VPLL",
-               .min_uV = 1050000,
-               .max_uV = 1800000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data vusb2_init = {
-       .constraints = {
-               .name = "VUSB2",
-               .min_uV = 2400000,
-               .max_uV = 2775000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data vvideo_init = {
-       .constraints = {
-               .name = "VVIDEO",
-               .min_uV = 2775000,
-               .max_uV = 2775000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-               .apply_uV = 1,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
-       .consumer_supplies = vvideo_consumers,
-};
-
-static struct regulator_init_data vaudio_init = {
-       .constraints = {
-               .name = "VAUDIO",
-               .min_uV = 2300000,
-               .max_uV = 3000000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-       }
-};
-
-static struct regulator_init_data vsd_init = {
-       .constraints = {
-               .name = "VSD",
-               .min_uV = 1800000,
-               .max_uV = 3150000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE,
-               .boot_on = 1,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
-       .consumer_supplies = vsd_consumers,
-};
-
-static struct regulator_init_data vcam_init = {
-       .constraints = {
-               .name = "VCAM",
-               .min_uV = 2500000,
-               .max_uV = 3000000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE |
-                       REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-               .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
-               .boot_on = 1,
-       }
-};
-
-static struct regulator_init_data vgen1_init = {
-       .constraints = {
-               .name = "VGEN1",
-               .min_uV = 1200000,
-               .max_uV = 3150000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data vgen2_init = {
-       .constraints = {
-               .name = "VGEN2",
-               .min_uV = 1200000,
-               .max_uV = 3150000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data vgen3_init = {
-       .constraints = {
-               .name = "VGEN3",
-               .min_uV = 1800000,
-               .max_uV = 2900000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-               .always_on = 1,
-       }
-};
-
-static struct regulator_init_data gpo1_init = {
-       .constraints = {
-               .name = "GPO1",
-       }
-};
-
-static struct regulator_init_data gpo2_init = {
-       .constraints = {
-               .name = "GPO2",
-       }
-};
-
-static struct regulator_init_data gpo3_init = {
-       .constraints = {
-               .name = "GPO3",
-       }
-};
-
-static struct regulator_init_data gpo4_init = {
-       .constraints = {
-               .name = "GPO4",
-       }
-};
-
-static struct regulator_init_data pwgt1_init = {
-       .constraints = {
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-               .boot_on        = 1,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
-       .consumer_supplies = pwgt1_consumer,
-};
-
-static struct regulator_init_data pwgt2_init = {
-       .constraints = {
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-               .boot_on        = 1,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
-       .consumer_supplies = pwgt2_consumer,
-};
-
-static struct regulator_init_data vcoincell_init = {
-       .constraints = {
-               .name = "COINCELL",
-               .min_uV = 3000000,
-               .max_uV = 3000000,
-               .valid_ops_mask =
-                       REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
-       .consumer_supplies = coincell_consumer,
-};
-
-static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
-       { .id = MC13892_SW1,            .init_data =  &sw1_init },
-       { .id = MC13892_SW2,            .init_data =  &sw2_init },
-       { .id = MC13892_SW3,            .init_data =  &sw3_init },
-       { .id = MC13892_SW4,            .init_data =  &sw4_init },
-       { .id = MC13892_SWBST,          .init_data =  &swbst_init },
-       { .id = MC13892_VIOHI,          .init_data =  &viohi_init },
-       { .id = MC13892_VPLL,           .init_data =  &vpll_init },
-       { .id = MC13892_VDIG,           .init_data =  &vdig_init },
-       { .id = MC13892_VSD,            .init_data =  &vsd_init },
-       { .id = MC13892_VUSB2,          .init_data =  &vusb2_init },
-       { .id = MC13892_VVIDEO,         .init_data =  &vvideo_init },
-       { .id = MC13892_VAUDIO,         .init_data =  &vaudio_init },
-       { .id = MC13892_VCAM,           .init_data =  &vcam_init },
-       { .id = MC13892_VGEN1,          .init_data =  &vgen1_init },
-       { .id = MC13892_VGEN2,          .init_data =  &vgen2_init },
-       { .id = MC13892_VGEN3,          .init_data =  &vgen3_init },
-       { .id = MC13892_VUSB,           .init_data =  &vusb_init },
-       { .id = MC13892_GPO1,           .init_data =  &gpo1_init },
-       { .id = MC13892_GPO2,           .init_data =  &gpo2_init },
-       { .id = MC13892_GPO3,           .init_data =  &gpo3_init },
-       { .id = MC13892_GPO4,           .init_data =  &gpo4_init },
-       { .id = MC13892_PWGT1SPI,       .init_data = &pwgt1_init },
-       { .id = MC13892_PWGT2SPI,       .init_data = &pwgt2_init },
-       { .id = MC13892_VCOINCELL,      .init_data = &vcoincell_init },
-};
-
-static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
-       .flags = MC13XXX_USE_RTC,
-       .regulators = {
-               .num_regulators = ARRAY_SIZE(mx51_efika_regulators),
-               .regulators = mx51_efika_regulators,
-       },
-};
-
-static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
-       {
-               .modalias = "m25p80",
-               .max_speed_hz = 25000000,
-               .bus_num = 0,
-               .chip_select = 1,
-               .platform_data = &mx51_efika_spi_flash_data,
-               .irq = -1,
-       },
-       {
-               .modalias = "mc13892",
-               .max_speed_hz = 1000000,
-               .bus_num = 0,
-               .chip_select = 0,
-               .platform_data = &mx51_efika_mc13892_data,
-               .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
-       },
-};
-
-static int mx51_efika_spi_cs[] = {
-       EFIKAMX_SPI_CS0,
-       EFIKAMX_SPI_CS1,
-};
-
-static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
-       .chipselect     = mx51_efika_spi_cs,
-       .num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
-};
-
-void __init efika_board_common_init(void)
-{
-       mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
-                                       ARRAY_SIZE(mx51efika_pads));
-       imx51_add_imx_uart(0, &uart_pdata);
-       mx51_efika_usb();
-
-       /* FIXME: comes from original code. check this. */
-       if (mx51_revision() < IMX_CHIP_REVISION_2_0)
-               sw2_init.constraints.state_mem.uV = 1100000;
-       else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
-               sw2_init.constraints.state_mem.uV = 1250000;
-               sw1_init.constraints.state_mem.uV = 1000000;
-       }
-       if (machine_is_mx51_efikasb())
-               vgen1_init.constraints.max_uV = 1200000;
-
-       gpio_request(EFIKAMX_PMIC, "pmic irq");
-       gpio_direction_input(EFIKAMX_PMIC);
-       spi_register_board_info(mx51_efika_spi_board_info,
-               ARRAY_SIZE(mx51_efika_spi_board_info));
-       imx51_add_ecspi(0, &mx51_efika_spi_pdata);
-
-       imx51_add_pata_imx();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-       get_cpu_op = mx51_get_cpu_op;
-#endif
-}
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
deleted file mode 100644 (file)
index 98052fc..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/suspend.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include "crm_regs.h"
-
-static struct clk *gpc_dvfs_clk;
-
-static int mx5_suspend_prepare(void)
-{
-       return clk_enable(gpc_dvfs_clk);
-}
-
-static int mx5_suspend_enter(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_MEM:
-               mx5_cpu_lp_set(STOP_POWER_OFF);
-               break;
-       case PM_SUSPEND_STANDBY:
-               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (state == PM_SUSPEND_MEM) {
-               local_flush_tlb_all();
-               flush_cache_all();
-
-               /*clear the EMPGC0/1 bits */
-               __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
-               __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
-       }
-       cpu_do_idle();
-       return 0;
-}
-
-static void mx5_suspend_finish(void)
-{
-       clk_disable(gpc_dvfs_clk);
-}
-
-static int mx5_pm_valid(suspend_state_t state)
-{
-       return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
-}
-
-static const struct platform_suspend_ops mx5_suspend_ops = {
-       .valid = mx5_pm_valid,
-       .prepare = mx5_suspend_prepare,
-       .enter = mx5_suspend_enter,
-       .finish = mx5_suspend_finish,
-};
-
-static int __init mx5_pm_init(void)
-{
-       if (gpc_dvfs_clk == NULL)
-               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-
-       if (!IS_ERR(gpc_dvfs_clk)) {
-               if (cpu_is_mx51())
-                       suspend_set_ops(&mx5_suspend_ops);
-       } else
-               return -EPERM;
-
-       return 0;
-}
-device_initcall(mx5_pm_init);
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
deleted file mode 100644 (file)
index 5eebfaa..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include "crm_regs.h"
-
-/* set cpu low power mode before WFI instruction. This function is called
-  * mx5 because it can be used for mx50, mx51, and mx53.*/
-void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
-{
-       u32 plat_lpc, arm_srpgcr, ccm_clpcr;
-       u32 empgc0, empgc1;
-       int stop_mode = 0;
-
-       /* always allow platform to issue a deep sleep mode request */
-       plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
-           ~(MXC_CORTEXA8_PLAT_LPC_DSM);
-       ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
-       arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
-       empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
-       empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
-
-       switch (mode) {
-       case WAIT_CLOCKED:
-               break;
-       case WAIT_UNCLOCKED:
-               ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
-               break;
-       case WAIT_UNCLOCKED_POWER_OFF:
-       case STOP_POWER_OFF:
-               plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
-                           | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
-               if (mode == WAIT_UNCLOCKED_POWER_OFF) {
-                       ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
-                       ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
-                       ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
-                       stop_mode = 0;
-               } else {
-                       ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
-                       ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
-                       ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
-                       ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
-                       stop_mode = 1;
-               }
-               arm_srpgcr |= MXC_SRPGCR_PCR;
-               break;
-       case STOP_POWER_ON:
-               ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
-               break;
-       default:
-               printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
-               return;
-       }
-
-       __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
-       __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
-       __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
-
-       /* Enable NEON SRPG for all but MX50TO1.0. */
-       if (mx50_revision() != IMX_CHIP_REVISION_1_0)
-               __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
-
-       if (stop_mode) {
-               empgc0 |= MXC_SRPGCR_PCR;
-               empgc1 |= MXC_SRPGCR_PCR;
-
-               __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
-               __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
-       }
-}
index a8ba7b96dcd1c3177b11e634e5e8e4608dc7a4d4..d965da45160e67c4e03056a7d8c0d72178575042 100644 (file)
@@ -33,7 +33,6 @@ config ARCH_OMAP3
        default y
        select CPU_V7
        select USB_ARCH_HAS_EHCI
-       select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
        select ARCH_HAS_OPP
        select PM_OPP if PM
        select ARM_CPU_SUSPEND if PM
@@ -214,13 +213,12 @@ config MACH_OMAP3_PANDORA
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_OMAP3_TOUCHBOOK
        bool "OMAP3 Touch Book"
        depends on ARCH_OMAP3
        default y
-       select BACKLIGHT_CLASS_DEVICE
 
 config MACH_OMAP_3430SDP
        bool "OMAP 3430 SDP board"
@@ -266,7 +264,7 @@ config MACH_OMAP_ZOOM2
        select SERIAL_8250
        select SERIAL_CORE_CONSOLE
        select SERIAL_8250_CONSOLE
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_OMAP_ZOOM3
        bool "OMAP3630 Zoom3 board"
@@ -276,7 +274,7 @@ config MACH_OMAP_ZOOM3
        select SERIAL_8250
        select SERIAL_CORE_CONSOLE
        select SERIAL_8250_CONSOLE
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_CM_T35
        bool "CompuLab CM-T35/CM-T3730 modules"
@@ -335,7 +333,7 @@ config MACH_OMAP_4430SDP
        depends on ARCH_OMAP4
        select OMAP_PACKAGE_CBL
        select OMAP_PACKAGE_CBS
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_OMAP4_PANDA
        bool "OMAP4 Panda Board"
@@ -343,7 +341,7 @@ config MACH_OMAP4_PANDA
        depends on ARCH_OMAP4
        select OMAP_PACKAGE_CBL
        select OMAP_PACKAGE_CBS
-       select REGULATOR_FIXED_VOLTAGE
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config OMAP3_EMU
        bool "OMAP3 debugging peripherals"
index fc9b238cbc190c1e657d07552131c7c767fa1104..bd76394ccaf8c90de32b824dc5dc65675a73fb18 100644 (file)
@@ -11,9 +11,9 @@ hwmod-common                          = omap_hwmod.o \
                                          omap_hwmod_common_data.o
 clock-common                           = clock.o clock_common_data.o \
                                          clkt_dpll.o clkt_clksel.o
-secure-common                          = omap-smc.o omap-secure.o
+secure-common                          = omap-smc.o omap-secure.o
 
-obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
+obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
 obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
 
index 39fba9df17fba3209396cba2d8be2d59553c8ab5..4e9071589bfb60ac3bfb5a222eefcfebc700bd03 100644 (file)
@@ -52,8 +52,9 @@
 #define ETH_KS8851_QUART               138
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO       184
 #define OMAP4_SFH7741_ENABLE_GPIO              188
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD  63 /* Hotplug detect */
 #define DISPLAY_SEL_GPIO       59      /* LCD2/PicoDLP switch */
 #define DLP_POWER_ON_GPIO      40
 
@@ -603,8 +604,9 @@ static void __init omap_sfh7741prox_init(void)
 }
 
 static struct gpio sdp4430_hdmi_gpios[] = {
-       { HDMI_GPIO_HPD,        GPIOF_OUT_INIT_HIGH,    "hdmi_gpio_hpd"   },
+       { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
        { HDMI_GPIO_LS_OE,      GPIOF_OUT_INIT_HIGH,    "hdmi_gpio_ls_oe" },
+       { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
 };
 
 static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -621,8 +623,7 @@ static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
 
 static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
 {
-       gpio_free(HDMI_GPIO_LS_OE);
-       gpio_free(HDMI_GPIO_HPD);
+       gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
 }
 
 static struct nokia_dsi_panel_data dsi1_panel = {
@@ -738,6 +739,10 @@ static void sdp4430_lcd_init(void)
                pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
 }
 
+static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+       .hpd_gpio = HDMI_GPIO_HPD,
+};
+
 static struct omap_dss_device sdp4430_hdmi_device = {
        .name = "hdmi",
        .driver_name = "hdmi_panel",
@@ -745,6 +750,7 @@ static struct omap_dss_device sdp4430_hdmi_device = {
        .platform_enable = sdp4430_panel_enable_hdmi,
        .platform_disable = sdp4430_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
+       .data = &sdp4430_hdmi_data,
 };
 
 static struct picodlp_panel_data sdp4430_picodlp_pdata = {
@@ -808,7 +814,7 @@ static struct omap_dss_board_info sdp4430_dss_data = {
        .default_device = &sdp4430_lcd_device,
 };
 
-static void omap_4430sdp_display_init(void)
+static void __init omap_4430sdp_display_init(void)
 {
        int r;
 
@@ -829,6 +835,10 @@ static void omap_4430sdp_display_init(void)
                omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
        else
                omap_hdmi_init(0);
+
+       omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -841,7 +851,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux      NULL
  #endif
 
-static void omap4_sdp4430_wifi_mux_init(void)
+static void __init omap4_sdp4430_wifi_mux_init(void)
 {
        omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
                                OMAP_PIN_OFF_WAKEUPENABLE);
@@ -868,12 +878,17 @@ static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = {
        .board_tcxo_clock = WL12XX_TCXOCLOCK_26,
 };
 
-static void omap4_sdp4430_wifi_init(void)
+static void __init omap4_sdp4430_wifi_init(void)
 {
+       int ret;
+
        omap4_sdp4430_wifi_mux_init();
-       if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data))
-               pr_err("Error setting wl12xx data\n");
-       platform_device_register(&omap_vwlan_device);
+       ret = wl12xx_set_platform_data(&omap4_sdp4430_wlan_data);
+       if (ret)
+               pr_err("Error setting wl12xx data: %d\n", ret);
+       ret = platform_device_register(&omap_vwlan_device);
+       if (ret)
+               pr_err("Error registering wl12xx device: %d\n", ret);
 }
 
 static void __init omap_4430sdp_init(void)
index e921e3be24a4575d5bc4ea908f9fe8bc19c78355..d73316ed4207c600378cb538b73ae0daf04dcb2e 100644 (file)
@@ -437,7 +437,7 @@ static struct usbhs_omap_board_data usbhs_bdata __initdata = {
        .reset_gpio_port[2]  = -EINVAL
 };
 
-static void cm_t35_init_usbh(void)
+static void  __init cm_t35_init_usbh(void)
 {
        int err;
 
index d587560604836f5d7ee836b773f37798c17cdf41..ad497620539bccdada5a0907a19fab8f7da36813 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/i2c/twl.h>
 
 #include <mach/hardware.h>
+#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 
 #include <plat/board.h>
@@ -102,6 +103,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
        .map_io         = omap242x_map_io,
        .init_early     = omap2420_init_early,
        .init_irq       = omap2_init_irq,
+       .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
        .dt_compat      = omap242x_boards_compat,
@@ -141,6 +143,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
        .map_io         = omap3_map_io,
        .init_early     = omap3430_init_early,
        .init_irq       = omap3_init_irq,
+       .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3_init,
        .timer          = &omap3_timer,
        .dt_compat      = omap3_boards_compat,
@@ -160,6 +163,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
        .map_io         = omap4_map_io,
        .init_early     = omap4430_init_early,
        .init_irq       = gic_init_irq,
+       .handle_irq     = gic_handle_irq,
        .init_machine   = omap4_init,
        .timer          = &omap4_timer,
        .dt_compat      = omap4_boards_compat,
index 003fe34c934311251452ba4af1efc20382dbbdb6..c775bead1497c3f487e22696bee4b59c6c46eeed 100644 (file)
@@ -617,6 +617,21 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {
        { OMAP3_EVM_EHCI_SELECT, GPIOF_OUT_INIT_LOW,   "select EHCI port" },
 };
 
+static void __init omap3_evm_wl12xx_init(void)
+{
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+       int ret;
+
+       /* WL12xx WLAN Init */
+       ret = wl12xx_set_platform_data(&omap3evm_wlan_data);
+       if (ret)
+               pr_err("error setting wl12xx data: %d\n", ret);
+       ret = platform_device_register(&omap3evm_wlan_regulator);
+       if (ret)
+               pr_err("error registering wl12xx device: %d\n", ret);
+#endif
+}
+
 static void __init omap3_evm_init(void)
 {
        omap3_evm_get_revision();
@@ -665,13 +680,7 @@ static void __init omap3_evm_init(void)
        omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
        omap3evm_init_smsc911x();
        omap3_evm_display_init();
-
-#ifdef CONFIG_WL12XX_PLATFORM_DATA
-       /* WL12xx WLAN Init */
-       if (wl12xx_set_platform_data(&omap3evm_wlan_data))
-               pr_err("error setting wl12xx data\n");
-       platform_device_register(&omap3evm_wlan_regulator);
-#endif
+       omap3_evm_wl12xx_init();
 }
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
index 30ad40db2cf39558bdefc6bf40169114919ed6e7..28fc271f70316510b5268c2a212adcac3718fce1 100644 (file)
@@ -51,8 +51,9 @@
 #define GPIO_HUB_NRESET                62
 #define GPIO_WIFI_PMENA                43
 #define GPIO_WIFI_IRQ          53
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD  63 /* Hotplug detect */
 
 /* wl127x BT, FM, GPS connectivity chip */
 static int wl1271_gpios[] = {46, -1, -1};
@@ -413,8 +414,9 @@ int __init omap4_panda_dvi_init(void)
 }
 
 static struct gpio panda_hdmi_gpios[] = {
-       { HDMI_GPIO_HPD,        GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd"   },
+       { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
        { HDMI_GPIO_LS_OE,      GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+       { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
 };
 
 static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -431,10 +433,13 @@ static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
 
 static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
 {
-       gpio_free(HDMI_GPIO_LS_OE);
-       gpio_free(HDMI_GPIO_HPD);
+       gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
 }
 
+static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+       .hpd_gpio = HDMI_GPIO_HPD,
+};
+
 static struct omap_dss_device  omap4_panda_hdmi_device = {
        .name = "hdmi",
        .driver_name = "hdmi_panel",
@@ -442,6 +447,7 @@ static struct omap_dss_device  omap4_panda_hdmi_device = {
        .platform_enable = omap4_panda_panel_enable_hdmi,
        .platform_disable = omap4_panda_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
+       .data = &omap4_panda_hdmi_data,
 };
 
 static struct omap_dss_device *omap4_panda_dss_devices[] = {
@@ -473,18 +479,24 @@ void omap4_panda_display_init(void)
                omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
        else
                omap_hdmi_init(0);
+
+       omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
 }
 
 static void __init omap4_panda_init(void)
 {
        int package = OMAP_PACKAGE_CBS;
+       int ret;
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
                package = OMAP_PACKAGE_CBL;
        omap4_mux_init(board_mux, NULL, package);
 
-       if (wl12xx_set_platform_data(&omap_panda_wlan_data))
-               pr_err("error setting wl12xx data\n");
+       ret = wl12xx_set_platform_data(&omap_panda_wlan_data);
+       if (ret)
+               pr_err("error setting wl12xx data: %d\n", ret);
 
        omap4_panda_i2c_init();
        platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
index 8d7ce11cfeaf14b34d18c5ac4945a855b51f0d2d..c126461836ac5d2134314b82c80dae0eb41fcf60 100644 (file)
@@ -296,8 +296,10 @@ static void enable_board_wakeup_source(void)
 
 void __init zoom_peripherals_init(void)
 {
-       if (wl12xx_set_platform_data(&omap_zoom_wlan_data))
-               pr_err("error setting wl12xx data\n");
+       int ret = wl12xx_set_platform_data(&omap_zoom_wlan_data);
+
+       if (ret)
+               pr_err("error setting wl12xx data: %d\n", ret);
 
        omap_i2c_init();
        platform_device_register(&omap_vwlan_device);
index 0b510ad01a00b5a7ad4ae224f17447e8bba6301f..283d11eae693115b42d2bbcca9176f019274960c 100644 (file)
@@ -405,6 +405,7 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
                        break;
        default:
                        pr_err("Invalid McSPI Revision value\n");
+                       kfree(pdata);
                        return -EINVAL;
        }
 
index 3c446d1a1781fe3d819b2732ea28e2426c2a1348..3677b1f58b85f32c25e9c4f1e886a0e259ee9102 100644 (file)
@@ -103,12 +103,8 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
        u32 reg;
        u16 control_i2c_1;
 
-       /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
-       omap_mux_init_signal("hdmi_hpd",
-                       OMAP_PIN_INPUT_PULLUP);
        omap_mux_init_signal("hdmi_cec",
                        OMAP_PIN_INPUT_PULLUP);
-       /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
        omap_mux_init_signal("hdmi_ddc_scl",
                        OMAP_PIN_INPUT_PULLUP);
        omap_mux_init_signal("hdmi_ddc_sda",
index 130034bf01d5f880541976cf3210de7e74293ce1..dfffbbf4c009624c87375b6322a2a7285cd8a2e7 100644 (file)
@@ -528,7 +528,13 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
 
        case GPMC_CONFIG_DEV_SIZE:
                regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               /* clear 2 target bits */
+               regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
+
+               /* set the proper value */
                regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+
                gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
                break;
 
index bd844af13af56106d7fe5511dcaa6d2ebf6f7afa..b40c288952987a2327d950abbfe374193f8f59e7 100644 (file)
@@ -175,14 +175,15 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc)
 {
        u32 reg;
 
-       if (mmc->slots[0].internal_clock) {
-               reg = omap_ctrl_readl(control_devconf1_offset);
+       reg = omap_ctrl_readl(control_devconf1_offset);
+       if (mmc->slots[0].internal_clock)
                reg |= OMAP2_MMCSDIO2ADPCLKISEL;
-               omap_ctrl_writel(reg, control_devconf1_offset);
-       }
+       else
+               reg &= ~OMAP2_MMCSDIO2ADPCLKISEL;
+       omap_ctrl_writel(reg, control_devconf1_offset);
 }
 
-static void hsmmc23_before_set_reg(struct device *dev, int slot,
+static void hsmmc2_before_set_reg(struct device *dev, int slot,
                                   int power_on, int vdd)
 {
        struct omap_mmc_platform_data *mmc = dev->platform_data;
@@ -292,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
        }
 }
 
-static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
-                                       struct omap_mmc_platform_data *mmc)
+static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+                                struct omap_mmc_platform_data *mmc)
 {
        char *hc_name;
 
@@ -407,14 +408,13 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
                        c->caps &= ~MMC_CAP_8_BIT_DATA;
                        c->caps |= MMC_CAP_4_BIT_DATA;
                }
-               /* FALLTHROUGH */
-       case 3:
                if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
                        /* off-chip level shifting, or none */
-                       mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+                       mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;
                        mmc->slots[0].after_set_reg = NULL;
                }
                break;
+       case 3:
        case 4:
        case 5:
                mmc->slots[0].before_set_reg = NULL;
@@ -430,7 +430,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN            16
 
-void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 {
        struct omap_hwmod *oh;
        struct platform_device *pdev;
@@ -487,7 +487,7 @@ done:
        kfree(mmc_data);
 }
 
-void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
        u32 reg;
 
index 3f174d51f67fb8e4f41f01ebbbe577c892999449..eb50c29fb6448e1404eef693e8f74c5e10641aed 100644 (file)
@@ -388,7 +388,7 @@ static void __init omap_hwmod_init_postsetup(void)
        omap_pm_if_early_init();
 }
 
-#ifdef CONFIG_ARCH_OMAP2
+#ifdef CONFIG_SOC_OMAP2420
 void __init omap2420_init_early(void)
 {
        omap2_set_globals_242x();
@@ -400,7 +400,9 @@ void __init omap2420_init_early(void)
        omap_hwmod_init_postsetup();
        omap2420_clk_init();
 }
+#endif
 
+#ifdef CONFIG_SOC_OMAP2430
 void __init omap2430_init_early(void)
 {
        omap2_set_globals_243x();
index e1cc75d1a57ac024ba18382c26daa127ccce3abe..fb8bc9fa43b140fbfd5050ebc478833877b8066f 100644 (file)
@@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,
 
 static char *omap_mux_options;
 
-static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
-                                     int gpio, int val)
+static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
+                              int gpio, int val)
 {
        struct omap_mux_entry *e;
        struct omap_mux *gpio_mux = NULL;
@@ -145,7 +145,7 @@ static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
        return 0;
 }
 
-int __init omap_mux_init_gpio(int gpio, int val)
+int omap_mux_init_gpio(int gpio, int val)
 {
        struct omap_mux_partition *partition;
        int ret;
@@ -159,9 +159,9 @@ int __init omap_mux_init_gpio(int gpio, int val)
        return -ENODEV;
 }
 
-static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
-                                       const char *muxname,
-                                       struct omap_mux **found_mux)
+static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
+                                const char *muxname,
+                                struct omap_mux **found_mux)
 {
        struct omap_mux *mux = NULL;
        struct omap_mux_entry *e;
@@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,
        return -ENODEV;
 }
 
-int __init omap_mux_init_signal(const char *muxname, int val)
+int omap_mux_init_signal(const char *muxname, int val)
 {
        struct omap_mux_partition *partition = NULL;
        struct omap_mux *mux = NULL;
@@ -1094,8 +1094,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
                omap_mux_package_init_balls(package_balls, superset);
 }
 
-static void omap_mux_init_signals(struct omap_mux_partition *partition,
-                                 struct omap_board_mux *board_mux)
+static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
+                                        struct omap_board_mux *board_mux)
 {
        omap_mux_set_cmdline_signals();
        omap_mux_write_array(partition, board_mux);
@@ -1109,8 +1109,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
 {
 }
 
-static void omap_mux_init_signals(struct omap_mux_partition *partition,
-                                 struct omap_board_mux *board_mux)
+static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
+                                        struct omap_board_mux *board_mux)
 {
 }
 
index b13ef7ef5ef4746bf4d2f8987375ba3d5261cc2f..503ac777a2ba8682b35f0798eccd80f3f8621763 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+       __CPUINIT
 /*
  * OMAP4 specific entry point for secondary CPU to jump from ROM
  * code.  This routine also provides a holding flag into which
index 5192cabb40ed812ca39363124f2a94eebf8541dc..eba6cd3816f5e917d09aa5d8367c84f27a6e51dc 100644 (file)
@@ -1517,8 +1517,8 @@ static int _enable(struct omap_hwmod *oh)
        if (oh->_state != _HWMOD_STATE_INITIALIZED &&
            oh->_state != _HWMOD_STATE_IDLE &&
            oh->_state != _HWMOD_STATE_DISABLED) {
-               WARN(1, "omap_hwmod: %s: enabled state can only be entered "
-                    "from initialized, idle, or disabled state\n", oh->name);
+               WARN(1, "omap_hwmod: %s: enabled state can only be entered from initialized, idle, or disabled state\n",
+                       oh->name);
                return -EINVAL;
        }
 
@@ -1600,8 +1600,8 @@ static int _idle(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->_state != _HWMOD_STATE_ENABLED) {
-               WARN(1, "omap_hwmod: %s: idle state can only be entered from "
-                    "enabled state\n", oh->name);
+               WARN(1, "omap_hwmod: %s: idle state can only be entered from enabled state\n",
+                       oh->name);
                return -EINVAL;
        }
 
@@ -1682,8 +1682,8 @@ static int _shutdown(struct omap_hwmod *oh)
 
        if (oh->_state != _HWMOD_STATE_IDLE &&
            oh->_state != _HWMOD_STATE_ENABLED) {
-               WARN(1, "omap_hwmod: %s: disabled state can only be entered "
-                    "from idle, or enabled state\n", oh->name);
+               WARN(1, "omap_hwmod: %s: disabled state can only be entered from idle, or enabled state\n",
+                       oh->name);
                return -EINVAL;
        }
 
@@ -2240,8 +2240,8 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
        BUG_ON(!oh);
 
        if (!oh->class->sysc || !oh->class->sysc->sysc_flags) {
-               WARN(1, "omap_device: %s: OCP barrier impossible due to "
-                     "device configuration\n", oh->name);
+               WARN(1, "omap_device: %s: OCP barrier impossible due to device configuration\n",
+                       oh->name);
                return;
        }
 
index c11273da5dcc33f046e94babfdb6f34c1d6f2778..f08e442af3976d371bda89390c6529fe25839604 100644 (file)
@@ -55,27 +55,6 @@ struct omap_hwmod_class omap2_dss_hwmod_class = {
        .reset  = omap_dss_reset,
 };
 
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0014,
-       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
-                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_dispc_hwmod_class = {
-       .name   = "dispc",
-       .sysc   = &omap2_dispc_sysc,
-};
-
 /*
  * 'rfbi' class
  * remote frame buffer interface
index 177dee20faef1ef79b8bacdcde89a4b8e86f1946..2a6729741b069c2fd7633bbfb14dab1432c471d7 100644 (file)
@@ -28,6 +28,28 @@ struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
        { .name = "dispc", .dma_req = 5 },
        { .dma_req = -1 }
 };
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+       .name   = "dispc",
+       .sysc   = &omap2_dispc_sysc,
+};
+
 /* OMAP2xxx Timer Common */
 static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
        .rev_offs       = 0x0000,
index 5324e8d93bc0262d9019db6feb7f81fdc42a8f44..3c8dd928628efd7c01cad5a1d2743c7ddc34a660 100644 (file)
@@ -1480,6 +1480,28 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
        .masters_cnt    = ARRAY_SIZE(omap3xxx_dss_masters),
 };
 
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3_dispc_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSC_HAS_ENAWAKEUP),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                          MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3_dispc_hwmod_class = {
+       .name   = "dispc",
+       .sysc   = &omap3_dispc_sysc,
+};
+
 /* l4_core -> dss_dispc */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
        .master         = &omap3xxx_l4_core_hwmod,
@@ -1503,7 +1525,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
        .name           = "dss_dispc",
-       .class          = &omap2_dispc_hwmod_class,
+       .class          = &omap3_dispc_hwmod_class,
        .mpu_irqs       = omap2_dispc_irqs,
        .main_clk       = "dss1_alwon_fck",
        .prcm           = {
@@ -3523,12 +3545,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_uart2_hwmod,
        &omap3xxx_uart3_hwmod,
 
-       /* dss class */
-       &omap3xxx_dss_dispc_hwmod,
-       &omap3xxx_dss_dsi1_hwmod,
-       &omap3xxx_dss_rfbi_hwmod,
-       &omap3xxx_dss_venc_hwmod,
-
        /* i2c class */
        &omap3xxx_i2c1_hwmod,
        &omap3xxx_i2c2_hwmod,
@@ -3635,6 +3651,15 @@ static __initdata struct omap_hwmod *am35xx_hwmods[] = {
        NULL
 };
 
+static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = {
+       /* dss class */
+       &omap3xxx_dss_dispc_hwmod,
+       &omap3xxx_dss_dsi1_hwmod,
+       &omap3xxx_dss_rfbi_hwmod,
+       &omap3xxx_dss_venc_hwmod,
+       NULL
+};
+
 int __init omap3xxx_hwmod_init(void)
 {
        int r;
@@ -3708,6 +3733,21 @@ int __init omap3xxx_hwmod_init(void)
 
        if (h)
                r = omap_hwmod_register(h);
+       if (r < 0)
+               return r;
+
+       /*
+        * DSS code presumes that dss_core hwmod is handled first,
+        * _before_ any other DSS related hwmods so register common
+        * DSS hwmods last to ensure that dss_core is already registered.
+        * Otherwise some change things may happen, for ex. if dispc
+        * is handled before dss_core and DSS is enabled in bootloader
+        * DIPSC will be reset with outputs enabled which sometimes leads
+        * to unrecoverable L3 error.
+        * XXX The long-term fix to this is to ensure modules are set up
+        * in dependency order in the hwmod core code.
+        */
+       r = omap_hwmod_register(omap3xxx_dss_hwmods);
 
        return r;
 }
index f9f1510817603332292348eedccca1155ac80895..ef0524c10a840296b089f4e3ca81d291f737a503 100644 (file)
@@ -1031,6 +1031,7 @@ static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
 
 static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
        {
+               .name           = "mpu",
                .pa_start       = 0x4012e000,
                .pa_end         = 0x4012e07f,
                .flags          = ADDR_TYPE_RT
@@ -1049,6 +1050,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
 
 static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
        {
+               .name           = "dma",
                .pa_start       = 0x4902e000,
                .pa_end         = 0x4902e07f,
                .flags          = ADDR_TYPE_RT
index b8822f8b289184c46332732bc20ebe2ea5605cb3..23de98d0384151b76274f67a99a10a005d4b3541 100644 (file)
@@ -82,13 +82,7 @@ static int omap2_fclks_active(void)
        f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
        f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 
-       /* Ignore UART clocks.  These are handled by UART core (serial.c) */
-       f1 &= ~(OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_UART2_MASK);
-       f2 &= ~OMAP24XX_EN_UART3_MASK;
-
-       if (f1 | f2)
-               return 1;
-       return 0;
+       return (f1 | f2) ? 1 : 0;
 }
 
 static void omap2_enter_full_retention(void)
index c1c4d86a79a8e5f7ff32b2739928963be7a4d4e2..9ce765407ad55d5ac9190af77cdb48338c338752 100644 (file)
@@ -19,6 +19,7 @@
 #include "common.h"
 #include <plat/cpu.h>
 #include <plat/prcm.h>
+#include <plat/irqs.h>
 
 #include "vp.h"
 
index 33dd655e6aabf96a8b1c66d9b912aabaf8fa583c..a1d6154dc120af3ceb056e0616c6d55eee6b17b9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "common.h"
 #include <plat/cpu.h>
+#include <plat/irqs.h>
 #include <plat/prcm.h>
 
 #include "vp.h"
index 247d89478f2439010c741045518d455e78e73d17..f590afc1f673f3afdb3c43cc89f0338ccb2fcc07 100644 (file)
@@ -107,18 +107,18 @@ static void omap_uart_set_noidle(struct platform_device *pdev)
        omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
 }
 
-static void omap_uart_set_forceidle(struct platform_device *pdev)
+static void omap_uart_set_smartidle(struct platform_device *pdev)
 {
        struct omap_device *od = to_omap_device(pdev);
 
-       omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE);
+       omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
 }
 
 #else
 static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
 {}
 static void omap_uart_set_noidle(struct platform_device *pdev) {}
-static void omap_uart_set_forceidle(struct platform_device *pdev) {}
+static void omap_uart_set_smartidle(struct platform_device *pdev) {}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
@@ -349,7 +349,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
        omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
        omap_up.flags = UPF_BOOT_AUTOCONF;
        omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
-       omap_up.set_forceidle = omap_uart_set_forceidle;
+       omap_up.set_forceidle = omap_uart_set_smartidle;
        omap_up.set_noidle = omap_uart_set_noidle;
        omap_up.enable_wakeup = omap_uart_enable_wakeup;
        omap_up.dma_rx_buf_size = info->dma_rx_buf_size;
index 9dd93453e563eaa666b2640663d529dc9102c928..7e755bb0ffc4c6a9bbfa906609cc370e383fdbf1 100644 (file)
@@ -897,7 +897,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                ret = sr_late_init(sr_info);
                if (ret) {
                        pr_warning("%s: Error in SR late init\n", __func__);
-                       return ret;
+                       goto err_iounmap;
                }
        }
 
index 6eeff0e0ae01932d0e841444754d913a30e748b5..5c9acea957619196d502baaa3fd591e96a1db01d 100644 (file)
@@ -270,7 +270,7 @@ static struct clocksource clocksource_gpt = {
 static u32 notrace dmtimer_read_sched_clock(void)
 {
        if (clksrc.reserved)
-               return __omap_dm_timer_read_counter(clksrc.io_base, 1);
+               return __omap_dm_timer_read_counter(&clksrc, 1);
 
        return 0;
 }
index 031d116fbf103fff322a4e13bb16ae4221b28d02..175b7d86d86ac3673d926745dc67e42a4e0ad899 100644 (file)
@@ -247,7 +247,7 @@ static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
  * omap_vc_i2c_init - initialize I2C interface to PMIC
  * @voltdm: voltage domain containing VC data
  *
- * Use PMIC supplied seetings for I2C high-speed mode and
+ * Use PMIC supplied settings for I2C high-speed mode and
  * master code (if set) and program the VC I2C configuration
  * register.
  *
@@ -265,8 +265,8 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
 
        if (initialized) {
                if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
-                       pr_warn("%s: I2C config for all channels must match.",
-                               __func__);
+                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).",
+                               __func__, voltdm->name, i2c_high_speed);
                return;
        }
 
@@ -292,9 +292,7 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
        u32 val;
 
        if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
-               pr_err("%s: PMIC info requried to configure vc for"
-                       "vdd_%s not populated.Hence cannot initialize vc\n",
-                       __func__, voltdm->name);
+               pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
                return;
        }
 
index c005e2f5e38341eae7b7577e4d7059be27ea6f81..57db2038b23c59c307e480a4872ee6ebebec30d3 100644 (file)
@@ -108,6 +108,7 @@ void __init omap3xxx_voltagedomains_init(void)
         * XXX Will depend on the process, validation, and binning
         * for the currently-running IC
         */
+#ifdef CONFIG_PM_OPP
        if (cpu_is_omap3630()) {
                omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
                omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
@@ -115,6 +116,7 @@ void __init omap3xxx_voltagedomains_init(void)
                omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
                omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
        }
+#endif
 
        if (cpu_is_omap3517() || cpu_is_omap3505())
                voltdms = voltagedomains_am35xx;
index 4e11d022595d13fa349601bf5c194fe69e0a40d3..c3115f6853d40414af8e6f8fa6982bedf9529ece 100644 (file)
@@ -100,9 +100,11 @@ void __init omap44xx_voltagedomains_init(void)
         * XXX Will depend on the process, validation, and binning
         * for the currently-running IC
         */
+#ifdef CONFIG_PM_OPP
        omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
        omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
        omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
+#endif
 
        for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
                voltdm->sys_clk.name = sys_clk_name;
index 807391d84a9dcd6aa394bb71b3729e97de542f67..0df88820978d5d509ded718d3311659e8ab079d4 100644 (file)
@@ -41,6 +41,11 @@ void __init omap_vp_init(struct voltagedomain *voltdm)
        u32 val, sys_clk_rate, timeout, waittime;
        u32 vddmin, vddmax, vstepmin, vstepmax;
 
+       if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+               pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
+               return;
+       }
+
        if (!voltdm->read || !voltdm->write) {
                pr_err("%s: No read/write API for accessing vdd_%s regs\n",
                        __func__, voltdm->name);
index 0e28bae20bd4dfe88d57de429f54631f89d298a8..5dad38ec00ea1422c618d455e14cc3bd4c364d04 100644 (file)
@@ -29,6 +29,7 @@
 #include <mach/hardware.h>
 #include <mach/orion5x.h>
 #include <plat/orion_nand.h>
+#include <plat/ehci-orion.h>
 #include <plat/time.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
@@ -72,7 +73,8 @@ void __init orion5x_map_io(void)
  ****************************************************************************/
 void __init orion5x_ehci0_init(void)
 {
-       orion_ehci_init(ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL);
+       orion_ehci_init(ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL,
+                       EHCI_PHY_ORION);
 }
 
 
index 6c89cf8ab22eece43dd765896bf0e53824f8753e..2ecba6743b8e66b050f7bb79665878a34878484b 100644 (file)
@@ -67,7 +67,7 @@ static void picoxcell_add_clocksource(struct device_node *source_timer)
 
 static void __iomem *sched_io_base;
 
-unsigned u32 notrace picoxcell_read_sched_clock(void)
+static u32 picoxcell_read_sched_clock(void)
 {
        return __raw_readl(sched_io_base);
 }
index 18fd177073f4a54862e17a60f8d2b9c459df3c1f..5bc13121eac5d15eb239e3992b18f90720f67416 100644 (file)
@@ -415,29 +415,9 @@ static struct resource pxa_rtc_resources[] = {
        },
 };
 
-static struct resource sa1100_rtc_resources[] = {
-       [0] = {
-               .start  = 0x40900000,
-               .end    = 0x409000ff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_RTC1Hz,
-               .end    = IRQ_RTC1Hz,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = IRQ_RTCAlrm,
-               .end    = IRQ_RTCAlrm,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
 struct platform_device sa1100_device_rtc = {
        .name           = "sa1100-rtc",
        .id             = -1,
-       .num_resources  = ARRAY_SIZE(sa1100_rtc_resources),
-       .resource       = sa1100_rtc_resources,
 };
 
 struct platform_device pxa_device_rtc = {
index adf058fa97ee56665cc6d56f33d7ec8513de6abb..91e4f6c037661420e5f3e02e30af9174eef9edfd 100644 (file)
@@ -209,8 +209,6 @@ static struct clk_lookup pxa25x_clkregs[] = {
        INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
        INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
        INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
-       INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static struct clk_lookup pxa25x_hwuart_clkreg =
index 180bd8675d4b01a6044b6a32a0301e34c29e98c1..aed6cbcf386641e45147d67cb036301e9a6a54e6 100644 (file)
@@ -230,8 +230,6 @@ static struct clk_lookup pxa27x_clkregs[] = {
        INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
        INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
        INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
-       INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 #ifdef CONFIG_PM
index 0388eda7878aa9ac3490188cc4646c5d357b6733..40bb16501d8601789875c03bbef88dd87519c925 100644 (file)
@@ -89,7 +89,6 @@ static DEFINE_PXA3_CKEN(gcu, PXA300_GCU, 0, 0);
 static struct clk_lookup common_clkregs[] = {
        INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL),
        INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0);
index d487e1ff4c9a45e699f367e5e18be19709cdca17..8d614ecd8e998d3d663187656dd108ca29405e62 100644 (file)
@@ -83,7 +83,6 @@ static DEFINE_PXA3_CKEN(gcu, PXA320_GCU, 0, 0);
 static struct clk_lookup pxa320_clkregs[] = {
        INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL),
        INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static int __init pxa320_init(void)
index f107c71c7589f186918fb1c7e080f84ec067261d..4f402afa6609c0ed584100d951347ec1272f8531 100644 (file)
@@ -67,7 +67,6 @@ static struct clk_lookup pxa3xx_clkregs[] = {
        INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
        /* Power I2C clock is always on */
        INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
        INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
        INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
        INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
index fccc644702e6d4b05b67f75a55b33c7839756dc2..d082a583df78a14c0bc4074db270bb8ce2393ca1 100644 (file)
@@ -217,7 +217,6 @@ static struct clk_lookup pxa95x_clkregs[] = {
        INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
        /* Power I2C clock is always on */
        INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
        INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
        INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
        INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
index ac1aed2a8da4c7a27c84def422a76f51540b45ef..eb55f05bef3a1554b1a65485eed8fd3bb529853a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 
 extern volatile int pen_release;
 
index 794a8d91a6a62110872c1a989f167b10a90f595c..124bce6b4d7ba55df09bc262a3caf2acaf58b0fe 100644 (file)
 #define REALVIEW_EB_USB_BASE           0x4F000000      /* USB */
 
 #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
-#define REALVIEW_EB11MP_SCU_BASE       0x10100000      /* SCU registers */
-#define REALVIEW_EB11MP_GIC_CPU_BASE   0x10100100      /* Generic interrupt controller CPU interface */
-#define REALVIEW_EB11MP_TWD_BASE       0x10100600
-#define REALVIEW_EB11MP_GIC_DIST_BASE  0x10101000      /* Generic interrupt controller distributor */
+#define REALVIEW_EB11MP_PRIV_MEM_BASE  0x1F000000
 #define REALVIEW_EB11MP_L220_BASE      0x10102000      /* L220 registers */
 #define REALVIEW_EB11MP_SYS_PLD_CTRL1  0xD8            /* Register offset for MPCore sysctl */
 #else
-#define REALVIEW_EB11MP_SCU_BASE       0x1F000000      /* SCU registers */
-#define REALVIEW_EB11MP_GIC_CPU_BASE   0x1F000100      /* Generic interrupt controller CPU interface */
-#define REALVIEW_EB11MP_TWD_BASE       0x1F000600
-#define REALVIEW_EB11MP_GIC_DIST_BASE  0x1F001000      /* Generic interrupt controller distributor */
+#define REALVIEW_EB11MP_PRIV_MEM_BASE  0x1F000000
 #define REALVIEW_EB11MP_L220_BASE      0x1F002000      /* L220 registers */
 #define REALVIEW_EB11MP_SYS_PLD_CTRL1  0x74            /* Register offset for MPCore sysctl */
 #endif
 
+#define REALVIEW_EB11MP_PRIV_MEM_SIZE  SZ_8K
+#define REALVIEW_EB11MP_PRIV_MEM_OFF(x)        (REALVIEW_EB11MP_PRIV_MEM_BASE + (x))
+
+#define REALVIEW_EB11MP_SCU_BASE       REALVIEW_EB11MP_PRIV_MEM_OFF(0)         /* SCU registers */
+#define REALVIEW_EB11MP_GIC_CPU_BASE   REALVIEW_EB11MP_PRIV_MEM_OFF(0x0100)    /* Generic interrupt controller CPU interface */
+#define REALVIEW_EB11MP_TWD_BASE       REALVIEW_EB11MP_PRIV_MEM_OFF(0x0600)
+#define REALVIEW_EB11MP_GIC_DIST_BASE  REALVIEW_EB11MP_PRIV_MEM_OFF(0x1000)    /* Generic interrupt controller distributor */
+
 /*
  * Core tile identification (REALVIEW_SYS_PROCID)
  */
index 7abf918b77e9fec5af2f7334e277c2dc82684565..aa2d4e02ea2ca5142558255eef93ca6757f066ef 100644 (file)
@@ -75,6 +75,8 @@
 /*
  * Testchip peripheral and fpga gic regions
  */
+#define REALVIEW_TC11MP_PRIV_MEM_BASE          0x1F000000
+#define REALVIEW_TC11MP_PRIV_MEM_SIZE          SZ_8K
 #define REALVIEW_TC11MP_SCU_BASE               0x1F000000      /* IRQ, Test chip */
 #define REALVIEW_TC11MP_GIC_CPU_BASE           0x1F000100      /* Test chip interrupt controller CPU interface */
 #define REALVIEW_TC11MP_TWD_BASE               0x1F000600
index e83c654a58d0f4540445840e1b7f1af377c12bff..17c878ddbc70d1da5a63b31a6d1bba663841c704 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
-#include <asm/unified.h>
 
 #include <mach/board-eb.h>
 #include <mach/board-pb11mp.h>
@@ -75,6 +74,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
         * until it receives a soft interrupt, and then the
         * secondary CPU branches to this address.
         */
-       __raw_writel(BSYM(virt_to_phys(versatile_secondary_startup)),
+       __raw_writel(virt_to_phys(versatile_secondary_startup),
                     __io_address(REALVIEW_SYS_FLAGSSET));
 }
index e62962117763879cb469c172d7f464b6339608d3..9578145f2df031f33d8e13c277e405073cc3d197 100644 (file)
@@ -91,14 +91,9 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
 
 static struct map_desc realview_eb11mp_io_desc[] __initdata = {
        {
-               .virtual        = IO_ADDRESS(REALVIEW_EB11MP_SCU_BASE),
-               .pfn            = __phys_to_pfn(REALVIEW_EB11MP_SCU_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
-               .pfn            = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
-               .length         = SZ_4K,
+               .virtual        = IO_ADDRESS(REALVIEW_EB11MP_PRIV_MEM_BASE),
+               .pfn            = __phys_to_pfn(REALVIEW_EB11MP_PRIV_MEM_BASE),
+               .length         = REALVIEW_EB11MP_PRIV_MEM_SIZE,
                .type           = MT_DEVICE,
        }, {
                .virtual        = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
index 127a3fd42ab13db2e8430b55166a66df9b46cfae..2147335f66f5d63bcc38772983aff10fb7d27166 100644 (file)
@@ -64,15 +64,10 @@ static struct map_desc realview_pb11mp_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(REALVIEW_PB11MP_GIC_DIST_BASE),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = IO_ADDRESS(REALVIEW_TC11MP_GIC_CPU_BASE),
-               .pfn            = __phys_to_pfn(REALVIEW_TC11MP_GIC_CPU_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = IO_ADDRESS(REALVIEW_TC11MP_GIC_DIST_BASE),
-               .pfn            = __phys_to_pfn(REALVIEW_TC11MP_GIC_DIST_BASE),
-               .length         = SZ_4K,
+       }, {    /* Maps the SCU, GIC CPU interface, TWD, GIC DIST */
+               .virtual        = IO_ADDRESS(REALVIEW_TC11MP_PRIV_MEM_BASE),
+               .pfn            = __phys_to_pfn(REALVIEW_TC11MP_PRIV_MEM_BASE),
+               .length         = REALVIEW_TC11MP_PRIV_MEM_SIZE,
                .type           = MT_DEVICE,
        }, {
                .virtual        = IO_ADDRESS(REALVIEW_SCTL_BASE),
index 7dc6c46b5e2ba4171b204f94513d190cbf855095..5404535da1a5863f8e2a471a1a1c968f2996943d 100644 (file)
@@ -115,7 +115,8 @@ static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
        .debug_io_show  = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
 };
 
-static int s3c2410_cpufreq_add(struct device *dev)
+static int s3c2410_cpufreq_add(struct device *dev,
+                              struct subsys_interface *sif)
 {
        return s3c_cpufreq_register(&s3c2410_cpufreq_info);
 }
@@ -133,7 +134,8 @@ static int __init s3c2410_cpufreq_init(void)
 
 arch_initcall(s3c2410_cpufreq_init);
 
-static int s3c2410a_cpufreq_add(struct device *dev)
+static int s3c2410a_cpufreq_add(struct device *dev,
+                               struct subsys_interface *sif)
 {
        /* alter the maximum freq settings for S3C2410A. If a board knows
         * it only has a maximum of 200, then it should register its own
@@ -144,7 +146,7 @@ static int s3c2410a_cpufreq_add(struct device *dev)
        s3c2410_cpufreq_info.max.pclk =  66500000;
        s3c2410_cpufreq_info.name = "s3c2410a";
 
-       return s3c2410_cpufreq_add(dev);
+       return s3c2410_cpufreq_add(dev, sif);
 }
 
 static struct subsys_interface s3c2410a_cpufreq_interface = {
index 2afd00014a77f0aa05db8368a689794f0ed172e5..4803338cf56e07960dec40f97603dbd2d34e3072 100644 (file)
@@ -132,7 +132,8 @@ static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
        },
 };
 
-static int __init s3c2410_dma_add(struct device *dev)
+static int __init s3c2410_dma_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        s3c2410_dma_init();
        s3c24xx_dma_order_set(&s3c2410_dma_order);
@@ -148,7 +149,7 @@ static struct subsys_interface s3c2410_dma_interface = {
 
 static int __init s3c2410_dma_drvinit(void)
 {
-       return subsys_interface_register(&s3c2410_interface);
+       return subsys_interface_register(&s3c2410_dma_interface);
 }
 
 arch_initcall(s3c2410_dma_drvinit);
index c07438bfc99f4da3a4df64989c01ffca7aef8a5c..e0b3b347da82c38f1699ba279644e5d6a1da2bdf 100644 (file)
@@ -66,7 +66,7 @@ static struct cpufreq_frequency_table pll_vals_12MHz[] = {
     { .frequency = 270000000, .index = PLLVAL(127, 1, 1),  },
 };
 
-static int s3c2410_plls_add(struct device *dev)
+static int s3c2410_plls_add(struct device *dev, struct subsys_interface *sif)
 {
        return s3c_plltab_register(pll_vals_12MHz, ARRAY_SIZE(pll_vals_12MHz));
 }
index fda5385deff6f7e90800fa91006f472726705b86..03f706dd6009a2f21b5910991c4e228351529ba7 100644 (file)
@@ -111,7 +111,7 @@ struct syscore_ops s3c2410_pm_syscore_ops = {
        .resume         = s3c2410_pm_resume,
 };
 
-static int s3c2410_pm_add(struct device *dev)
+static int s3c2410_pm_add(struct device *dev, struct subsys_interface *sif)
 {
        pm_cpu_prep = s3c2410_pm_prepare;
        pm_cpu_sleep = s3c2410_cpu_suspend;
index d8664b7652ce3301bdc3e1317afd9f18b8133d3b..125be7d5fa601eefa2c911d2642589bbae24b550 100644 (file)
@@ -194,7 +194,8 @@ static struct s3c_cpufreq_info s3c2412_cpufreq_info = {
        .debug_io_show  = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs),
 };
 
-static int s3c2412_cpufreq_add(struct device *dev)
+static int s3c2412_cpufreq_add(struct device *dev,
+                              struct subsys_interface *sif)
 {
        unsigned long fclk_rate;
 
index 142acd3b5e1558280a4b574e9bdadebc4e230a2f..38472ac920ff16b13b2ae21c0e82e010dd4311a6 100644 (file)
@@ -159,7 +159,8 @@ static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
        .map_size       = ARRAY_SIZE(s3c2412_dma_mappings),
 };
 
-static int __init s3c2412_dma_add(struct device *dev)
+static int __init s3c2412_dma_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        s3c2410_dma_init();
        return s3c24xx_dma_init_map(&s3c2412_dma_sel);
index a8a46c1644f460040bf50cf1cf2a1aed78c1d1c2..e65619ddbccc3c1398a427b4bfb7d26689a68799 100644 (file)
@@ -170,7 +170,7 @@ static int s3c2412_irq_rtc_wake(struct irq_data *data, unsigned int state)
 
 static struct irq_chip s3c2412_irq_rtc_chip;
 
-static int s3c2412_irq_add(struct device *dev)
+static int s3c2412_irq_add(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int irqno;
 
index d1adfa65f66da97ca0bd356d391644aa1801c607..d04588506ec401a99f7eddae63b2d1932d47d47c 100644 (file)
@@ -56,7 +56,7 @@ static void s3c2412_pm_prepare(void)
 {
 }
 
-static int s3c2412_pm_add(struct device *dev)
+static int s3c2412_pm_add(struct device *dev, struct subsys_interface *sif)
 {
        pm_cpu_prep = s3c2412_pm_prepare;
        pm_cpu_sleep = s3c2412_cpu_suspend;
index 36df761061deffcea6f04c73cc584f169d062c2e..fd49f35e448ec7090098a4293493df7ee8a32f86 100644 (file)
@@ -213,7 +213,8 @@ static int __init s3c2416_add_sub(unsigned int base,
        return 0;
 }
 
-static int __init s3c2416_irq_add(struct device *dev)
+static int __init s3c2416_irq_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        printk(KERN_INFO "S3C2416: IRQ Support\n");
 
index 3bdb15a0d419ce805c8bb7819b2adb534a0bce17..1bd4817b8eb8bef37a762e9fa870a1b8900522d5 100644 (file)
@@ -48,7 +48,7 @@ static void s3c2416_pm_prepare(void)
        __raw_writel(virt_to_phys(s3c_cpu_resume), S3C2412_INFORM1);
 }
 
-static int s3c2416_pm_add(struct device *dev)
+static int s3c2416_pm_add(struct device *dev, struct subsys_interface *sif)
 {
        pm_cpu_prep = s3c2416_pm_prepare;
        pm_cpu_sleep = s3c2416_cpu_suspend;
index bedbc87a3426fb2b9f6c1c83126bf1b021ce4289..414364eb426cf70d58a439b7e99b15e26c91a0c7 100644 (file)
@@ -149,7 +149,7 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
 };
 
-static int s3c2440_clk_add(struct device *dev)
+static int s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
 {
        struct clk *clock_upll;
        struct clk *clock_h;
index 15b1ddf8f6266177099f757499d045b575b8eb7f..5f0a0c8ef84fdbc8066aab37898db9ebbf4c4024 100644 (file)
@@ -174,7 +174,8 @@ static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
        },
 };
 
-static int __init s3c2440_dma_add(struct device *dev)
+static int __init s3c2440_dma_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        s3c2410_dma_init();
        s3c24xx_dma_order_set(&s3c2440_dma_order);
index 4fee9bc6bcb51e5f0d025fb34912b8a455ceeb93..4a18cde439cc1d54854d73524b12f75b60beca72 100644 (file)
@@ -92,7 +92,7 @@ static struct irq_chip s3c_irq_wdtac97 = {
        .irq_ack        = s3c_irq_wdtac97_ack,
 };
 
-static int s3c2440_irq_add(struct device *dev)
+static int s3c2440_irq_add(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int irqno;
 
index cf7596694efe07ec37eead10bc1e2932a92342f2..61776764d9f49eb3e0222fff76a8db387e51b4ed 100644 (file)
@@ -270,7 +270,8 @@ struct s3c_cpufreq_info s3c2440_cpufreq_info = {
        .debug_io_show  = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
 };
 
-static int s3c2440_cpufreq_add(struct device *dev)
+static int s3c2440_cpufreq_add(struct device *dev,
+                              struct subsys_interface *sif)
 {
        xtal = s3c_cpufreq_clk_get(NULL, "xtal");
        hclk = s3c_cpufreq_clk_get(NULL, "hclk");
index b5368ae8d7fe2e7a5b98ccb44f1045d9dfa6faa2..551fb433be871379af8a8db64d29657757bc05d8 100644 (file)
@@ -51,7 +51,7 @@ static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = {
        { .frequency = 400000000,       .index = PLLVAL(0x5c, 1, 1),  },        /* FVco 800.000000 */
 };
 
-static int s3c2440_plls12_add(struct device *dev)
+static int s3c2440_plls12_add(struct device *dev, struct subsys_interface *sif)
 {
        struct clk *xtal_clk;
        unsigned long xtal;
index 42f2b5cd23998bb27243485d3ebd60ac4d0304ae..3f15bcf642900c4a83f39ca11c4bd945974d24f7 100644 (file)
@@ -79,7 +79,8 @@ static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = {
        { .frequency = 402192000,       .index = PLLVAL(87, 2, 1),      },      /* FVco 804.384000 */
 };
 
-static int s3c2440_plls169344_add(struct device *dev)
+static int s3c2440_plls169344_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        struct clk *xtal_clk;
        unsigned long xtal;
index 8004e0497bf4e262cc52cf903b0bf49fcb026f9b..22cb7c94a8c8880d81b987f132acca9b39352bef 100644 (file)
@@ -122,7 +122,7 @@ static struct clk s3c2442_clk_cam_upll = {
        },
 };
 
-static int s3c2442_clk_add(struct device *dev)
+static int s3c2442_clk_add(struct device *dev, struct subsys_interface *sif)
 {
        struct clk *clock_upll;
        struct clk *clock_h;
index b3fdbdda3d5f368fe44e74b4a1c2f476b76c6622..6d9b688c442bd649f81bf93ef897cb295fc0f091 100644 (file)
@@ -72,7 +72,7 @@ static struct clk clk_arm = {
        },
 };
 
-static int s3c244x_clk_add(struct device *dev)
+static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif)
 {
        unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
        unsigned long clkdivn;
index 74d3dcf46a48ca30613cca2a06ef7c964d45f6c8..5fe8e58d3afdb5a5c6f7d1d40e621ed383b0dd42 100644 (file)
@@ -91,7 +91,7 @@ static struct irq_chip s3c_irq_cam = {
        .irq_ack        = s3c_irq_cam_ack,
 };
 
-static int s3c244x_irq_add(struct device *dev)
+static int s3c244x_irq_add(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int irqno;
 
index de6b4a23c9edb02b839ef53f01c7f0facf5a6320..14224517e6210d3010789ad45e7716116d8c015a 100644 (file)
@@ -135,7 +135,8 @@ static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
        .map_size       = ARRAY_SIZE(s3c2443_dma_mappings),
 };
 
-static int __init s3c2443_dma_add(struct device *dev)
+static int __init s3c2443_dma_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
        return s3c24xx_dma_init_map(&s3c2443_dma_sel);
index 35e4ff24fb43f89c9cc5c162efd9df04572d0c30..ac2829f56d1277d3437b2c85a1043097c766282b 100644 (file)
@@ -241,7 +241,8 @@ static int __init s3c2443_add_sub(unsigned int base,
        return 0;
 }
 
-static int __init s3c2443_irq_add(struct device *dev)
+static int __init s3c2443_irq_add(struct device *dev,
+                                 struct subsys_interface *sif)
 {
        printk("S3C2443: IRQ Support\n");
 
index 31bb27dc4aeba8ace23ad4a8bdb80df742657085..aebbcc291b4e2ae35c5d8dee6035002fa038bd49 100644 (file)
@@ -138,6 +138,11 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = S3C_CLKCON_PCLK_TSADC,
        }, {
                .name           = "i2c",
+#ifdef CONFIG_S3C_DEV_I2C1
+               .devname        = "s3c2440-i2c.0",
+#else
+               .devname        = "s3c2440-i2c",
+#endif
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_IIC,
index 4a7394d4bd9ea0e2f79fbb2af25a19c862cf7257..bee7dcd4df7c34ad8fb381173d1a7250a80b418a 100644 (file)
@@ -49,7 +49,7 @@
 
 /* uart registration process */
 
-void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
        s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
 }
index 5d55ab018b6b3f74b1946a67d0efd84a534e3caf..4cb2f951f1e9155d9b4434fac10ff4ea330e9039 100644 (file)
@@ -21,5 +21,6 @@
 #define CODEC_GPIO_BASE                        (GPIO_BOARD_START + 8)
 #define GLENFARCLAS_PMIC_GPIO_BASE     (GPIO_BOARD_START + 32)
 #define BANFF_PMIC_GPIO_BASE           (GPIO_BOARD_START + 64)
+#define MMGPIO_GPIO_BASE               (GPIO_BOARD_START + 96)
 
 #endif
index 1cc91d794c973e538e52a9678bff72fa4e1b8d0e..8077f650eb0e6c291ac607aff70a02b35dfa62b8 100644 (file)
@@ -260,6 +260,7 @@ static struct platform_device crag6410_dm9k_device = {
 
 static struct resource crag6410_mmgpio_resource[] = {
        [0] = {
+               .name   = "dat",
                .start  = S3C64XX_PA_XM0CSN4 + 1,
                .end    = S3C64XX_PA_XM0CSN4 + 1,
                .flags  = IORESOURCE_MEM,
@@ -272,7 +273,7 @@ static struct platform_device crag6410_mmgpio = {
        .resource       = crag6410_mmgpio_resource,
        .num_resources  = ARRAY_SIZE(crag6410_mmgpio_resource),
        .dev.platform_data = &(struct bgpio_pdata) {
-               .base   = -1,
+               .base   = MMGPIO_GPIO_BASE,
        },
 };
 
@@ -328,7 +329,6 @@ static struct platform_device wallvdd_device = {
 
 static struct platform_device *crag6410_devices[] __initdata = {
        &s3c_device_hsmmc0,
-       &s3c_device_hsmmc1,
        &s3c_device_hsmmc2,
        &s3c_device_i2c0,
        &s3c_device_i2c1,
@@ -355,7 +355,7 @@ static struct platform_device *crag6410_devices[] __initdata = {
 
 static struct pca953x_platform_data crag6410_pca_data = {
        .gpio_base      = PCA935X_GPIO_BASE,
-       .irq_base       = 0,
+       .irq_base       = -1,
 };
 
 /* VDDARM is controlled by DVS1 connected to GPK(0) */
@@ -683,12 +683,6 @@ static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
 };
 
-static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
-       .max_width              = 4,
-       .cd_type                = S3C_SDHCI_CD_GPIO,
-       .ext_cd_gpio            = S3C64XX_GPF(11),
-};
-
 static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
 {
        /* Set all the necessary GPG pins to special-function 2 */
@@ -723,7 +717,6 @@ static void __init crag6410_machine_init(void)
        gpio_direction_output(S3C64XX_GPF(10), 1);
 
        s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
-       s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
        s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
 
        s3c_i2c0_set_platdata(&i2c0_pdata);
index 055dac90e0e247c95258ecd412e47bb2297de1cc..7d3e81b9dd06229034603aa260064384d8d44a5d 100644 (file)
@@ -346,23 +346,10 @@ int __init s3c64xx_pm_init(void)
 
 static __init int s3c64xx_pm_initcall(void)
 {
-       u32 val;
-
        pm_cpu_prep = s3c64xx_pm_prepare;
        pm_cpu_sleep = s3c64xx_cpu_suspend;
        pm_uart_udivslot = 1;
 
-       /*
-        * Unconditionally disable power domains that contain only
-        * blocks which have no mainline driver support.
-        */
-       val = __raw_readl(S3C64XX_NORMAL_CFG);
-       val &= ~(S3C64XX_NORMALCFG_DOMAIN_G_ON |
-                S3C64XX_NORMALCFG_DOMAIN_V_ON |
-                S3C64XX_NORMALCFG_DOMAIN_I_ON |
-                S3C64XX_NORMALCFG_DOMAIN_P_ON);
-       __raw_writel(val, S3C64XX_NORMAL_CFG);
-
 #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
        gpio_request(S3C64XX_GPN(12), "DEBUG_LED0");
        gpio_request(S3C64XX_GPN(13), "DEBUG_LED1");
index 23f9b22439c955863430198cb32b2f66c6a52854..9cba18bfe47bbd56bc197518fdd48496f5980664 100644 (file)
@@ -160,7 +160,7 @@ static void s5p64x0_pm_prepare(void)
 
 }
 
-static int s5p64x0_pm_add(struct device *dev)
+static int s5p64x0_pm_add(struct device *dev, struct subsys_interface *sif)
 {
        pm_cpu_prep = s5p64x0_pm_prepare;
        pm_cpu_sleep = s5p64x0_cpu_suspend;
index c78dfddd77fd374f0377e1c6694ce594ebe5bd98..b9ec0c35379f572ebf63fc9dd4d2af97c5a0d377 100644 (file)
@@ -175,7 +175,7 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
 }
 
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+static int s5pv210_clk_hdmiphy_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
 }
@@ -372,7 +372,7 @@ static struct clk init_clocks_off[] = {
        }, {
                .name           = "hdmiphy",
                .devname        = "s5pv210-hdmi",
-               .enable         = exynos4_clk_hdmiphy_ctrl,
+               .enable         = s5pv210_clk_hdmiphy_ctrl,
                .ctrlbit        = (1 << 0),
        }, {
                .name           = "dacphy",
index 677c71c41e50fc1830b99556ea8d429e24db31ef..736bfb103cbc4acc3e38f057bd018cc841e2b420 100644 (file)
@@ -133,7 +133,7 @@ static void s5pv210_pm_prepare(void)
        s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
 }
 
-static int s5pv210_pm_add(struct device *dev)
+static int s5pv210_pm_add(struct device *dev, struct subsys_interface *sif)
 {
        pm_cpu_prep = s5pv210_pm_prepare;
        pm_cpu_sleep = s5pv210_cpu_suspend;
index ebafe8aa8956e1d9f7e24987e777ce7d87f27369..0c4b76ab4d8eba0037e305d5d8f9b17b36074fa7 100644 (file)
@@ -202,7 +202,6 @@ static struct irda_platform_data assabet_irda_data = {
 static struct mcp_plat_data assabet_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
-       .codec          = "ucb1x00",
 };
 
 static void __init assabet_init(void)
@@ -253,17 +252,6 @@ static void __init assabet_init(void)
        sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
                            ARRAY_SIZE(assabet_flash_resources));
        sa11x0_register_irda(&assabet_irda_data);
-
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
-       ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
        sa11x0_register_mcp(&assabet_mcp_data);
 }
 
index d12d0f48b1dc4bec59f9a9939edc6c93e5f3ddcb..11bb6d0b9be377b6c926f3e759a03a21d2e9ffff 100644 (file)
@@ -124,23 +124,12 @@ static void __init cerf_map_io(void)
 static struct mcp_plat_data cerf_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
-       .codec          = "ucb1x00",
 };
 
 static void __init cerf_init(void)
 {
        platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
        sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
-
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
        sa11x0_register_mcp(&cerf_mcp_data);
 }
 
index d6df9f6c9f7e42d9d9d06a1401c89bc5a47b246d..dab3c6347a8f2d8e80bafba18b6916f8f97161f9 100644 (file)
 #include <linux/clk.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 
-struct clkops {
-       void                    (*enable)(struct clk *);
-       void                    (*disable)(struct clk *);
-       unsigned long           (*getrate)(struct clk *);
-};
-
+/*
+ * Very simple clock implementation - we only have one clock to deal with.
+ */
 struct clk {
-       const struct clkops     *ops;
-       unsigned long           rate;
        unsigned int            enabled;
 };
 
-#define INIT_CLKREG(_clk, _devname, _conname)          \
-       {                                               \
-               .clk            = _clk,                 \
-               .dev_id         = _devname,             \
-               .con_id         = _conname,             \
-       }
-
-#define DEFINE_CLK(_name, _ops, _rate)                 \
-struct clk clk_##_name = {                             \
-               .ops    = _ops,                         \
-               .rate   = _rate,                        \
-       }
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void clk_gpio27_enable(struct clk *clk)
+static void clk_gpio27_enable(void)
 {
        /*
         * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@@ -54,22 +32,38 @@ static void clk_gpio27_enable(struct clk *clk)
        TUCR = TUCR_3_6864MHz;
 }
 
-static void clk_gpio27_disable(struct clk *clk)
+static void clk_gpio27_disable(void)
 {
        TUCR = 0;
        GPDR &= ~GPIO_32_768kHz;
        GAFR &= ~GPIO_32_768kHz;
 }
 
+static struct clk clk_gpio27;
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       const char *devname = dev_name(dev);
+
+       return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
 int clk_enable(struct clk *clk)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&clocks_lock, flags);
        if (clk->enabled++ == 0)
-               clk->ops->enable(clk);
+               clk_gpio27_enable();
        spin_unlock_irqrestore(&clocks_lock, flags);
-
        return 0;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -82,48 +76,13 @@ void clk_disable(struct clk *clk)
 
        spin_lock_irqsave(&clocks_lock, flags);
        if (--clk->enabled == 0)
-               clk->ops->disable(clk);
+               clk_gpio27_disable();
        spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
 unsigned long clk_get_rate(struct clk *clk)
 {
-       unsigned long rate;
-
-       rate = clk->rate;
-       if (clk->ops->getrate)
-               rate = clk->ops->getrate(clk);
-
-       return rate;
+       return 3686400;
 }
 EXPORT_SYMBOL(clk_get_rate);
-
-const struct clkops clk_gpio27_ops = {
-       .enable         = clk_gpio27_enable,
-       .disable        = clk_gpio27_disable,
-};
-
-static void clk_dummy_enable(struct clk *clk) { }
-static void clk_dummy_disable(struct clk *clk) { }
-
-const struct clkops clk_dummy_ops = {
-       .enable         = clk_dummy_enable,
-       .disable        = clk_dummy_disable,
-};
-
-static DEFINE_CLK(gpio27, &clk_gpio27_ops, 3686400);
-static DEFINE_CLK(dummy, &clk_dummy_ops, 0);
-
-static struct clk_lookup sa11xx_clkregs[] = {
-       INIT_CLKREG(&clk_gpio27, "sa1111.0", NULL),
-       INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
-};
-
-static int __init sa11xx_clk_init(void)
-{
-       clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
-       return 0;
-}
-
-postcore_initcall(sa11xx_clk_init);
index c483912d08af4535ce964992a19d66f511c80c21..fd5652118ed19565d5754ffdd16f1cfe0db59011 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/timer.h>
 #include <linux/gpio.h>
 #include <linux/pda_power.h>
-#include <linux/mfd/ucb1x00.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -86,15 +85,10 @@ static struct scoop_pcmcia_config collie_pcmcia_config = {
        .num_devs       = 1,
 };
 
-static struct ucb1x00_plat_data collie_ucb1x00_data = {
-       .gpio_base      = COLLIE_TC35143_GPIO_BASE,
-};
-
 static struct mcp_plat_data collie_mcp_data = {
        .mccr0          = MCCR0_ADM | MCCR0_ExtClk,
        .sclk_rate      = 9216000,
-       .codec          = "ucb1x00",
-       .codec_pdata    = &collie_ucb1x00_data,
+       .gpio_base      = COLLIE_TC35143_GPIO_BASE,
 };
 
 /*
@@ -144,8 +138,6 @@ static struct pda_power_pdata collie_power_data = {
 static struct resource collie_power_resource[] = {
        {
                .name           = "ac",
-               .start          = gpio_to_irq(COLLIE_GPIO_AC_IN),
-               .end            = gpio_to_irq(COLLIE_GPIO_AC_IN),
                .flags          = IORESOURCE_IRQ |
                                  IORESOURCE_IRQ_HIGHEDGE |
                                  IORESOURCE_IRQ_LOWEDGE,
@@ -347,7 +339,8 @@ static void __init collie_init(void)
 
        GPSR |= _COLLIE_GPIO_UCB1x00_RESET;
 
-
+       collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN);
+       collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN);
        platform_scoop_config = &collie_pcmcia_config;
 
        ret = platform_add_devices(devices, ARRAY_SIZE(devices));
@@ -357,16 +350,6 @@ static void __init collie_init(void)
 
        sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
                            ARRAY_SIZE(collie_flash_resources));
-
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
        sa11x0_register_mcp(&collie_mcp_data);
 
        sharpsl_save_param();
index aaa8acf76b7b551e29af1e1d04f38f6bba970b2c..19b2053f5af4146a68184ce4c40571cfa3353e67 100644 (file)
@@ -228,7 +228,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct cpufreq_driver sa1100_driver = {
+static struct cpufreq_driver sa1100_driver __refdata = {
        .flags          = CPUFREQ_STICKY,
        .verify         = sa11x0_verify_speed,
        .target         = sa1100_target,
index e3a28ca2a7b754fff9b095eb5c58e113525b16df..bb10ee2cb89f11f82c801d7f9c1d8ced11c1c3b7 100644 (file)
@@ -217,15 +217,10 @@ static struct platform_device sa11x0uart3_device = {
 static struct resource sa11x0mcp_resources[] = {
        [0] = {
                .start  = __PREG(Ser4MCCR0),
-               .end    = __PREG(Ser4MCCR0) + 0x1C - 1,
+               .end    = __PREG(Ser4MCCR0) + 0xffff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = __PREG(Ser4MCCR1),
-               .end    = __PREG(Ser4MCCR1) + 0x4 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
                .start  = IRQ_Ser4MCP,
                .end    = IRQ_Ser4MCP,
                .flags  = IORESOURCE_IRQ,
@@ -350,29 +345,9 @@ void sa11x0_register_irda(struct irda_platform_data *irda)
        sa11x0_register_device(&sa11x0ir_device, irda);
 }
 
-static struct resource sa11x0rtc_resources[] = {
-       [0] = {
-               .start  = 0x90010000,
-               .end    = 0x900100ff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_RTC1Hz,
-               .end    = IRQ_RTC1Hz,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = IRQ_RTCAlrm,
-               .end    = IRQ_RTCAlrm,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
 static struct platform_device sa11x0rtc_device = {
        .name           = "sa1100-rtc",
        .id             = -1,
-       .resource       = sa11x0rtc_resources,
-       .num_resources  = ARRAY_SIZE(sa11x0rtc_resources),
 };
 
 static struct platform_device *sa11x0_devices[] __initdata = {
index 586cec898b35ae8578025727e3ec4e2b679964e0..ed1a331508a754bf2e802f537689a97ee2b524c5 100644 (file)
@@ -17,8 +17,6 @@ struct mcp_plat_data {
        u32 mccr1;
        unsigned int sclk_rate;
        int gpio_base;
-       const char *codec;
-       void *codec_pdata;
 };
 
 #endif
index f50b00bd18a053603f98b77a5e25678b11f25b96..b412fc09c80cb30038e513c1b44021d1dabb42ff 100644 (file)
@@ -198,3 +198,5 @@ static int __init jornada_ssp_init(void)
 {
        return platform_driver_register(&jornadassp_driver);
 }
+
+module_init(jornada_ssp_init);
index d117ceab6215c4f8d814504aa313bacf17460b45..af4e2761f3dbf4a6254bfab53f98080334e5f387 100644 (file)
 static struct mcp_plat_data lart_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
-       .codec          = "ucb1x00",
 };
 
 static void __init lart_init(void)
 {
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
        sa11x0_register_mcp(&lart_mcp_data);
 }
 
index 748d34435b3f070000f2afcfc420253d85ccb060..318b2b766a0b3ee7b8921c2904b65c0fdd551c8c 100644 (file)
@@ -55,22 +55,11 @@ static struct resource shannon_flash_resource = {
 static struct mcp_plat_data shannon_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
-       .codec          = "ucb1x00",
 };
 
 static void __init shannon_init(void)
 {
        sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1);
-
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
        sa11x0_register_mcp(&shannon_mcp_data);
 }
 
index 458ececefa58a122332de40798d3df7aae3d1ea2..e17c04d6e32428af6aa7c8eb1fbc35ca6d7a02d8 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
-#include <linux/mfd/ucb1x00.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -188,15 +187,10 @@ static struct resource simpad_flash_resources [] = {
        }
 };
 
-static struct ucb1x00_plat_data simpad_ucb1x00_data = {
-       .gpio_base      = SIMPAD_UCB1X00_GPIO_BASE,
-};
-
 static struct mcp_plat_data simpad_mcp_data = {
        .mccr0          = MCCR0_ADM,
        .sclk_rate      = 11981000,
-       .codec          = "ucb1300",
-       .codec_pdata    = &simpad_ucb1x00_data,
+       .gpio_base      = SIMPAD_UCB1X00_GPIO_BASE,
 };
 
 
@@ -384,16 +378,6 @@ static int __init simpad_init(void)
 
        sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
                              ARRAY_SIZE(simpad_flash_resources));
-
-       /*
-        * Setup the PPC unit correctly.
-        */
-       PPDR &= ~PPC_RXD4;
-       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-       PSDR |= PPC_RXD4;
-       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
        sa11x0_register_mcp(&simpad_mcp_data);
 
        ret = platform_add_devices(devices, ARRAY_SIZE(devices));
index 1ea89be63e29e1d13e7783d0d7f2ff31f64057a9..a83cf51fc09906a13018472b4f563baebaf7bcb5 100644 (file)
@@ -445,31 +445,39 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
        },
 };
 
+#define SH7372_CHCLR 0x220
+
 static const struct sh_dmae_channel sh7372_dmae_channels[] = {
        {
                .offset = 0,
                .dmars = 0,
                .dmars_bit = 0,
+               .chclr_offset = SH7372_CHCLR + 0,
        }, {
                .offset = 0x10,
                .dmars = 0,
                .dmars_bit = 8,
+               .chclr_offset = SH7372_CHCLR + 0x10,
        }, {
                .offset = 0x20,
                .dmars = 4,
                .dmars_bit = 0,
+               .chclr_offset = SH7372_CHCLR + 0x20,
        }, {
                .offset = 0x30,
                .dmars = 4,
                .dmars_bit = 8,
+               .chclr_offset = SH7372_CHCLR + 0x30,
        }, {
                .offset = 0x50,
                .dmars = 8,
                .dmars_bit = 0,
+               .chclr_offset = SH7372_CHCLR + 0x50,
        }, {
                .offset = 0x60,
                .dmars = 8,
                .dmars_bit = 8,
+               .chclr_offset = SH7372_CHCLR + 0x60,
        }
 };
 
@@ -487,6 +495,7 @@ static struct sh_dmae_pdata dma_platform_data = {
        .ts_shift       = ts_shift,
        .ts_shift_num   = ARRAY_SIZE(ts_shift),
        .dmaor_init     = DMAOR_DME,
+       .chclr_present  = 1,
 };
 
 /* Resource order important! */
@@ -494,7 +503,7 @@ static struct resource sh7372_dmae0_resources[] = {
        {
                /* Channel registers and DMAOR */
                .start  = 0xfe008020,
-               .end    = 0xfe00808f,
+               .end    = 0xfe00828f,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -522,7 +531,7 @@ static struct resource sh7372_dmae1_resources[] = {
        {
                /* Channel registers and DMAOR */
                .start  = 0xfe018020,
-               .end    = 0xfe01808f,
+               .end    = 0xfe01828f,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -550,7 +559,7 @@ static struct resource sh7372_dmae2_resources[] = {
        {
                /* Channel registers and DMAOR */
                .start  = 0xfe028020,
-               .end    = 0xfe02808f,
+               .end    = 0xfe02828f,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -653,6 +662,7 @@ static struct sh_dmae_pdata usb_dma0_platform_data = {
        .dmaor_is_32bit = 1,
        .needs_tend_set = 1,
        .no_dmars       = 1,
+       .slave_only     = 1,
 };
 
 static struct resource sh7372_usb_dmae0_resources[] = {
@@ -714,6 +724,7 @@ static struct sh_dmae_pdata usb_dma1_platform_data = {
        .dmaor_is_32bit = 1,
        .needs_tend_set = 1,
        .no_dmars       = 1,
+       .slave_only     = 1,
 };
 
 static struct resource sh7372_usb_dmae1_resources[] = {
index cc97ef892d1b337e1e056f6172196860a6e00dc8..4fe2e9eaf5016e643aec46e6e1652828ad9e3ea9 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <mach/common.h>
 #include <mach/r8a7779.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/gic.h>
index be1ade76ccc81bb580523df640e2a3522638d510..0d159d64a34521a90b6b5f16ba14a8d294c5264f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <mach/common.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/gic.h>
index fcf4f377b1dcf0e99d11fdf62f228a1f05b1dda1..330afdfa24754ae773238f45f855db0407c7dd57 100644 (file)
@@ -60,9 +60,9 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
                .uartclk        = 216000000,
        }, {
                /* serial port on mini-pcie */
-               .membase        = IO_ADDRESS(TEGRA_UARTD_BASE),
-               .mapbase        = TEGRA_UARTD_BASE,
-               .irq            = INT_UARTD,
+               .membase        = IO_ADDRESS(TEGRA_UARTC_BASE),
+               .mapbase        = TEGRA_UARTC_BASE,
+               .irq            = INT_UARTC,
                .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
                .type           = PORT_TEGRA,
                .iotype         = UPIO_MEM,
@@ -174,7 +174,7 @@ static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
 static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
        /* name         parent          rate            enabled */
        { "uarta",      "pll_p",        216000000,      true },
-       { "uartd",      "pll_p",        216000000,      true },
+       { "uartc",      "pll_p",        216000000,      true },
 
        { "pll_p_out4", "pll_p",        24000000,       true },
        { "usbd",       "clk_m",        12000000,       false },
index ffa83f580db6740289fe0ee00ef1a77a1cf8910b..3c9f8da37ea3ce16de68b760bf87223585e15cff 100644 (file)
@@ -22,7 +22,7 @@
 /* SDCARD */
 #define TEGRA_GPIO_SD1_CD              TEGRA_GPIO_PV5
 #define TEGRA_GPIO_SD1_WP              TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD1_POWER           TEGRA_GPIO_PT3
+#define TEGRA_GPIO_SD1_POWER           TEGRA_GPIO_PV1
 
 /* ULPI */
 #define TEGRA_ULPI_RST                 TEGRA_GPIO_PV0
index d0132e8031a1fca5e874403d5343fc05ce293a9b..3c9339058bec1bdcb7435f30e137870e059e1469 100644 (file)
 
 #include <linux/list.h>
 
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
-
-struct tegra_dma_req;
-struct tegra_dma_channel;
-
 #define TEGRA_DMA_REQ_SEL_CNTR                 0
 #define TEGRA_DMA_REQ_SEL_I2S_2                        1
 #define TEGRA_DMA_REQ_SEL_I2S_1                        2
@@ -56,6 +51,11 @@ struct tegra_dma_channel;
 #define TEGRA_DMA_REQ_SEL_OWR                  25
 #define TEGRA_DMA_REQ_SEL_INVALID              31
 
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+
+struct tegra_dma_req;
+struct tegra_dma_channel;
+
 enum tegra_dma_mode {
        TEGRA_DMA_SHARED = 1,
        TEGRA_DMA_MODE_CONTINOUS = 2,
index a3e0c8692f0d1ddabd689f35c86f6e358c5d49ba..52af00446a6335ff9fd5bb1fccbd9a3d8805caae 100644 (file)
@@ -7,6 +7,7 @@ config UX500_SOC_COMMON
        select HAS_MTU
        select ARM_ERRATA_753970
        select ARM_ERRATA_754322
+       select ARM_ERRATA_764369
 
 menu "Ux500 SoC"
 
index 23be34b3bb6e8a9f2e41547c2d18b724c1a17609..5dde4d4ebe882f37a6d826f008c5ffd4666c5a36 100644 (file)
@@ -261,6 +261,8 @@ void __init mop500_sdi_init(void)
 
 void __init snowball_sdi_init(void)
 {
+       /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
+       mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED;
        /* On-board eMMC */
        db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
        /* External Micro SD slot */
index 122ddde00ba78deabf82db84273705598ffda34e..da5569d83d58d87216438bf65aa15de86a6f71ea 100644 (file)
 
 static void __iomem *l2x0_base;
 
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
-       /* wait for the operation to complete */
-       while (readl_relaxed(reg) & mask)
-               cpu_relax();
-}
-
-static inline void ux500_cache_sync(void)
-{
-       writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
-       ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
-       uint32_t l2x0_way_mask = (1<<16) - 1;   /* Bitmask of active ways */
-
-       /* invalidate all ways */
-       writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
-       ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
-       ux500_cache_sync();
-}
-
 static int __init ux500_l2x0_unlock(void)
 {
        int i;
@@ -85,9 +47,13 @@ static int __init ux500_l2x0_init(void)
        /* 64KB way size, 8 way associativity, force WA */
        l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
 
-       /* Override invalidate function */
-       outer_cache.disable = ux500_l2x0_disable;
-       outer_cache.inv_all = ux500_l2x0_inv_all;
+       /*
+        * We can't disable l2 as we are in non secure mode, currently
+        * this seems be called only during kexec path. So let's
+        * override outer.disable with nasty assignment until we have
+        * some SMI service available.
+        */
+       outer_cache.disable = NULL;
 
        return 0;
 }
index 64fa451edcfd486bdbaa0163f55e93399597d8ed..08da5589bcd8a60179cc458dba05f735ea6f919f 100644 (file)
@@ -32,6 +32,8 @@ pen:  ldr     r7, [r6]
         * should now contain the SVC stack for this core
         */
        b       secondary_startup
+ENDPROC(u8500_secondary_startup)
 
+       .align 2
 1:     .long   .
        .long   pen_release
index 572015e57cd997f6b355de1a835404a94df12abc..c76f0f456f045d8baaaf2c9b228633f98d63186d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 
 extern volatile int pen_release;
 
index a19e398dade35d6e9c14c75da381f89d3a3420a2..d2058ef8345fd4518874d2ab409ae3daa376d5df 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/gic.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
index 0a01cbdfe06339492c8aa21632d3223af3bf4ef1..9f9e1c203061dc8cbe0cff19cd69420462b05810 100644 (file)
@@ -95,13 +95,7 @@ static struct musb_hdrc_config musb_hdrc_config = {
 };
 
 static struct musb_hdrc_platform_data musb_platform_data = {
-#if defined(CONFIG_USB_MUSB_OTG)
        .mode = MUSB_OTG,
-#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
-       .mode = MUSB_PERIPHERAL,
-#else /* defined(CONFIG_USB_MUSB_HOST) */
-       .mode = MUSB_HOST,
-#endif
        .config = &musb_hdrc_config,
        .board_data = &musb_board_data,
 };
index 2b1e836a76ed77b7f39eaeaecfdd67ab2d3832f0..b1e87c184e54b3a0f3096353871bdf6f00d97027 100644 (file)
@@ -217,7 +217,7 @@ static void __init ct_ca9x4_init(void)
 }
 
 #ifdef CONFIG_SMP
-static void ct_ca9x4_init_cpu_map(void)
+static void __init ct_ca9x4_init_cpu_map(void)
 {
        int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
 
@@ -233,7 +233,7 @@ static void ct_ca9x4_init_cpu_map(void)
        set_smp_cross_call(gic_raise_softirq);
 }
 
-static void ct_ca9x4_smp_enable(unsigned int max_cpus)
+static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
 {
        scu_enable(MMIO_P2V(A9_MPCORE_SCU));
 }
index 813ee08f96e6a3d7f7052a45be2e92e68e347b3c..3034a4dab4a1a3a927ace6f2364393c5fbbcfbe4 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 #include <asm/system.h>
 
 extern volatile int pen_release;
index 2b5f7ac001a3326a160c346b9a3a0706d9e3c858..124ffb16909382f1383673783812fd5a1354f70c 100644 (file)
@@ -13,8 +13,6 @@
 #include <linux/smp.h>
 #include <linux/io.h>
 
-#include <asm/unified.h>
-
 #include <mach/motherboard.h>
 #define V2M_PA_CS7 0x10000000
 
@@ -46,6 +44,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
         * secondary CPU branches to this address.
         */
        writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
-       writel(BSYM(virt_to_phys(versatile_secondary_startup)),
+       writel(virt_to_phys(versatile_secondary_startup),
                MMIO_P2V(V2M_SYS_FLAGSSET));
 }
index 4cefb57d9ed2d79a9ac59e6d3f252dc1076d56a3..7edef9121632ed94c8e477d64385625040da92a7 100644 (file)
@@ -631,7 +631,8 @@ comment "Processor Features"
 
 config ARM_LPAE
        bool "Support for the Large Physical Address Extension"
-       depends on MMU && CPU_V7
+       depends on MMU && CPU_32v7 && !CPU_32v6 && !CPU_32v5 && \
+               !CPU_32v4 && !CPU_32v3
        help
          Say Y if you have an ARMv7 processor supporting the LPAE page
          table format and you would like to access memory beyond the
@@ -882,6 +883,7 @@ config CACHE_XSC3L2
 
 config ARM_L1_CACHE_SHIFT_6
        bool
+       default y if CPU_V7
        help
          Setting ARM L1 cache line size to 64 Bytes.
 
index 07c4bc8ea0a4aaf3cfd1bfcd819bd1061ec090e1..a655d3da386d6c3620a07bc25176163c21a07e15 100644 (file)
@@ -54,9 +54,15 @@ loop1:
        and     r1, r1, #7                      @ mask of the bits for current cache only
        cmp     r1, #2                          @ see what cache we have at this level
        blt     skip                            @ skip if no cache, or just i-cache
+#ifdef CONFIG_PREEMPT
+       save_and_disable_irqs_notrace r9        @ make cssr&csidr read atomic
+#endif
        mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
        isb                                     @ isb to sych the new cssr&csidr
        mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
+#ifdef CONFIG_PREEMPT
+       restore_irqs_notrace r9
+#endif
        and     r2, r1, #7                      @ extract the length of the cache lines
        add     r2, r2, #4                      @ add 4 (line length offset)
        ldr     r4, =0x3ff
index 6ec1226fc62d2fc58caa6c795614455c0f7e8ed7..5dc7d127a40fba7e8e16c6dd54abade74a45d5aa 100644 (file)
@@ -310,7 +310,7 @@ static void arm_memory_present(void)
 
 static bool arm_memblock_steal_permitted = true;
 
-phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
+phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
 {
        phys_addr_t phys;
 
index 7e9b5bf910c199cba4fc2fce9bead46e91d470b8..0404ccbb8aa3ee39f0a8084c55879fb464115ca2 100644 (file)
@@ -148,10 +148,6 @@ ENDPROC(cpu_v7_do_resume)
  *     Initialise TLB, Caches, and MMU state ready to switch the MMU
  *     on.  Return in r0 the new CP15 C1 control register setting.
  *
- *     We automatically detect if we have a Harvard cache, and use the
- *     Harvard cache control instructions insead of the unified cache
- *     control instructions.
- *
  *     This should be able to cover all ARMv7 cores.
  *
  *     It is assumed that:
@@ -251,9 +247,7 @@ __v7_setup:
 #endif
 
 3:     mov     r10, #0
-#ifdef HARVARD_CACHE
        mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
-#endif
        dsb
 #ifdef CONFIG_MMU
        mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
@@ -329,16 +323,6 @@ __v7_ca5mp_proc_info:
        __v7_proc __v7_ca5mp_setup
        .size   __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
 
-       /*
-        * ARM Ltd. Cortex A7 processor.
-        */
-       .type   __v7_ca7mp_proc_info, #object
-__v7_ca7mp_proc_info:
-       .long   0x410fc070
-       .long   0xff0ffff0
-       __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
-       .size   __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
-
        /*
         * ARM Ltd. Cortex A9 processor.
         */
@@ -350,6 +334,16 @@ __v7_ca9mp_proc_info:
        .size   __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
 #endif /* CONFIG_ARM_LPAE */
 
+       /*
+        * ARM Ltd. Cortex A7 processor.
+        */
+       .type   __v7_ca7mp_proc_info, #object
+__v7_ca7mp_proc_info:
+       .long   0x410fc070
+       .long   0xff0ffff0
+       __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
+       .size   __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
+
        /*
         * ARM Ltd. Cortex A15 processor.
         */
index b30708e28c1de1560fb886e30b35d305fb25738d..dcebb1230f7fd3cd6f6e492c97507a483dcef3b8 100644 (file)
@@ -17,26 +17,17 @@ config ARCH_IMX_V4_V5
          and ARMv5 SoCs
 
 config ARCH_IMX_V6_V7
-       bool "i.MX3, i.MX6"
+       bool "i.MX3, i.MX5, i.MX6"
        select AUTO_ZRELADDR if !ZBOOT_ROM
        select ARM_PATCH_PHYS_VIRT
        select MIGHT_HAVE_CACHE_L2X0
        help
-         This enables support for systems based on the Freescale i.MX3 and i.MX6
-         family.
-
-config ARCH_MX5
-       bool "i.MX50, i.MX51, i.MX53"
-       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
-         processors.
+         This enables support for systems based on the Freescale i.MX3, i.MX5
+         and i.MX6 family.
 
 endchoice
 
 source "arch/arm/mach-imx/Kconfig"
-source "arch/arm/mach-mx5/Kconfig"
 
 endmenu
 
index 6fa8a707b9a0347778a0513f05c953f16defd70f..f7d18046c04ffd49e52f678da6270c288f8958e0 100644 (file)
@@ -96,6 +96,6 @@ extern int mxc_gpio_mode(int gpio_mode);
 extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
                const char *label);
 
-extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
+extern int imx_iomuxv1_init(void __iomem *base, int numports);
 
 #endif /* __MACH_IOMUX_V1_H__ */
index ac24c5c4bc83c48cfe005fb2cea0e9bd7d2fc89e..fdbe60001542615595b5f178f6856d8d5c0455bb 100644 (file)
 #define FB_SYNC_SWAP_RGB       0x04000000
 #define FB_SYNC_CLK_SEL_EN     0x02000000
 
+/*
+ * Specify the way your display is connected. The IPU can arbitrarily
+ * map the internal colors to the external data lines. We only support
+ * the following mappings at the moment.
+ */
+enum disp_data_mapping {
+       /* blue -> d[0..5], green -> d[6..11], red -> d[12..17] */
+       IPU_DISP_DATA_MAPPING_RGB666,
+       /* blue -> d[0..4], green -> d[5..10], red -> d[11..15] */
+       IPU_DISP_DATA_MAPPING_RGB565,
+       /* blue -> d[0..7], green -> d[8..15], red -> d[16..23] */
+       IPU_DISP_DATA_MAPPING_RGB888,
+};
+
 /**
  * struct mx3fb_platform_data - mx3fb platform data
  *
@@ -33,6 +47,7 @@ struct mx3fb_platform_data {
        const char                      *name;
        const struct fb_videomode       *mode;
        int                             num_modes;
+       enum disp_data_mapping          disp_data_fmt;
 };
 
 #endif
index 685c78716d95234d1cb955b69d23a0bd929d107b..fd0ee84c45d1bc66b51e0a5527f75d9981040eeb 100644 (file)
@@ -113,7 +113,8 @@ struct stedma40_half_channel_info {
  * @dst_dev_type: Dst device type
  * @src_info: Parameters for dst half channel
  * @dst_info: Parameters for dst half channel
- *
+ * @use_fixed_channel: if true, use physical channel specified by phy_channel
+ * @phy_channel: physical channel to use, only if use_fixed_channel is true
  *
  * This structure has to be filled by the client drivers.
  * It is recommended to do all dma configurations for clients in the machine.
@@ -129,6 +130,9 @@ struct stedma40_chan_cfg {
        int                                      dst_dev_type;
        struct stedma40_half_channel_info        src_info;
        struct stedma40_half_channel_info        dst_info;
+
+       bool                                     use_fixed_channel;
+       int                                      phy_channel;
 };
 
 /**
@@ -153,6 +157,7 @@ struct stedma40_platform_data {
        struct stedma40_chan_cfg        *memcpy_conf_phy;
        struct stedma40_chan_cfg        *memcpy_conf_log;
        int                              disabled_channels[STEDMA40_MAX_PHYS];
+       bool                             use_esram_lcla;
 };
 
 #ifdef CONFIG_STE_DMA40
@@ -187,7 +192,7 @@ static inline struct
 dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
                                            dma_addr_t addr,
                                            unsigned int size,
-                                           enum dma_data_direction direction,
+                                           enum dma_transfer_direction direction,
                                            unsigned long flags)
 {
        struct scatterlist sg;
@@ -209,7 +214,7 @@ static inline struct
 dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
                                            dma_addr_t addr,
                                            unsigned int size,
-                                           enum dma_data_direction direction,
+                                           enum dma_transfer_direction direction,
                                            unsigned long flags)
 {
        return NULL;
index 64f9d1c7f1bb10787cb556adbf05f693d9b84a88..3047ff923a63cc62747d38aa51686f2a2e2cdc64 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/types.h>
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 extern int omap_secure_ram_reserve_memblock(void);
 #else
 static inline void omap_secure_ram_reserve_memblock(void)
index e5a2fde29b190f41c7384c7e135fc48728fec836..089899a7db724e7d5d09cc5d7bfa568e484a64a4 100644 (file)
@@ -789,10 +789,7 @@ void __init orion_xor1_init(unsigned long mapbase_low,
 /*****************************************************************************
  * EHCI
  ****************************************************************************/
-static struct orion_ehci_data orion_ehci_data = {
-       .phy_version    = EHCI_PHY_NA,
-};
-
+static struct orion_ehci_data orion_ehci_data;
 static u64 ehci_dmamask = DMA_BIT_MASK(32);
 
 
@@ -812,8 +809,10 @@ static struct platform_device orion_ehci = {
 };
 
 void __init orion_ehci_init(unsigned long mapbase,
-                           unsigned long irq)
+                           unsigned long irq,
+                           enum orion_ehci_phy_ver phy_version)
 {
+       orion_ehci_data.phy_version = phy_version;
        fill_resources(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
                       irq);
 
index 0fe08d77e835a47d05ce81265bea44823e55db24..a7fa005a5a0eb335e6b0267a090664a5a9d86ae7 100644 (file)
@@ -89,7 +89,8 @@ void __init orion_xor1_init(unsigned long mapbase_low,
                            unsigned long irq_1);
 
 void __init orion_ehci_init(unsigned long mapbase,
-                           unsigned long irq);
+                           unsigned long irq,
+                           enum orion_ehci_phy_ver phy_version);
 
 void __init orion_ehci_1_init(unsigned long mapbase,
                              unsigned long irq);
index 91553432711d0eb079110512f9246feafa7a2a4b..3b1e17bd3d17ddbffaf3be9e7b11631b20dfbd29 100644 (file)
@@ -64,8 +64,7 @@ void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
                        gpio_mode |= GPIO_INPUT_OK;
                if (*mpp_list & MPP_OUTPUT_MASK)
                        gpio_mode |= GPIO_OUTPUT_OK;
-               if (sel != 0)
-                       gpio_mode = 0;
+
                orion_gpio_set_valid(num, gpio_mode);
        }
 
index 32a6e394db24db39b7192519cee91667600c887a..f10768e988d480d8e49758d900ba890a3649099a 100644 (file)
@@ -468,8 +468,10 @@ void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
 {
        struct s3c2410_platform_i2c *npd;
 
-       if (!pd)
+       if (!pd) {
                pd = &default_i2c_data;
+               pd->bus_num = 0;
+       }
 
        npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
                               &s3c_device_i2c0);
index 2cded872f22b3debd634282a408d67169ceff981..0747c77a2fd53d0d2a66a1f1f2377b3d7e7722f6 100644 (file)
@@ -37,14 +37,14 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
                                (void *)dma_ch;
        chan = dma_request_channel(mask, pl330_filter, filter_param);
 
-       if (info->direction == DMA_FROM_DEVICE) {
+       if (info->direction == DMA_DEV_TO_MEM) {
                memset(&slave_config, 0, sizeof(struct dma_slave_config));
                slave_config.direction = info->direction;
                slave_config.src_addr = info->fifo;
                slave_config.src_addr_width = info->width;
                slave_config.src_maxburst = 1;
                dmaengine_slave_config(chan, &slave_config);
-       } else if (info->direction == DMA_TO_DEVICE) {
+       } else if (info->direction == DMA_MEM_TO_DEV) {
                memset(&slave_config, 0, sizeof(struct dma_slave_config));
                slave_config.direction = info->direction;
                slave_config.dst_addr = info->fifo;
index 22eafc310bd7858a8fb10b39087fc6064e78e04c..71a6827c7706b21e10200bd834b5dbaad1fa9e45 100644 (file)
 #define __SAMSUNG_DMA_OPS_H_ __FILE__
 
 #include <linux/dmaengine.h>
+#include <mach/dma.h>
 
 struct samsung_dma_prep_info {
        enum dma_transaction_type cap;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        dma_addr_t buf;
        unsigned long period;
        unsigned long len;
@@ -27,7 +28,7 @@ struct samsung_dma_prep_info {
 
 struct samsung_dma_info {
        enum dma_transaction_type cap;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        enum dma_slave_buswidth width;
        dma_addr_t fifo;
        struct s3c2410_dma_client *client;
index b9061128abdef3bcf76a2e9cdd4bab76732b4fd5..7b02143ccd9a2236b1ba0f32cc47dfb54d8b3d54 100644 (file)
@@ -10,6 +10,9 @@
  * published by the Free Software Foundation.
 */
 
+#ifndef __PLAT_DMA_H
+#define __PLAT_DMA_H
+
 #include <linux/dma-mapping.h>
 
 enum s3c2410_dma_buffresult {
@@ -122,5 +125,6 @@ extern int s3c2410_dma_getposition(enum dma_ch channel,
 extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn);
 extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
 
-
 #include <plat/dma-ops.h>
+
+#endif
index aea68b60ef98af7bac8c5841536c8150d803888f..fa95e9a009729f41ddd1c39174e4f6908f515226 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __S3C64XX_PLAT_SPI_H
 #define __S3C64XX_PLAT_SPI_H
 
+struct platform_device;
+
 /**
  * struct s3c64xx_spi_csinfo - ChipSelect description
  * @fb_delay: Slave specific feedback delay.
index d397a1fb2f5414ac7337d9aca3e8d328bf39f4c8..dd703ef09b8d9d623d83e4a131c12e87e329e838 100644 (file)
@@ -38,3 +38,4 @@ pen:  ldr     r7, [r6]
        .align
 1:     .long   .
        .long   pen_release
+ENDPROC(versatile_secondary_startup)
index 92f18d372b69ea24e062fb40b9f508b09d64dbf8..49c7db48c7f13d21b5211f1900ff99d639c4df8f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 #include <asm/hardware/gic.h>
 
 /*
index 197e96f7040594fa1994f6d7f61edddff6ccd65d..3dea7231f637c5d09e8c545fdee437a550b67c10 100644 (file)
@@ -8,6 +8,7 @@ config AVR32
        select HAVE_KPROBES
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
+       select GENERIC_ATOMIC64
        select HARDIRQS_SW_RESEND
        select GENERIC_IRQ_SHOW
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
index f5cb27614e35df7c4027094e7ac1d6626091021c..68c98f5b3ca625aaca9f342addd31c68c48c27af 100644 (file)
@@ -246,7 +246,18 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
        return regs->ar_bspstore;
 }
 
-#define regs_return_value(regs) ((regs)->r8)
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+       return regs->r10 != -1;
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       if (is_syscall_success(regs))
+               return regs->r8;
+       else
+               return -regs->r8;
+}
 
 /* Conserve space in histogram by encoding slot bits in address
  * bits 2 and 3 rather than bits 0 and 1.
index bfb4d01e0e519ed74a2a941214b4426627307134..5207035dc061bb5c567275efa0e0b58d2149a54d 100644 (file)
@@ -429,22 +429,24 @@ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
 static struct acpi_table_slit __initdata *slit_table;
 cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
 
-static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
+static int __init
+get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
 {
        int pxm;
 
        pxm = pa->proximity_domain_lo;
-       if (ia64_platform_is("sn2"))
+       if (ia64_platform_is("sn2") || acpi_srat_revision >= 2)
                pxm += pa->proximity_domain_hi[0] << 8;
        return pxm;
 }
 
-static int get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
+static int __init
+get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
 {
        int pxm;
 
        pxm = ma->proximity_domain;
-       if (!ia64_platform_is("sn2"))
+       if (!ia64_platform_is("sn2") && acpi_srat_revision <= 1)
                pxm &= 0xff;
 
        return pxm;
index 8848f43d819e55ba91bf07fc6ae8756f88e7ad36..dad91661ddf96e8b54aa4fbeafb9190879a65ccf 100644 (file)
@@ -1246,15 +1246,8 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
        if (test_thread_flag(TIF_RESTORE_RSE))
                ia64_sync_krbs();
 
-       if (unlikely(current->audit_context)) {
-               long syscall;
-               int arch;
 
-               syscall = regs.r15;
-               arch = AUDIT_ARCH_IA64;
-
-               audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3);
-       }
+       audit_syscall_entry(AUDIT_ARCH_IA64, regs.r15, arg0, arg1, arg2, arg3);
 
        return 0;
 }
@@ -1268,14 +1261,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
 {
        int step;
 
-       if (unlikely(current->audit_context)) {
-               int success = AUDITSC_RESULT(regs.r10);
-               long result = regs.r8;
-
-               if (success != AUDITSC_SUCCESS)
-                       result = -result;
-               audit_syscall_exit(success, result);
-       }
+       audit_syscall_exit(&regs);
 
        step = test_thread_flag(TIF_SINGLESTEP);
        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
index 4203d101363cf23074e7ce0e22a6f19579bf92ba..c4ac15c4f065ce97d0f86aafeb148efd5734e7ba 100644 (file)
@@ -414,9 +414,9 @@ void __init config_atari(void)
                                         * FDC val = 4 -> Supervisor only */
                asm volatile ("\n"
                        "       .chip   68030\n"
-                       "       pmove   %0@,%/tt1\n"
+                       "       pmove   %0,%/tt1\n"
                        "       .chip   68k"
-                       : : "a" (&tt1_val));
+                       : : "m" (tt1_val));
        } else {
                asm volatile ("\n"
                        "       .chip   68040\n"
@@ -569,10 +569,10 @@ static void atari_reset(void)
                        : "d0");
        } else
                asm volatile ("\n"
-                       "       pmove   %0@,%%tc\n"
+                       "       pmove   %0,%%tc\n"
                        "       jmp     %1@"
                        : /* no outputs */
-                       : "a" (&tc_val), "a" (reset_addr));
+                       : "m" (tc_val), "a" (reset_addr));
 }
 
 
index 0e89fa05de0e60bda81f5df2056106c49160e3e8..c1155f0e22cc2615a0e97f5745dd3c5d7d77aba9 100644 (file)
 
 #define IRQ_USER       8
 
-/*
- * various flags for request_irq() - the Amiga now uses the standard
- * mechanism like all other architectures - IRQF_DISABLED and
- * IRQF_SHARED are your friends.
- */
-#ifndef MACH_AMIGA_ONLY
-#define IRQ_FLG_LOCK   (0x0001)        /* handler is not replaceable   */
-#define IRQ_FLG_REPLACE        (0x0002)        /* replace existing handler     */
-#define IRQ_FLG_FAST   (0x0004)
-#define IRQ_FLG_SLOW   (0x0008)
-#define IRQ_FLG_STD    (0x8000)        /* internally used              */
-#endif
-
 struct irq_data;
 struct irq_chip;
 struct irq_desc;
index 756bde4fb4f83005cb52592249c11754ebc4ff56..3c793682e5d99a078b485fd4358bf27e163448f2 100644 (file)
@@ -78,7 +78,8 @@
                                 | CF_PAGE_READABLE \
                                 | CF_PAGE_WRITABLE \
                                 | CF_PAGE_EXEC \
-                                | CF_PAGE_SYSTEM)
+                                | CF_PAGE_SYSTEM \
+                                | CF_PAGE_SHARED)
 
 #define PAGE_COPY      __pgprot(CF_PAGE_VALID \
                                 | CF_PAGE_ACCESSED \
index 125f34e00bf01e8409634a1c3dbfd1d2d294f123..099283ee1a8fd0810672f2a36ad038786799dc5d 100644 (file)
@@ -172,7 +172,7 @@ void flush_thread(void)
 
        current->thread.fs = __USER_DS;
        if (!FPU_IS_EMU)
-               asm volatile ("frestore %0@" : : "a" (&zero) : "memory");
+               asm volatile("frestore %0": :"m" (zero));
 }
 
 /*
index 69c1803fcf1bed00b4a2ba6a60956992543ffac1..5e1078cabe0e54bf10d4537aa86eaa11c8b0e8a5 100644 (file)
@@ -163,8 +163,8 @@ void flush_thread(void)
 #ifdef CONFIG_FPU
        if (!FPU_IS_EMU)
                asm volatile (".chip 68k/68881\n\t"
-                             "frestore %0@\n\t"
-                             ".chip 68k" : : "a" (&zero));
+                             "frestore %0\n\t"
+                             ".chip 68k" : : "m" (zero));
 #endif
 }
 
index a76452ca964ef6e538ee6d5181b4341c7679dd48..daaa9187654ca6706278e79e5502d0a9f4f44a82 100644 (file)
@@ -552,13 +552,13 @@ static inline void bus_error030 (struct frame *fp)
 
 #ifdef DEBUG
                asm volatile ("ptestr %3,%2@,#7,%0\n\t"
-                             "pmove %%psr,%1@"
-                             : "=a&" (desc)
-                             : "a" (&temp), "a" (addr), "d" (ssw));
+                             "pmove %%psr,%1"
+                             : "=a&" (desc), "=m" (temp)
+                             : "a" (addr), "d" (ssw));
 #else
                asm volatile ("ptestr %2,%1@,#7\n\t"
-                             "pmove %%psr,%0@"
-                             : : "a" (&temp), "a" (addr), "d" (ssw));
+                             "pmove %%psr,%0"
+                             : "=m" (temp) : "a" (addr), "d" (ssw));
 #endif
                mmusr = temp;
 
@@ -605,20 +605,18 @@ static inline void bus_error030 (struct frame *fp)
                               !(ssw & RW) ? "write" : "read", addr,
                               fp->ptregs.pc, ssw);
                        asm volatile ("ptestr #1,%1@,#0\n\t"
-                                     "pmove %%psr,%0@"
-                                     : /* no outputs */
-                                     : "a" (&temp), "a" (addr));
+                                     "pmove %%psr,%0"
+                                     : "=m" (temp)
+                                     : "a" (addr));
                        mmusr = temp;
 
                        printk ("level 0 mmusr is %#x\n", mmusr);
 #if 0
-                       asm volatile ("pmove %%tt0,%0@"
-                                     : /* no outputs */
-                                     : "a" (&tlong));
+                       asm volatile ("pmove %%tt0,%0"
+                                     : "=m" (tlong));
                        printk("tt0 is %#lx, ", tlong);
-                       asm volatile ("pmove %%tt1,%0@"
-                                     : /* no outputs */
-                                     : "a" (&tlong));
+                       asm volatile ("pmove %%tt1,%0"
+                                     : "=m" (tlong));
                        printk("tt1 is %#lx\n", tlong);
 #endif
 #ifdef DEBUG
@@ -668,13 +666,13 @@ static inline void bus_error030 (struct frame *fp)
 
 #ifdef DEBUG
        asm volatile ("ptestr #1,%2@,#7,%0\n\t"
-                     "pmove %%psr,%1@"
-                     : "=a&" (desc)
-                     : "a" (&temp), "a" (addr));
+                     "pmove %%psr,%1"
+                     : "=a&" (desc), "=m" (temp)
+                     : "a" (addr));
 #else
        asm volatile ("ptestr #1,%1@,#7\n\t"
-                     "pmove %%psr,%0@"
-                     : : "a" (&temp), "a" (addr));
+                     "pmove %%psr,%0"
+                     : "=m" (temp) : "a" (addr));
 #endif
        mmusr = temp;
 
index 95d0bf66e2e22e72b272e11b48f5d41914b5be38..3d84c1f2ffb2ef8765b5adae4bd8d334b8c78b6d 100644 (file)
@@ -52,9 +52,9 @@ static unsigned long virt_to_phys_slow(unsigned long vaddr)
                unsigned long *descaddr;
 
                asm volatile ("ptestr %3,%2@,#7,%0\n\t"
-                             "pmove %%psr,%1@"
-                             : "=a&" (descaddr)
-                             : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg));
+                             "pmove %%psr,%1"
+                             : "=a&" (descaddr), "=m" (mmusr)
+                             : "a" (vaddr), "d" (get_fs().seg));
                if (mmusr & (MMU_I|MMU_B|MMU_L))
                        return 0;
                descaddr = phys_to_virt((unsigned long)descaddr);
index babd5a97cdcb6fd9f63dd075b554693b17d2fd7e..875b800ef0ddb765d9785ecb9d179eb919526c92 100644 (file)
@@ -87,7 +87,7 @@ void __init paging_init(void)
 
 int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
 {
-       unsigned long flags, mmuar;
+       unsigned long flags, mmuar, mmutr;
        struct mm_struct *mm;
        pgd_t *pgd;
        pmd_t *pmd;
@@ -137,9 +137,10 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
        if (!pte_dirty(*pte) && !KMAPAREA(mmuar))
                set_pte(pte, pte_wrprotect(*pte));
 
-       mmu_write(MMUTR, (mmuar & PAGE_MASK) | (asid << MMUTR_IDN) |
-               (((int)(pte->pte) & (int)CF_PAGE_MMUTR_MASK)
-               >> CF_PAGE_MMUTR_SHIFT) | MMUTR_V);
+       mmutr = (mmuar & PAGE_MASK) | (asid << MMUTR_IDN) | MMUTR_V;
+       if ((mmuar < TASK_UNMAPPED_BASE) || (mmuar >= TASK_SIZE))
+               mmutr |= (pte->pte & CF_PAGE_MMUTR_MASK) >> CF_PAGE_MMUTR_SHIFT;
+       mmu_write(MMUTR, mmutr);
 
        mmu_write(MMUDR, (pte_val(*pte) & PAGE_MASK) |
                ((pte->pte) & CF_PAGE_MMUDR_MASK) | MMUDR_SZ_8KB | MMUDR_X);
index 863889fc31c9c1fe2b0ad7a9b460a8627a14a56c..281e38c2b6c74976c1c5da0ee061b51ce9335a4c 100644 (file)
@@ -136,7 +136,7 @@ Luser_return:
        movel   %sp,%d1                 /* get thread_info pointer */
        andl    #-THREAD_SIZE,%d1       /* at base of kernel stack */
        movel   %d1,%a0
-       movel   %a0@(TINFO_FLAGS),%d1   /* get thread_info->flags */
+       moveb   %a0@(TINFO_FLAGS+3),%d1 /* thread_info->flags (low 8 bits) */
        jne     Lwork_to_do             /* still work to do */
 
 Lreturn:
@@ -148,8 +148,6 @@ Lwork_to_do:
        btst    #TIF_NEED_RESCHED,%d1
        jne     reschedule
 
-       /* GERG: do we need something here for TRACEing?? */
-
 Lsignal_return:
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
index 74f23a460ba2f4415a1657fd7288b318c469683d..c8d6efb99dbf668b7f283f23624c2f50f632c442 100644 (file)
@@ -19,6 +19,7 @@ config MICROBLAZE
        select GENERIC_IRQ_SHOW
        select GENERIC_PCI_IOMAP
        select GENERIC_CPU_DEVICES
+       select GENERIC_ATOMIC64
 
 config SWAP
        def_bool n
index 6d2e1d418be74f7dbc3797e82a497b8bcab93bc8..615f53992c654e4f78625bf8708d5d92c7c12b09 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_MICROBLAZE_ATOMIC_H
 
 #include <asm-generic/atomic.h>
+#include <asm-generic/atomic64.h>
 
 /*
  * Atomically test *v and decrement if it is greater than 0.
index 816bee64b1961d202f35a1aa9c4d2be0fc1d640e..94e92c8058592f786cfd6fac942c90b308664e85 100644 (file)
@@ -61,6 +61,11 @@ struct pt_regs {
 #define instruction_pointer(regs)      ((regs)->pc)
 #define profile_pc(regs)               instruction_pointer(regs)
 
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       return regs->r3;
+}
+
 #else /* __KERNEL__ */
 
 /* pt_regs offsets used by gdbserver etc in ptrace syscalls */
index 043cb58f9c443e72843fa44a9ebd399442a965b5..6eb2aa927d8966b842f388b219ae19b8dadd7309 100644 (file)
@@ -147,10 +147,8 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
                 */
                ret = -1L;
 
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(EM_MICROBLAZE, regs->r12,
-                                   regs->r5, regs->r6,
-                                   regs->r7, regs->r8);
+       audit_syscall_entry(EM_MICROBLAZE, regs->r12, regs->r5, regs->r6,
+                           regs->r7, regs->r8);
 
        return ret ?: regs->r12;
 }
@@ -159,8 +157,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 {
        int step;
 
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(regs->r3), regs->r3);
+       audit_syscall_exit(regs);
 
        step = test_thread_flag(TIF_SINGLESTEP);
        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
index c4c1312473fbf6cd9104cc3d206846bcd38b1b4b..5ab6e89603c56bc461de1b4390ada67482749c2e 100644 (file)
@@ -2356,6 +2356,7 @@ config PCI
        depends on HW_HAS_PCI
        select PCI_DOMAINS
        select GENERIC_PCI_IOMAP
+       select NO_GENERIC_PCI_IOPORT_MAP
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 7b99c670e478ed9ab79998762c839489cefb66a1..4b7f5252d2fd31ba156723c23db11e57e983442b 100644 (file)
@@ -137,7 +137,19 @@ extern int ptrace_set_watch_regs(struct task_struct *child,
  */
 #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
 
-#define regs_return_value(_regs) ((_regs)->regs[2])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+       return !regs->regs[7];
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       if (is_syscall_success(regs))
+               return regs->regs[2];
+       else
+               return -regs->regs[2];
+}
+
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
 
index 4e6ea1ffad46617b3e1c0880c4061371f7aa5885..7786b608d9322289ce23a83eb5205b50b57f3cb6 100644 (file)
@@ -560,10 +560,9 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
        }
 
 out:
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(audit_arch(), regs->regs[2],
-                                   regs->regs[4], regs->regs[5],
-                                   regs->regs[6], regs->regs[7]);
+       audit_syscall_entry(audit_arch(), regs->regs[2],
+                           regs->regs[4], regs->regs[5],
+                           regs->regs[6], regs->regs[7]);
 }
 
 /*
@@ -572,9 +571,7 @@ out:
  */
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(regs->regs[7]),
-                                  -regs->regs[2]);
+       audit_syscall_exit(regs);
 
        if (!(current->ptrace & PT_PTRACED))
                return;
index 2635b1a9633385568677b9a121f50adb6f96d8b7..fd35daa45314a370b89f521e3ec401d39e5dfdc9 100644 (file)
@@ -10,8 +10,8 @@
 #include <linux/module.h>
 #include <asm/io.h>
 
-static void __iomem *ioport_map_pci(struct pci_dev *dev,
-                                     unsigned long port, unsigned int nr)
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+                              unsigned long port, unsigned int nr)
 {
        struct pci_controller *ctrl = dev->bus->sysdata;
        unsigned long base = ctrl->io_map_base;
index 89af6263770701e71a3e8e4c9e9d3db3c2b657d0..b37da56018b6340a6d514a85644d5131960de9ff 100644 (file)
        };
 
 /include/ "pq3-esdhc-0.dtsi"
+       sdhc@2e000 {
+               compatible = "fsl,mpc8536-esdhc", "fsl,esdhc";
+       };
+
 /include/ "pq3-sec3.0-0.dtsi"
 /include/ "pq3-mpic.dtsi"
 /include/ "pq3-mpic-timer-B.dtsi"
index bd9e163c764b33e858e835684f46b69c369e751b..a97d1263372ccbf9350f5db9ee29b9483886642a 100644 (file)
 /include/ "pq3-usb2-dr-0.dtsi"
 /include/ "pq3-esdhc-0.dtsi"
        sdhc@2e000 {
-               fsl,sdhci-auto-cmd12;
+               compatible = "fsl,p1010-esdhc", "fsl,esdhc";
+               sdhci,auto-cmd12;
        };
 
 /include/ "pq3-sec4.4-0.dtsi"
index fc924c5ffebe2245a65abf26bf71031f0ca8d078..5de5fc351314a627605c0bd0389f05ae452e1714 100644 (file)
 /include/ "pq3-usb2-dr-1.dtsi"
 
 /include/ "pq3-esdhc-0.dtsi"
+       sdhc@2e000 {
+               compatible = "fsl,p1020-esdhc", "fsl,esdhc";
+               sdhci,auto-cmd12;
+       };
 /include/ "pq3-sec3.3-0.dtsi"
 
 /include/ "pq3-mpic.dtsi"
index 16239b199d0a35b1d338590898582d9215cf525a..ff9ed1d879297bfe0975cd7261abdc9eaab7a57f 100644 (file)
 
 /include/ "pq3-esdhc-0.dtsi"
        sdhc@2e000 {
-               fsl,sdhci-auto-cmd12;
+               compatible = "fsl,p1022-esdhc", "fsl,esdhc";
+               sdhci,auto-cmd12;
        };
 
 /include/ "pq3-sec3.3-0.dtsi"
index c041050561a7f17a284e45b0c00119eb33ab4411..332e9e75e6c2f706b370d9f7524594df25c5c387 100644 (file)
 /include/ "pq3-etsec1-1.dtsi"
 /include/ "pq3-etsec1-2.dtsi"
 /include/ "pq3-esdhc-0.dtsi"
+       sdhc@2e000 {
+               compatible = "fsl,p2020-esdhc", "fsl,esdhc";
+       };
+
 /include/ "pq3-sec3.1-0.dtsi"
 /include/ "pq3-mpic.dtsi"
 /include/ "pq3-mpic-timer-B.dtsi"
index b5bd86f4baf21b810f4b38fef873b7e4775eb00e..1fb7e0e0940f0cb098843b78207c6117efeffab7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P1020 RDB Device Tree Source stub (no addresses or top-level ranges)
  *
- * Copyright 2011 Freescale Semiconductor Inc.
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 
        usb@22000 {
                phy_type = "ulpi";
+               dr_mode = "host";
        };
 
-       /* USB2 is shared with localbus, so it must be disabled
-          by default. We can't put 'status = "disabled";' here
-          since U-Boot doesn't clear the status property when
-          it enables USB2. OTOH, U-Boot does create a new node
-          when there isn't any. So, just comment it out.
+       /* USB2 is shared with localbus. It is used
+          only in case of SPI and SD boot after
+          appropriate device-tree fixup done by uboot */
        usb@23000 {
                phy_type = "ulpi";
+               dr_mode = "host";
        };
-       */
 
        mdio@24000 {
                phy0: ethernet-phy@0 {
index d9540791e4342034ca9509826104a9ae06ab32d2..97116f198a37fa1c793e1fb09d11090bd7f51515 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P1021 MDS Device Tree Source
  *
- * Copyright 2010 Freescale Semiconductor Inc.
+ * Copyright 2010,2012 Freescale Semiconductor 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
 
                usb@22000 {
                        phy_type = "ulpi";
+                       dr_mode = "host";
                };
 
                mdio@24000 {
index c1cf6cef4dd60265586419252e0f67828ee6ddf2..d3b939c573b007e5ca25ad89f58523abb3db56cc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P2020DS Device Tree Source stub (no addresses or top-level ranges)
  *
- * Copyright 2011 Freescale Semiconductor Inc.
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 &board_soc {
        usb@22000 {
                phy_type = "ulpi";
+               dr_mode = "host";
        };
 
        mdio@24520 {
index 26759a5917129505e02c00070d7c067453b002de..eb8a6aa2bda5f019ae06311a9e753f12cf2891b0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P2020 RDB Device Tree Source
  *
- * Copyright 2009-2011 Freescale Semiconductor Inc.
+ * Copyright 2009-2012 Freescale Semiconductor 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
 
                usb@22000 {
                        phy_type = "ulpi";
+                       dr_mode = "host";
                };
 
                mdio@24520 {
index 2156e077859b9bee6285bfb87677b72f64c77311..1acf65026773a6b6336d21e5b3b07f06bf6e84a7 100644 (file)
@@ -24,10 +24,6 @@ CONFIG_PPC_SPLPAR=y
 CONFIG_SCANLOG=m
 CONFIG_PPC_SMLPAR=y
 CONFIG_DTL=y
-CONFIG_PPC_ISERIES=y
-CONFIG_VIODASD=y
-CONFIG_VIOCD=m
-CONFIG_VIOTAPE=m
 CONFIG_PPC_MAPLE=y
 CONFIG_PPC_PASEMI=y
 CONFIG_PPC_PASEMI_IOMMU=y
@@ -259,7 +255,6 @@ CONFIG_PASEMI_MAC=y
 CONFIG_MLX4_EN=m
 CONFIG_QLGE=m
 CONFIG_BE2NET=m
-CONFIG_ISERIES_VETH=m
 CONFIG_PPP=m
 CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
index 43268f15004e8082148cc1a57de8766fdad75c7d..6d422979ebafde984906f20add7886fd9e1464ec 100644 (file)
@@ -142,6 +142,11 @@ static inline const char *eeh_pci_name(struct pci_dev *pdev)
        return pdev ? pci_name(pdev) : "<null>";
 } 
 
+static inline const char *eeh_driver_name(struct pci_dev *pdev)
+{
+       return (pdev && pdev->driver) ? pdev->driver->name : "<null>";
+}
+
 #endif /* CONFIG_EEH */
 
 #else /* CONFIG_PCI */
index 48223f9b8728d5e1433c6d13ab9c1c583780d2cb..84cc7840cd18f139e1410f50fc383baa8010d16b 100644 (file)
@@ -83,17 +83,32 @@ struct pt_regs {
 
 #ifndef __ASSEMBLY__
 
-#define instruction_pointer(regs) ((regs)->nip)
-#define user_stack_pointer(regs) ((regs)->gpr[1])
-#define kernel_stack_pointer(regs) ((regs)->gpr[1])
-#define regs_return_value(regs) ((regs)->gpr[3])
+#define GET_IP(regs)           ((regs)->nip)
+#define GET_USP(regs)          ((regs)->gpr[1])
+#define GET_FP(regs)           (0)
+#define SET_FP(regs, val)
 
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *regs);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
+#define profile_pc profile_pc
 #endif
 
+#include <asm-generic/ptrace.h>
+
+#define kernel_stack_pointer(regs) ((regs)->gpr[1])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+       return !(regs->ccr & 0x10000000);
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       if (is_syscall_success(regs))
+               return regs->gpr[3];
+       else
+               return -regs->gpr[3];
+}
+
 #ifdef __powerpc64__
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 #else
index 28be3452e67ad75157940bc7ee29a6fd3f0c0195..abef75176c079f2f72f71d6af4f10cec4095deca 100644 (file)
@@ -46,7 +46,6 @@
 
 /* This keeps a track of which one is the crashing cpu. */
 int crashing_cpu = -1;
-static atomic_t cpus_in_crash;
 static int time_to_dump;
 
 #define CRASH_HANDLER_MAX 3
@@ -66,6 +65,7 @@ static int handle_fault(struct pt_regs *regs)
 
 #ifdef CONFIG_SMP
 
+static atomic_t cpus_in_crash;
 void crash_ipi_callback(struct pt_regs *regs)
 {
        static cpumask_t cpus_state_saved = CPU_MASK_NONE;
index 4f80cf1ce77b84c30e905bcb8cb8d660c005c22b..3e57a00b8cba784633d1b0465fd3b47f1b85baf0 100644 (file)
@@ -1213,7 +1213,7 @@ do_user_signal:                   /* r10 contains MSR_KERNEL here */
        stw     r3,_TRAP(r1)
 2:     addi    r3,r1,STACK_FRAME_OVERHEAD
        mr      r4,r9
-       bl      do_signal
+       bl      do_notify_resume
        REST_NVGPRS(r1)
        b       recheck
 
index d834425186aeaa7fae6905bd8bffb50d0d99354d..866462cbe2d832341d2cbf5b89d32be7986ec815 100644 (file)
@@ -751,12 +751,16 @@ user_work:
 
        andi.   r0,r4,_TIF_NEED_RESCHED
        beq     1f
+       li      r5,1
+       TRACE_AND_RESTORE_IRQ(r5);
        bl      .schedule
        b       .ret_from_except_lite
 
 1:     bl      .save_nvgprs
+       li      r5,1
+       TRACE_AND_RESTORE_IRQ(r5);
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .do_signal
+       bl      .do_notify_resume
        b       .ret_from_except
 
 unrecov_restore:
index d4be7bb3dbdfdffd5d62d76aa96860392040a305..15c5a4f6de0105b410de25643b22a7b9409bba22 100644 (file)
@@ -774,8 +774,8 @@ alignment_common:
 program_check_common:
        EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
        bl      .save_nvgprs
+       DISABLE_INTS
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       ENABLE_INTS
        bl      .program_check_exception
        b       .ret_from_except
 
index 701d4aceb4f4ca72115426e32fb6fdc490370eb9..01e2877e8e04805694695361326ee0613a502fe1 100644 (file)
@@ -118,10 +118,14 @@ static inline notrace void set_soft_enabled(unsigned long enable)
 static inline notrace void decrementer_check_overflow(void)
 {
        u64 now = get_tb_or_rtc();
-       u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
+       u64 *next_tb;
+
+       preempt_disable();
+       next_tb = &__get_cpu_var(decrementers_next_tb);
 
        if (now >= *next_tb)
                set_dec(1);
+       preempt_enable();
 }
 
 notrace void arch_local_irq_restore(unsigned long en)
index 3fea3689527e963955f802ac7abf2a8471ddfd24..bedd12e1cfbcc0b636eea99f1ca18728938ed2f4 100644 (file)
@@ -442,8 +442,10 @@ static void __init fixup_port_irq(int index,
 
        port->irq = virq;
 
+#ifdef CONFIG_SERIAL_8250_FSL
        if (of_device_is_compatible(np, "fsl,ns16550"))
                port->handle_irq = fsl8250_handle_irq;
+#endif
 }
 
 static void __init fixup_port_pio(int index,
index 10a140f82cb87db296859f57ce18edfbb10f2ace..64483fde95c62cfa0cc5411e2c2cc6fce5cab453 100644 (file)
@@ -865,6 +865,7 @@ static void power_pmu_start(struct perf_event *event, int ef_flags)
 {
        unsigned long flags;
        s64 left;
+       unsigned long val;
 
        if (!event->hw.idx || !event->hw.sample_period)
                return;
@@ -880,7 +881,12 @@ static void power_pmu_start(struct perf_event *event, int ef_flags)
 
        event->hw.state = 0;
        left = local64_read(&event->hw.period_left);
-       write_pmc(event->hw.idx, left);
+
+       val = 0;
+       if (left < 0x80000000L)
+               val = 0x80000000L - left;
+
+       write_pmc(event->hw.idx, val);
 
        perf_event_update_userpage(event);
        perf_pmu_enable(event->pmu);
index ebe5766781aa8c9eca7d96849ca034233e043308..d817ab018486d71b8c06bb9b6275bd0f533d8c89 100644 (file)
@@ -566,12 +566,12 @@ static void show_instructions(struct pt_regs *regs)
                 */
                if (!__kernel_text_address(pc) ||
                     __get_user(instr, (unsigned int __user *)pc)) {
-                       printk("XXXXXXXX ");
+                       printk(KERN_CONT "XXXXXXXX ");
                } else {
                        if (regs->nip == pc)
-                               printk("<%08x> ", instr);
+                               printk(KERN_CONT "<%08x> ", instr);
                        else
-                               printk("%08x ", instr);
+                               printk(KERN_CONT "%08x ", instr);
                }
 
                pc += sizeof(int);
index 5de73dbd15c7e404a16257ae5239e9b1af293f65..5b43325402bcc8e5435c1e2804685e81cb24df72 100644 (file)
@@ -1724,22 +1724,20 @@ long do_syscall_trace_enter(struct pt_regs *regs)
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->gpr[0]);
 
-       if (unlikely(current->audit_context)) {
 #ifdef CONFIG_PPC64
-               if (!is_32bit_task())
-                       audit_syscall_entry(AUDIT_ARCH_PPC64,
-                                           regs->gpr[0],
-                                           regs->gpr[3], regs->gpr[4],
-                                           regs->gpr[5], regs->gpr[6]);
-               else
+       if (!is_32bit_task())
+               audit_syscall_entry(AUDIT_ARCH_PPC64,
+                                   regs->gpr[0],
+                                   regs->gpr[3], regs->gpr[4],
+                                   regs->gpr[5], regs->gpr[6]);
+       else
 #endif
-                       audit_syscall_entry(AUDIT_ARCH_PPC,
-                                           regs->gpr[0],
-                                           regs->gpr[3] & 0xffffffff,
-                                           regs->gpr[4] & 0xffffffff,
-                                           regs->gpr[5] & 0xffffffff,
-                                           regs->gpr[6] & 0xffffffff);
-       }
+               audit_syscall_entry(AUDIT_ARCH_PPC,
+                                   regs->gpr[0],
+                                   regs->gpr[3] & 0xffffffff,
+                                   regs->gpr[4] & 0xffffffff,
+                                   regs->gpr[5] & 0xffffffff,
+                                   regs->gpr[6] & 0xffffffff);
 
        return ret ?: regs->gpr[0];
 }
@@ -1748,9 +1746,7 @@ void do_syscall_trace_leave(struct pt_regs *regs)
 {
        int step;
 
-       if (unlikely(current->audit_context))
-               audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
-                                  regs->result);
+       audit_syscall_exit(regs);
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_exit(regs, regs->result);
index 517b1d8f455b2d29761ef792fdc8da5fc745cbc7..9f843cdfee9ec69ac38ea7b78518f035b2266c4e 100644 (file)
@@ -716,7 +716,6 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w
        int cpu;
 
        slb_set_size(SLB_MIN_SIZE);
-       stop_topology_update();
        printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id());
 
        while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) &&
@@ -732,7 +731,6 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w
                rc = atomic_read(&data->error);
 
        atomic_set(&data->error, rc);
-       start_topology_update();
        pSeries_coalesce_init();
 
        if (wake_when_done) {
@@ -846,6 +844,7 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
        atomic_set(&data.error, 0);
        data.token = rtas_token("ibm,suspend-me");
        data.complete = &done;
+       stop_topology_update();
 
        /* Call function on all CPUs.  One of us will make the
         * rtas call
@@ -858,6 +857,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
        if (atomic_read(&data.error) != 0)
                printk(KERN_ERR "Error doing global join\n");
 
+       start_topology_update();
+
        return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
index 2300426e531a096239b0620f9ec29f71e70b6daf..ac6e437b10214d47b6d6525cc9d23b8b3e37dabe 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/tracehook.h>
 #include <linux/signal.h>
+#include <linux/key.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -113,8 +114,9 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
        }
 }
 
-static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
+static int do_signal(struct pt_regs *regs)
 {
+       sigset_t *oldset;
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
@@ -123,7 +125,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
 
        if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
-       else if (!oldset)
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -191,14 +193,16 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
        return ret;
 }
 
-void do_signal(struct pt_regs *regs, unsigned long thread_info_flags)
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
        if (thread_info_flags & _TIF_SIGPENDING)
-               do_signal_pending(NULL, regs);
+               do_signal(regs);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
                tracehook_notify_resume(regs);
+               if (current->replacement_session_keyring)
+                       key_replace_session_keyring();
        }
 }
 
index 6c0ddfc0603e80fa29c5a4b3408fa393d90e8f62..8dde973aaaf513ffd4c39a41f0f3bf2bead0d7db 100644 (file)
@@ -12,7 +12,7 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags);
+extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
 
 extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
                                  size_t frame_size, int is_32);
index bb3d84f4046f53342bc0390c02359a73a34d4866..b0984ada3f83c41db76a56f3adbbd7779af6d7c1 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
+#include <asm/udbg.h>
 #include <asm/fsl_guts.h>
 #include "smp.h"
 
index f31162cfdaa9762f71cafe41e0f815e92181f6fd..5e155dfc4320ab011589d678408002dd05503a96 100644 (file)
@@ -204,11 +204,10 @@ static void __devinit pnv_ioda_offset_bus(struct pci_bus *bus,
        pr_devel("  -> OBR %s [%x] +%016llx\n",
                 bus->self ? pci_name(bus->self) : "root", flags, offset);
 
-       for (i = 0; i < 2; i++) {
-               r = bus->resource[i];
+       pci_bus_for_each_resource(bus, r, i) {
                if (r && (r->flags & flags)) {
-                       bus->resource[i]->start += offset;
-                       bus->resource[i]->end += offset;
+                       r->start += offset;
+                       r->end += offset;
                }
        }
        list_for_each_entry(dev, &bus->devices, bus_list)
@@ -288,12 +287,17 @@ static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags,
         * assignment algorithm is going to be uber-trivial for now, we
         * can try to be smarter later at filling out holes.
         */
-       start = bus->self ? 0 : bus->resource[bres]->start;
-
-       /* Don't hand out IO 0 */
-       if ((flags & IORESOURCE_IO) && !bus->self)
-               start += 0x1000;
-
+       if (bus->self) {
+               /* No offset for downstream bridges */
+               start = 0;
+       } else {
+               /* Offset from the root */
+               if (flags & IORESOURCE_IO)
+                       /* Don't hand out IO 0 */
+                       start = hose->io_resource.start + 0x1000;
+               else
+                       start = hose->mem_resources[0].start;
+       }
        while(!list_empty(&head)) {
                w = list_first_entry(&head, struct resource_wrap, link);
                list_del(&w->link);
@@ -321,13 +325,20 @@ static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags,
  empty:
        /* Only setup P2P's, not the PHB itself */
        if (bus->self) {
-               WARN_ON(bus->resource[bres] == NULL);
-               bus->resource[bres]->start = 0;
-               bus->resource[bres]->flags = (*size) ? flags : 0;
-               bus->resource[bres]->end = (*size) ? (*size - 1) : 0;
+               struct resource *res = bus->resource[bres];
+
+               if (WARN_ON(res == NULL))
+                       return;
 
-               /* Clear prefetch bus resources for now */
-               bus->resource[2]->flags = 0;
+               /*
+                * FIXME: We should probably export and call
+                * pci_bridge_check_ranges() to properly re-initialize
+                * the PCI portion of the flags here, and to detect
+                * what the bridge actually supports.
+                */
+               res->start = 0;
+               res->flags = (*size) ? flags : 0;
+               res->end = (*size) ? (*size - 1) : 0;
        }
 
        pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n",
index a70bc1e385eba68e49815599eeec52de1492e6d2..f92b9ef7340e85129f4ec801128e307c627273b3 100644 (file)
@@ -52,32 +52,38 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
 
 static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
 {
-       unsigned int id;
+       unsigned long flags;
+       unsigned int id, rc;
+
+       spin_lock_irqsave(&phb->lock, flags);
 
-       spin_lock(&phb->lock);
        id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
        if (id >= phb->msi_count && phb->msi_next)
                id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
        if (id >= phb->msi_count) {
-               spin_unlock(&phb->lock);
-               return 0;
+               rc = 0;
+               goto out;
        }
        __set_bit(id, phb->msi_map);
-       spin_unlock(&phb->lock);
-       return id + phb->msi_base;
+       rc = id + phb->msi_base;
+out:
+       spin_unlock_irqrestore(&phb->lock, flags);
+       return rc;
 }
 
 static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
 {
+       unsigned long flags;
        unsigned int id;
 
        if (WARN_ON(hwirq < phb->msi_base ||
                    hwirq >= (phb->msi_base + phb->msi_count)))
                return;
        id = hwirq - phb->msi_base;
-       spin_lock(&phb->lock);
+
+       spin_lock_irqsave(&phb->lock, flags);
        __clear_bit(id, phb->msi_map);
-       spin_unlock(&phb->lock);
+       spin_unlock_irqrestore(&phb->lock, flags);
 }
 
 static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
index ae7b6d41fed363580575aa4ea6b56d053b702c84..31f22c1f657dbf4c7e2f68ca25002a24f485b83d 100644 (file)
@@ -122,7 +122,7 @@ config DTL
          Say N if you are unsure.
 
 config PSERIES_IDLE
-       tristate "Cpuidle driver for pSeries platforms"
+       bool "Cpuidle driver for pSeries platforms"
        depends on CPU_IDLE
        depends on PPC_PSERIES
        default y
index 565869022e3d4e54c603cc6b2f79afb7fe6c2bd2..c0b40af4ce4f130edbd094d48467f747a10d78cc 100644 (file)
@@ -551,9 +551,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
                        printk (KERN_ERR "EEH: %d reads ignored for recovering device at "
                                "location=%s driver=%s pci addr=%s\n",
                                pdn->eeh_check_count, location,
-                               dev->driver->name, eeh_pci_name(dev));
+                               eeh_driver_name(dev), eeh_pci_name(dev));
                        printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n",
-                               dev->driver->name);
+                               eeh_driver_name(dev));
                        dump_stack();
                }
                goto dn_unlock;
index b84a8b2238dd94ce22f11d1c7778f048b0128392..47226e04126d10e930a7a4a1bf42aa1c9abedb7a 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/machdep.h>
 #include <asm/mmu.h>
 #include <asm/rtas.h>
+#include <asm/topology.h>
 
 static u64 stream_id;
 static struct device suspend_dev;
@@ -138,8 +139,11 @@ static ssize_t store_hibernate(struct device *dev,
                        ssleep(1);
        } while (rc == -EAGAIN);
 
-       if (!rc)
+       if (!rc) {
+               stop_topology_update();
                rc = pm_suspend(PM_SUSPEND_MEM);
+               start_topology_update();
+       }
 
        stream_id = 0;
 
index 57687439254310f8521bd3da217df1b380be64ba..97fe82ee863334664eb2864f18f0b2a7fbd1dc56 100644 (file)
@@ -346,7 +346,7 @@ static int wsp_chip_set_affinity(struct irq_data *d,
         * For the moment only implement delivery to all cpus or one cpu.
         * Get current irq_server for the given irq
         */
-       ret = cache_hwirq_map(ics, d->irq, cpumask);
+       ret = cache_hwirq_map(ics, hw_irq, cpumask);
        if (ret == -1) {
                char cpulist[128];
                cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
index 71bd105f38636b0435fae0590deec38cd02ddf1e..0ba103ae83a53c5218c5517227e942bf800753ba 100644 (file)
@@ -71,7 +71,7 @@ int __devinit smp_a2_kick_cpu(int nr)
 
 static int __init smp_a2_probe(void)
 {
-       return cpus_weight(cpu_possible_map);
+       return num_possible_cpus();
 }
 
 static struct smp_ops_t a2_smp_ops = {
index e0262cd0e2d3954e143cb4f8ffa490d88803a192..d24b3acf858eaf79f01a1a7662f0f53ef815595f 100644 (file)
@@ -468,15 +468,15 @@ static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
 #define DUMP_REG(x) \
        pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x))
 
-#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS
-       /* WSP DD1 has a bogus class code by default in the PCI-E
-        * root complex's built-in P2P bridge */
+       /*
+        * Some WSP variants  has a bogus class code by default in the PCI-E
+        * root complex's built-in P2P bridge
+        */
        val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1);
        pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val);
        out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1,
                 (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8));
        pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1));
-#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */
 
 #ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
        /* XXX Disable TCE caching, it doesn't work on DD1 */
index 3b61e8cf3421fd2ce2f132a42e25c2eb411e9d6f..6073288fed29889399bb640bc22f709043363f72 100644 (file)
@@ -205,12 +205,12 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 
        if (paddr_hi == paddr_lo) {
                pr_err("%s: No outbound window space\n", name);
-               return ;
+               goto out;
        }
 
        if (paddr_lo == 0) {
                pr_err("%s: No space for inbound window\n", name);
-               return ;
+               goto out;
        }
 
        /* setup PCSRBAR/PEXCSRBAR */
@@ -357,6 +357,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
                        (u64)hose->dma_window_size);
        }
 
+out:
        iounmap(pci);
 }
 
@@ -384,26 +385,36 @@ static void __init setup_pci_cmd(struct pci_controller *hose)
 void fsl_pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
-       int i;
-
-       if ((bus->parent == hose->bus) &&
-           ((fsl_pcie_bus_fixup &&
-             early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) ||
-            (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)))
-       {
-               for (i = 0; i < 4; ++i) {
+       int i, is_pcie = 0, no_link;
+
+       /* The root complex bridge comes up with bogus resources,
+        * we copy the PHB ones in.
+        *
+        * With the current generic PCI code, the PHB bus no longer
+        * has bus->resource[0..4] set, so things are a bit more
+        * tricky.
+        */
+
+       if (fsl_pcie_bus_fixup)
+               is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
+       no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK);
+
+       if (bus->parent == hose->bus && (is_pcie || no_link)) {
+               for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) {
                        struct resource *res = bus->resource[i];
-                       struct resource *par = bus->parent->resource[i];
-                       if (res) {
-                               res->start = 0;
-                               res->end   = 0;
-                               res->flags = 0;
-                       }
-                       if (res && par) {
-                               res->start = par->start;
-                               res->end   = par->end;
-                               res->flags = par->flags;
-                       }
+                       struct resource *par;
+
+                       if (!res)
+                               continue;
+                       if (i == 0)
+                               par = &hose->io_resource;
+                       else if (i < 4)
+                               par = &hose->mem_resources[i-1];
+                       else par = NULL;
+
+                       res->start = par ? par->start : 0;
+                       res->end   = par ? par->end   : 0;
+                       res->flags = par ? par->flags : 0;
                }
        }
 }
index e9f353341693615249c9ef76501920c457360e8a..0ad2f1e1ce9ec48928696f428a9063968ea04490 100644 (file)
@@ -88,7 +88,6 @@ KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
 KBUILD_AFLAGS  += $(aflags-y)
 
 OBJCOPYFLAGS   := -O binary
-LDFLAGS_vmlinux := -e start
 
 head-y         := arch/s390/kernel/head.o
 head-y         += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
index cf4e47b0948c3c9b25aa5d6f310566667615d14a..3f30dac804ea7ee92808bb5a1f51e16482462951 100644 (file)
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_S390
 
+/*
+ * Size for s390x ELF notes per CPU
+ *
+ * Seven notes plus zero note at the end: prstatus, fpregset, timer,
+ * tod_cmp, tod_reg, control regs, and prefix
+ */
+#define KEXEC_NOTE_BYTES \
+       (ALIGN(sizeof(struct elf_note), 4) * 8 + \
+        ALIGN(sizeof("CORE"), 4) * 7 + \
+        ALIGN(sizeof(struct elf_prstatus), 4) + \
+        ALIGN(sizeof(elf_fpregset_t), 4) + \
+        ALIGN(sizeof(u64), 4) + \
+        ALIGN(sizeof(u64), 4) + \
+        ALIGN(sizeof(u32), 4) + \
+        ALIGN(sizeof(u64) * 16, 4) + \
+        ALIGN(sizeof(u32), 4) \
+       )
+
 /* Provide a dummy definition to avoid build failures. */
 static inline void crash_setup_regs(struct pt_regs *newregs,
                                        struct pt_regs *oldregs) { }
index 56da355678f4aa7feed766a016b84282381451ba..aeb77f01798504cd250aebbd8748516b8c64e113 100644 (file)
@@ -541,9 +541,13 @@ struct user_regs_struct
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
 #define user_stack_pointer(regs)((regs)->gprs[15])
-#define regs_return_value(regs)((regs)->gprs[2])
 #define profile_pc(regs) instruction_pointer(regs)
 
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       return regs->gprs[2];
+}
+
 int regs_query_register_offset(const char *name);
 const char *regs_query_register_name(unsigned int offset);
 unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset);
index 18c51df9fe06c5ed98f785fb6af86655c025e887..ff605a39cf435661a6ba6ab5dee05544239fae6b 100644 (file)
@@ -662,7 +662,7 @@ ENTRY(sys32_getresuid16_wrapper)
 ENTRY(sys32_poll_wrapper)
        llgtr   %r2,%r2                 # struct pollfd *
        llgfr   %r3,%r3                 # unsigned int
-       lgfr    %r4,%r4                 # long
+       lgfr    %r4,%r4                 # int
        jg      sys_poll                # branch to system call
 
 ENTRY(sys32_setresgid16_wrapper)
index 3201ae447990c50052d7536d079e39286a77120d..4261aa799774f5972940f22ebd1b7c7ea29220f8 100644 (file)
@@ -76,7 +76,6 @@ static void default_idle(void)
        if (test_thread_flag(TIF_MCCK_PENDING)) {
                local_mcck_enable();
                local_irq_enable();
-               s390_handle_mcck();
                return;
        }
        trace_hardirqs_on();
@@ -93,10 +92,12 @@ void cpu_idle(void)
        for (;;) {
                tick_nohz_idle_enter();
                rcu_idle_enter();
-               while (!need_resched())
+               while (!need_resched() && !test_thread_flag(TIF_MCCK_PENDING))
                        default_idle();
                rcu_idle_exit();
                tick_nohz_idle_exit();
+               if (test_thread_flag(TIF_MCCK_PENDING))
+                       s390_handle_mcck();
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
index 573bc29551ef471fee58b89d02df0ea0ff956503..9d82ed4bcb273a91bd6c4875d204218da2d420a2 100644 (file)
@@ -740,20 +740,17 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->gprs[2]);
 
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(is_compat_task() ?
-                                       AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
-                                   regs->gprs[2], regs->orig_gpr2,
-                                   regs->gprs[3], regs->gprs[4],
-                                   regs->gprs[5]);
+       audit_syscall_entry(is_compat_task() ?
+                               AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
+                           regs->gprs[2], regs->orig_gpr2,
+                           regs->gprs[3], regs->gprs[4],
+                           regs->gprs[5]);
        return ret ?: regs->gprs[2];
 }
 
 asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
 {
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
-                                  regs->gprs[2]);
+       audit_syscall_exit(regs);
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_exit(regs, regs->gprs[2]);
index fa02f443f5f65dfa70c5804c9b411d9b357d7dd1..14da278febbfa89c2a20ea797fa9a4c6ff1a1de1 100644 (file)
@@ -113,11 +113,14 @@ static void fixup_clock_comparator(unsigned long long delta)
 static int s390_next_ktime(ktime_t expires,
                           struct clock_event_device *evt)
 {
+       struct timespec ts;
        u64 nsecs;
 
-       nsecs = ktime_to_ns(ktime_sub(expires, ktime_get_monotonic_offset()));
+       ts.tv_sec = ts.tv_nsec = 0;
+       monotonic_to_bootbased(&ts);
+       nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires));
        do_div(nsecs, 125);
-       S390_lowcore.clock_comparator = TOD_UNIX_EPOCH + (nsecs << 9);
+       S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9);
        set_clock_comparator(S390_lowcore.clock_comparator);
        return 0;
 }
index e4c79ebb40e628850fd230fc94a0c7fdc77aaeb1..21109c63eb12961483134141c67bfc8c2b8f8315 100644 (file)
@@ -9,12 +9,12 @@
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
 OUTPUT_ARCH(s390)
-ENTRY(_start)
+ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
-ENTRY(_start)
+ENTRY(startup)
 jiffies = jiffies_64;
 #endif
 
index 9a4d02f64f16e6af778555e89925ac71c9f76ce4..51b0738e13d12ef21ae05b68aa4ccc17d2862c9a 100644 (file)
@@ -574,7 +574,7 @@ static inline void page_table_free_pgste(unsigned long *table)
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        mp = (struct gmap_pgtable *) page->index;
        BUG_ON(!list_empty(&mp->mapper));
-       pgtable_page_ctor(page);
+       pgtable_page_dtor(page);
        atomic_set(&page->_mapcount, -1);
        kfree(mp);
        __free_page(page);
index 577abba3fac64a092e0bac9e47b9a51cee7ed415..83bb96079c43c513a832c6dd41a8de32a9cdffe6 100644 (file)
@@ -408,7 +408,7 @@ ENTRY(handle_sys)
        sw      r9, [r0, PT_EPC]
 
        cmpi.c  r27, __NR_syscalls      # check syscall number
-       bgtu    illegal_syscall
+       bgeu    illegal_syscall
 
        slli    r8, r27, 2              # get syscall routine
        la      r11, sys_call_table
index 3c8db65c89e5583ef16907f9d44eb0a9a74461ff..713fb58ca50724309d14f326c047bc4443df4772 100644 (file)
@@ -859,6 +859,7 @@ config PCI
        depends on SYS_SUPPORTS_PCI
        select PCI_DOMAINS
        select GENERIC_PCI_IOMAP
+       select NO_GENERIC_PCI_IOPORT_MAP
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 8f18dd090a66021b2a17051a0ade4f03f8ae71b4..1e7b0e2e764d1ae1319dd5a63ec563c9af9f1120 100644 (file)
@@ -356,8 +356,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 #ifndef CONFIG_GENERIC_IOMAP
 
-static void __iomem *ioport_map_pci(struct pci_dev *dev,
-                                   unsigned long port, unsigned int nr)
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+                              unsigned long port, unsigned int nr)
 {
        struct pci_channel *chan = dev->sysdata;
 
index 6c2239cca1a2d86204a52ecef53ab5514f8a6073..2d3e906aa72252d3b827a12405546465127d5f78 100644 (file)
@@ -76,7 +76,10 @@ struct pt_dspregs {
 #ifdef __KERNEL__
 
 #define MAX_REG_OFFSET         offsetof(struct pt_regs, tra)
-#define regs_return_value(_regs)       ((_regs)->regs[0])
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       return regs->regs[0];
+}
 
 #endif /* __KERNEL__ */
 
index bf9be7764d69f250978300cfb5c3e556e0d71e76..eb3fcceaf64b7bb5942a081637e78c5d479bad86 100644 (file)
@@ -13,7 +13,10 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #define MAX_REG_OFFSET         offsetof(struct pt_regs, tregs[7])
-#define regs_return_value(_regs)       ((_regs)->regs[3])
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       return regs->regs[3];
+}
 
 #endif /* __KERNEL__ */
 
index 92b3c276339a3a50d95a027c1d2a2e902a507ee3..a3e651563763aaabf76818e68729a53bc98aeaf7 100644 (file)
@@ -518,10 +518,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->regs[0]);
 
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(audit_arch(), regs->regs[3],
-                                   regs->regs[4], regs->regs[5],
-                                   regs->regs[6], regs->regs[7]);
+       audit_syscall_entry(audit_arch(), regs->regs[3],
+                           regs->regs[4], regs->regs[5],
+                           regs->regs[6], regs->regs[7]);
 
        return ret ?: regs->regs[0];
 }
@@ -530,9 +529,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 {
        int step;
 
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
-                                  regs->regs[0]);
+       audit_syscall_exit(regs);
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_exit(regs, regs->regs[0]);
index c8f97649f354b5f4b80366b79a95c9a9a0f4d4bb..3d0080b5c976bb9b19fbbc8ac5116239c7d841e3 100644 (file)
@@ -536,10 +536,9 @@ asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs)
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->regs[9]);
 
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(audit_arch(), regs->regs[1],
-                                   regs->regs[2], regs->regs[3],
-                                   regs->regs[4], regs->regs[5]);
+       audit_syscall_entry(audit_arch(), regs->regs[1],
+                           regs->regs[2], regs->regs[3],
+                           regs->regs[4], regs->regs[5]);
 
        return ret ?: regs->regs[9];
 }
@@ -548,9 +547,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 {
        int step;
 
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
-                                  regs->regs[9]);
+       audit_syscall_exit(regs);
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_exit(regs, regs->regs[9]);
index 96657992a72eef8f69580cc9cdb12e2c184639ec..ca5580e4d813711f272c57ddb6b5f43428ed99f9 100644 (file)
@@ -33,6 +33,7 @@ config SPARC
 config SPARC32
        def_bool !64BIT
        select GENERIC_ATOMIC64
+       select CLZ_TAB
 
 config SPARC64
        def_bool 64BIT
index a0e1bcf843a1ed5f9931a89c6cc63d4cd636d4ae..c00c3b5c2806edfac2b2b7f44f79045ae1bfec01 100644 (file)
@@ -207,7 +207,15 @@ do {       current_thread_info()->syscall_noerror = 1; \
 #define instruction_pointer(regs) ((regs)->tpc)
 #define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
-#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+       return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY));
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       return regs->u_regs[UREG_I0];
+}
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *);
 #else
index 96ee50a806613b782ce11e8627f1911ede3fde3f..9388844cd88c5afa47f3a24027019a96d11895ba 100644 (file)
@@ -1071,32 +1071,22 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->u_regs[UREG_G1]);
 
-       if (unlikely(current->audit_context) && !ret)
-               audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
-                                    AUDIT_ARCH_SPARC :
-                                    AUDIT_ARCH_SPARC64),
-                                   regs->u_regs[UREG_G1],
-                                   regs->u_regs[UREG_I0],
-                                   regs->u_regs[UREG_I1],
-                                   regs->u_regs[UREG_I2],
-                                   regs->u_regs[UREG_I3]);
+       audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
+                            AUDIT_ARCH_SPARC :
+                            AUDIT_ARCH_SPARC64),
+                           regs->u_regs[UREG_G1],
+                           regs->u_regs[UREG_I0],
+                           regs->u_regs[UREG_I1],
+                           regs->u_regs[UREG_I2],
+                           regs->u_regs[UREG_I3]);
 
        return ret;
 }
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
-#ifdef CONFIG_AUDITSYSCALL
-       if (unlikely(current->audit_context)) {
-               unsigned long tstate = regs->tstate;
-               int result = AUDITSC_SUCCESS;
+       audit_syscall_exit(regs);
 
-               if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
-                       result = AUDITSC_FAILURE;
-
-               audit_syscall_exit(result, regs->u_regs[UREG_I0]);
-       }
-#endif
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_exit(regs, regs->u_regs[UREG_G1]);
 
index 422c16dad1f66610f4d90b8723b652c658cfcae3..e61165161dd33d1df3f6b104edbf183f15136ebb 100644 (file)
@@ -399,6 +399,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
        timers_global = (void __iomem *)
                (unsigned long) addr[num_cpu_timers];
 
+       /* Every per-cpu timer works in timer mode */
+       sbus_writel(0x00000000, &timers_global->timer_config);
+
        sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
 
        master_l10_counter = &timers_global->l10_count;
index 681b3683da9e6134d065d8d719a691738f01653d..d74bc0925f2d2fc0ffbfb419f01e55fcd10d4019 100644 (file)
@@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-       .data
-       .align 8
-       .globl  __clz_tab
-__clz_tab:
-       .byte   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
-       .byte   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
-       .byte   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-       .byte   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .byte   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
-       .size    __clz_tab,256
-       .global .udiv
-
        .text
        .align 4
+       .global .udiv
        .globl __divdi3
 __divdi3:
        save %sp,-104,%sp
index c9da32b0c707015c19db39b49785cd8b0610a35a..06b190390505f848a095648d2c555bd9d996604d 100644 (file)
@@ -167,17 +167,15 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit)
        int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
        int tracesysgood;
 
-       if (unlikely(current->audit_context)) {
-               if (!entryexit)
-                       audit_syscall_entry(HOST_AUDIT_ARCH,
-                                           UPT_SYSCALL_NR(regs),
-                                           UPT_SYSCALL_ARG1(regs),
-                                           UPT_SYSCALL_ARG2(regs),
-                                           UPT_SYSCALL_ARG3(regs),
-                                           UPT_SYSCALL_ARG4(regs));
-               else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
-                                       UPT_SYSCALL_RET(regs));
-       }
+       if (!entryexit)
+               audit_syscall_entry(HOST_AUDIT_ARCH,
+                                   UPT_SYSCALL_NR(regs),
+                                   UPT_SYSCALL_ARG1(regs),
+                                   UPT_SYSCALL_ARG2(regs),
+                                   UPT_SYSCALL_ARG3(regs),
+                                   UPT_SYSCALL_ARG4(regs));
+       else
+               audit_syscall_exit(regs);
 
        /* Fake a debug trap */
        if (is_singlestep)
index 028079065af6c55ac518969a6b5c1d8ae321b6c3..7cab8c08e6d1d2eee802397c9bc17ea0f7b1bbc1 100644 (file)
@@ -1,3 +1,4 @@
 boot/compressed/vmlinux
 tools/test_get_len
+tools/insn_sanity
 
index 6c14ecd851d0b3ae9d32cbd73ce97419b1cb4a48..5bed94e189fab8ef9bf24f038763ee90bc45b798 100644 (file)
@@ -125,16 +125,6 @@ config HAVE_LATENCYTOP_SUPPORT
 config MMU
        def_bool y
 
-config ZONE_DMA
-       bool "DMA memory allocation support" if EXPERT
-       default y
-       help
-         DMA memory allocation support allows devices with less than 32-bit
-         addressing to allocate within the first 16MB of address space.
-         Disable if no such devices will be used.
-
-         If unsure, say Y.
-
 config SBUS
        bool
 
@@ -255,6 +245,16 @@ source "kernel/Kconfig.freezer"
 
 menu "Processor type and features"
 
+config ZONE_DMA
+       bool "DMA memory allocation support" if EXPERT
+       default y
+       help
+         DMA memory allocation support allows devices with less than 32-bit
+         addressing to allocate within the first 16MB of address space.
+         Disable if no such devices will be used.
+
+         If unsure, say Y.
+
 source "kernel/time/Kconfig"
 
 config SMP
@@ -360,7 +360,6 @@ config X86_NUMACHIP
        depends on NUMA
        depends on SMP
        depends on X86_X2APIC
-       depends on !EDAC_AMD64
        ---help---
          Adds support for Numascale NumaChip large-SMP systems. Needed to
          enable more than ~168 cores.
index 3a19d04cebebe920e78269693c97637a19404b3b..7116dcba0c9ed2df2afd680c4407d7f57c0244a7 100644 (file)
@@ -321,6 +321,8 @@ static void parse_elf(void *output)
                default: /* Ignore other PT_* */ break;
                }
        }
+
+       free(phdrs);
 }
 
 asmlinkage void decompress_kernel(void *rmode, memptr heap,
index 1106261856c8022610bface1d874c38f24b9bf63..e3e734005e19c1849dfb6f6be7a5b26f2fc9b374 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/segment.h>
 #include <asm/irqflags.h>
 #include <linux/linkage.h>
+#include <linux/err.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
 #include <linux/elf-em.h>
@@ -189,7 +190,7 @@ sysexit_from_sys_call:
        movl %ebx,%edx                  /* 3rd arg: 1st syscall arg */
        movl %eax,%esi                  /* 2nd arg: syscall number */
        movl $AUDIT_ARCH_I386,%edi      /* 1st arg: audit arch */
-       call audit_syscall_entry
+       call __audit_syscall_entry
        movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall number */
        cmpq $(IA32_NR_syscalls-1),%rax
        ja ia32_badsys
@@ -206,12 +207,13 @@ sysexit_from_sys_call:
        TRACE_IRQS_ON
        sti
        movl %eax,%esi          /* second arg, syscall return value */
-       cmpl $0,%eax            /* is it < 0? */
-       setl %al                /* 1 if so, 0 if not */
+       cmpl $-MAX_ERRNO,%eax   /* is it an error ? */
+       jbe 1f
+       movslq %eax, %rsi       /* if error sign extend to 64 bits */
+1:     setbe %al               /* 1 if error, 0 if not */
        movzbl %al,%edi         /* zero-extend that into %edi */
-       inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
-       call audit_syscall_exit
-       movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall return value */
+       call __audit_syscall_exit
+       movq RAX-ARGOFFSET(%rsp),%rax   /* reload syscall return value */
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
        cli
        TRACE_IRQS_OFF
index 0c9fa2745f13e4c1f242d3f37813f25849aebd6d..b3b7332629096849d11866c017c4444f8d156f9e 100644 (file)
@@ -145,13 +145,13 @@ extern void __add_wrong_size(void)
 
 #ifdef __HAVE_ARCH_CMPXCHG
 #define cmpxchg(ptr, old, new)                                         \
-       __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+       __cmpxchg(ptr, old, new, sizeof(*(ptr)))
 
 #define sync_cmpxchg(ptr, old, new)                                    \
-       __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+       __sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))
 
 #define cmpxchg_local(ptr, old, new)                                   \
-       __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+       __cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
 #endif
 
 /*
index 17c5d4bdee5ed5124c7be91bf8d4ef73b39b7c2f..8d67d428b0f993f79031bb5f9702bd44adc8001a 100644 (file)
 #define X86_FEATURE_WDT                (6*32+13) /* Watchdog timer */
 #define X86_FEATURE_LWP                (6*32+15) /* Light Weight Profiling */
 #define X86_FEATURE_FMA4       (6*32+16) /* 4 operands MAC instructions */
+#define X86_FEATURE_TCE                (6*32+17) /* translation cache extension */
 #define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
 #define X86_FEATURE_TBM                (6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT    (6*32+22) /* topology extensions CPUID leafs */
index 6919e936345bad54470bf334f33641ca60436156..247904945d3f3055dccf6e9fd0c05474167f98d7 100644 (file)
@@ -29,10 +29,11 @@ extern unsigned int sig_xstate_size;
 extern void fpu_init(void);
 extern void mxcsr_feature_mask_init(void);
 extern int init_fpu(struct task_struct *child);
-extern asmlinkage void math_state_restore(void);
-extern void __math_state_restore(void);
+extern void math_state_restore(void);
 extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
 
+DECLARE_PER_CPU(struct task_struct *, fpu_owner_task);
+
 extern user_regset_active_fn fpregs_active, xfpregs_active;
 extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get,
                                xstateregs_get;
@@ -212,19 +213,11 @@ static inline void fpu_fxsave(struct fpu *fpu)
 
 #endif /* CONFIG_X86_64 */
 
-/* We need a safe address that is cheap to find and that is already
-   in L1 during context switch. The best choices are unfortunately
-   different for UP and SMP */
-#ifdef CONFIG_SMP
-#define safe_address (__per_cpu_offset[0])
-#else
-#define safe_address (__get_cpu_var(kernel_cpustat).cpustat[CPUTIME_USER])
-#endif
-
 /*
- * These must be called with preempt disabled
+ * These must be called with preempt disabled. Returns
+ * 'true' if the FPU state is still intact.
  */
-static inline void fpu_save_init(struct fpu *fpu)
+static inline int fpu_save_init(struct fpu *fpu)
 {
        if (use_xsave()) {
                fpu_xsave(fpu);
@@ -233,33 +226,33 @@ static inline void fpu_save_init(struct fpu *fpu)
                 * xsave header may indicate the init state of the FP.
                 */
                if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
-                       return;
+                       return 1;
        } else if (use_fxsr()) {
                fpu_fxsave(fpu);
        } else {
                asm volatile("fnsave %[fx]; fwait"
                             : [fx] "=m" (fpu->state->fsave));
-               return;
+               return 0;
        }
 
-       if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
+       /*
+        * If exceptions are pending, we need to clear them so
+        * that we don't randomly get exceptions later.
+        *
+        * FIXME! Is this perhaps only true for the old-style
+        * irq13 case? Maybe we could leave the x87 state
+        * intact otherwise?
+        */
+       if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) {
                asm volatile("fnclex");
-
-       /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
-          is pending.  Clear the x87 state here by setting it to fixed
-          values. safe_address is a random variable that should be in L1 */
-       alternative_input(
-               ASM_NOP8 ASM_NOP2,
-               "emms\n\t"              /* clear stack tags */
-               "fildl %P[addr]",       /* set F?P to defined value */
-               X86_FEATURE_FXSAVE_LEAK,
-               [addr] "m" (safe_address));
+               return 0;
+       }
+       return 1;
 }
 
-static inline void __save_init_fpu(struct task_struct *tsk)
+static inline int __save_init_fpu(struct task_struct *tsk)
 {
-       fpu_save_init(&tsk->thread.fpu);
-       task_thread_info(tsk)->status &= ~TS_USEDFPU;
+       return fpu_save_init(&tsk->thread.fpu);
 }
 
 static inline int fpu_fxrstor_checking(struct fpu *fpu)
@@ -277,44 +270,212 @@ static inline int fpu_restore_checking(struct fpu *fpu)
 
 static inline int restore_fpu_checking(struct task_struct *tsk)
 {
+       /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+          is pending.  Clear the x87 state here by setting it to fixed
+          values. "m" is a random variable that should be in L1 */
+       alternative_input(
+               ASM_NOP8 ASM_NOP2,
+               "emms\n\t"              /* clear stack tags */
+               "fildl %P[addr]",       /* set F?P to defined value */
+               X86_FEATURE_FXSAVE_LEAK,
+               [addr] "m" (tsk->thread.fpu.has_fpu));
+
        return fpu_restore_checking(&tsk->thread.fpu);
 }
 
 /*
- * Signal frame handlers...
+ * Software FPU state helpers. Careful: these need to
+ * be preemption protection *and* they need to be
+ * properly paired with the CR0.TS changes!
  */
-extern int save_i387_xstate(void __user *buf);
-extern int restore_i387_xstate(void __user *buf);
+static inline int __thread_has_fpu(struct task_struct *tsk)
+{
+       return tsk->thread.fpu.has_fpu;
+}
 
-static inline void __unlazy_fpu(struct task_struct *tsk)
+/* Must be paired with an 'stts' after! */
+static inline void __thread_clear_has_fpu(struct task_struct *tsk)
 {
-       if (task_thread_info(tsk)->status & TS_USEDFPU) {
-               __save_init_fpu(tsk);
-               stts();
-       } else
-               tsk->fpu_counter = 0;
+       tsk->thread.fpu.has_fpu = 0;
+       percpu_write(fpu_owner_task, NULL);
+}
+
+/* Must be paired with a 'clts' before! */
+static inline void __thread_set_has_fpu(struct task_struct *tsk)
+{
+       tsk->thread.fpu.has_fpu = 1;
+       percpu_write(fpu_owner_task, tsk);
+}
+
+/*
+ * Encapsulate the CR0.TS handling together with the
+ * software flag.
+ *
+ * These generally need preemption protection to work,
+ * do try to avoid using these on their own.
+ */
+static inline void __thread_fpu_end(struct task_struct *tsk)
+{
+       __thread_clear_has_fpu(tsk);
+       stts();
+}
+
+static inline void __thread_fpu_begin(struct task_struct *tsk)
+{
+       clts();
+       __thread_set_has_fpu(tsk);
+}
+
+/*
+ * FPU state switching for scheduling.
+ *
+ * This is a two-stage process:
+ *
+ *  - switch_fpu_prepare() saves the old state and
+ *    sets the new state of the CR0.TS bit. This is
+ *    done within the context of the old process.
+ *
+ *  - switch_fpu_finish() restores the new state as
+ *    necessary.
+ */
+typedef struct { int preload; } fpu_switch_t;
+
+/*
+ * FIXME! We could do a totally lazy restore, but we need to
+ * add a per-cpu "this was the task that last touched the FPU
+ * on this CPU" variable, and the task needs to have a "I last
+ * touched the FPU on this CPU" and check them.
+ *
+ * We don't do that yet, so "fpu_lazy_restore()" always returns
+ * false, but some day..
+ */
+static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
+{
+       return new == percpu_read_stable(fpu_owner_task) &&
+               cpu == new->thread.fpu.last_cpu;
+}
+
+static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct task_struct *new, int cpu)
+{
+       fpu_switch_t fpu;
+
+       fpu.preload = tsk_used_math(new) && new->fpu_counter > 5;
+       if (__thread_has_fpu(old)) {
+               if (!__save_init_fpu(old))
+                       cpu = ~0;
+               old->thread.fpu.last_cpu = cpu;
+               old->thread.fpu.has_fpu = 0;    /* But leave fpu_owner_task! */
+
+               /* Don't change CR0.TS if we just switch! */
+               if (fpu.preload) {
+                       new->fpu_counter++;
+                       __thread_set_has_fpu(new);
+                       prefetch(new->thread.fpu.state);
+               } else
+                       stts();
+       } else {
+               old->fpu_counter = 0;
+               old->thread.fpu.last_cpu = ~0;
+               if (fpu.preload) {
+                       new->fpu_counter++;
+                       if (fpu_lazy_restore(new, cpu))
+                               fpu.preload = 0;
+                       else
+                               prefetch(new->thread.fpu.state);
+                       __thread_fpu_begin(new);
+               }
+       }
+       return fpu;
+}
+
+/*
+ * By the time this gets called, we've already cleared CR0.TS and
+ * given the process the FPU if we are going to preload the FPU
+ * state - all we need to do is to conditionally restore the register
+ * state itself.
+ */
+static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu)
+{
+       if (fpu.preload) {
+               if (unlikely(restore_fpu_checking(new)))
+                       __thread_fpu_end(new);
+       }
 }
 
+/*
+ * Signal frame handlers...
+ */
+extern int save_i387_xstate(void __user *buf);
+extern int restore_i387_xstate(void __user *buf);
+
 static inline void __clear_fpu(struct task_struct *tsk)
 {
-       if (task_thread_info(tsk)->status & TS_USEDFPU) {
+       if (__thread_has_fpu(tsk)) {
                /* Ignore delayed exceptions from user space */
                asm volatile("1: fwait\n"
                             "2:\n"
                             _ASM_EXTABLE(1b, 2b));
-               task_thread_info(tsk)->status &= ~TS_USEDFPU;
-               stts();
+               __thread_fpu_end(tsk);
        }
 }
 
+/*
+ * Were we in an interrupt that interrupted kernel mode?
+ *
+ * We can do a kernel_fpu_begin/end() pair *ONLY* if that
+ * pair does nothing at all: the thread must not have fpu (so
+ * that we don't try to save the FPU state), and TS must
+ * be set (so that the clts/stts pair does nothing that is
+ * visible in the interrupted kernel thread).
+ */
+static inline bool interrupted_kernel_fpu_idle(void)
+{
+       return !__thread_has_fpu(current) &&
+               (read_cr0() & X86_CR0_TS);
+}
+
+/*
+ * Were we in user mode (or vm86 mode) when we were
+ * interrupted?
+ *
+ * Doing kernel_fpu_begin/end() is ok if we are running
+ * in an interrupt context from user mode - we'll just
+ * save the FPU state as required.
+ */
+static inline bool interrupted_user_mode(void)
+{
+       struct pt_regs *regs = get_irq_regs();
+       return regs && user_mode_vm(regs);
+}
+
+/*
+ * Can we use the FPU in kernel mode with the
+ * whole "kernel_fpu_begin/end()" sequence?
+ *
+ * It's always ok in process context (ie "not interrupt")
+ * but it is sometimes ok even from an irq.
+ */
+static inline bool irq_fpu_usable(void)
+{
+       return !in_interrupt() ||
+               interrupted_user_mode() ||
+               interrupted_kernel_fpu_idle();
+}
+
 static inline void kernel_fpu_begin(void)
 {
-       struct thread_info *me = current_thread_info();
+       struct task_struct *me = current;
+
+       WARN_ON_ONCE(!irq_fpu_usable());
        preempt_disable();
-       if (me->status & TS_USEDFPU)
-               __save_init_fpu(me->task);
-       else
+       if (__thread_has_fpu(me)) {
+               __save_init_fpu(me);
+               __thread_clear_has_fpu(me);
+               /* We do 'stts()' in kernel_fpu_end() */
+       } else {
+               percpu_write(fpu_owner_task, NULL);
                clts();
+       }
 }
 
 static inline void kernel_fpu_end(void)
@@ -323,14 +484,6 @@ static inline void kernel_fpu_end(void)
        preempt_enable();
 }
 
-static inline bool irq_fpu_usable(void)
-{
-       struct pt_regs *regs;
-
-       return !in_interrupt() || !(regs = get_irq_regs()) || \
-               user_mode(regs) || (read_cr0() & X86_CR0_TS);
-}
-
 /*
  * Some instructions like VIA's padlock instructions generate a spurious
  * DNA fault but don't modify SSE registers. And these instructions
@@ -362,21 +515,65 @@ static inline void irq_ts_restore(int TS_state)
                stts();
 }
 
+/*
+ * The question "does this thread have fpu access?"
+ * is slightly racy, since preemption could come in
+ * and revoke it immediately after the test.
+ *
+ * However, even in that very unlikely scenario,
+ * we can just assume we have FPU access - typically
+ * to save the FP state - we'll just take a #NM
+ * fault and get the FPU access back.
+ *
+ * The actual user_fpu_begin/end() functions
+ * need to be preemption-safe, though.
+ *
+ * NOTE! user_fpu_end() must be used only after you
+ * have saved the FP state, and user_fpu_begin() must
+ * be used only immediately before restoring it.
+ * These functions do not do any save/restore on
+ * their own.
+ */
+static inline int user_has_fpu(void)
+{
+       return __thread_has_fpu(current);
+}
+
+static inline void user_fpu_end(void)
+{
+       preempt_disable();
+       __thread_fpu_end(current);
+       preempt_enable();
+}
+
+static inline void user_fpu_begin(void)
+{
+       preempt_disable();
+       if (!user_has_fpu())
+               __thread_fpu_begin(current);
+       preempt_enable();
+}
+
 /*
  * These disable preemption on their own and are safe
  */
 static inline void save_init_fpu(struct task_struct *tsk)
 {
+       WARN_ON_ONCE(!__thread_has_fpu(tsk));
        preempt_disable();
        __save_init_fpu(tsk);
-       stts();
+       __thread_fpu_end(tsk);
        preempt_enable();
 }
 
 static inline void unlazy_fpu(struct task_struct *tsk)
 {
        preempt_disable();
-       __unlazy_fpu(tsk);
+       if (__thread_has_fpu(tsk)) {
+               __save_init_fpu(tsk);
+               __thread_fpu_end(tsk);
+       } else
+               tsk->fpu_counter = 0;
        preempt_enable();
 }
 
index ab4092e3214ecea7d02e3827fe596ed662243214..7b9cfc4878afc374dacb4852312be4fcba35384e 100644 (file)
@@ -190,6 +190,9 @@ struct x86_emulate_ops {
        int (*intercept)(struct x86_emulate_ctxt *ctxt,
                         struct x86_instruction_info *info,
                         enum x86_intercept_stage stage);
+
+       bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
+                        u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 };
 
 typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -298,6 +301,19 @@ struct x86_emulate_ctxt {
 #define X86EMUL_MODE_PROT     (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
                               X86EMUL_MODE_PROT64)
 
+/* CPUID vendors */
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65
+
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273
+
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
+
 enum x86_intercept_stage {
        X86_ICTP_NONE = 0,   /* Allow zero-init to not match anything */
        X86_ICPT_PRE_EXCEPT,
index aa9088c26931ae349c0bc6fbfece5fe0b10edfb9..58545c97d071c84dba4a05b59bad7be5d0b69b01 100644 (file)
@@ -374,6 +374,8 @@ union thread_xstate {
 };
 
 struct fpu {
+       unsigned int last_cpu;
+       unsigned int has_fpu;
        union thread_xstate *state;
 };
 
index bc817cd8b44359b615e34f9b08aa67a61425cf29..cfd8144d552742bcd12ac1b42f0d7b45adc5c2fb 100644 (file)
@@ -247,8 +247,6 @@ static inline struct thread_info *current_thread_info(void)
  * ever touches our thread-synchronous status, so we don't
  * have to worry about atomic accesses.
  */
-#define TS_USEDFPU             0x0001  /* FPU was used by this task
-                                          this quantum (SMP) */
 #define TS_COMPAT              0x0002  /* 32bit syscall active (64BIT)*/
 #define TS_POLLING             0x0004  /* idle task polling need_resched,
                                           skip sending interrupt */
index b4a3db7ce1408213e0def655e775ff3aa94c82c0..21f77b89e47a6aeea5ab00c01c28db2d54f0520b 100644 (file)
@@ -7,6 +7,7 @@
 #  include <asm/unistd_32.h>
 #  define __ARCH_WANT_IPC_PARSE_VERSION
 #  define __ARCH_WANT_STAT64
+#  define __ARCH_WANT_SYS_IPC
 #  define __ARCH_WANT_SYS_OLD_MMAP
 #  define __ARCH_WANT_SYS_OLD_SELECT
 
index 8e862aaf0d905555e23265df00e139346d9b6649..becf47b81735ef6731e0271d0de7c0d939a389a9 100644 (file)
@@ -65,7 +65,7 @@
  * UV2: Bit 19 selects between
  *  (0): 10 microsecond timebase and
  *  (1): 80 microseconds
- *  we're using 655us, similar to UV1: 65 units of 10us
+ *  we're using 560us, similar to UV1: 65 units of 10us
  */
 #define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL)
 #define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)
 #define FLUSH_RETRY_TIMEOUT            2
 #define FLUSH_GIVEUP                   3
 #define FLUSH_COMPLETE                 4
+#define FLUSH_RETRY_BUSYBUG            5
 
 /*
  * tuning the action when the numalink network is extremely delayed
@@ -235,10 +236,10 @@ struct bau_msg_payload {
 
 
 /*
- * Message header:  16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
+ * UV1 Message header:  16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
  * see table 4.2.3.0.1 in broacast_assist spec.
  */
-struct bau_msg_header {
+struct uv1_bau_msg_header {
        unsigned int    dest_subnodeid:6;       /* must be 0x10, for the LB */
        /* bits 5:0 */
        unsigned int    base_dest_nasid:15;     /* nasid of the first bit */
@@ -317,20 +318,88 @@ struct bau_msg_header {
        /* bits 127:107 */
 };
 
+/*
+ * UV2 Message header:  16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
+ * see figure 9-2 of harp_sys.pdf
+ */
+struct uv2_bau_msg_header {
+       unsigned int    base_dest_nasid:15;     /* nasid of the first bit */
+       /* bits 14:0 */                         /* in uvhub map */
+       unsigned int    dest_subnodeid:5;       /* must be 0x10, for the LB */
+       /* bits 19:15 */
+       unsigned int    rsvd_1:1;               /* must be zero */
+       /* bit 20 */
+       /* Address bits 59:21 */
+       /* bits 25:2 of address (44:21) are payload */
+       /* these next 24 bits become bytes 12-14 of msg */
+       /* bits 28:21 land in byte 12 */
+       unsigned int    replied_to:1;           /* sent as 0 by the source to
+                                                  byte 12 */
+       /* bit 21 */
+       unsigned int    msg_type:3;             /* software type of the
+                                                  message */
+       /* bits 24:22 */
+       unsigned int    canceled:1;             /* message canceled, resource
+                                                  is to be freed*/
+       /* bit 25 */
+       unsigned int    payload_1:3;            /* not currently used */
+       /* bits 28:26 */
+
+       /* bits 36:29 land in byte 13 */
+       unsigned int    payload_2a:3;           /* not currently used */
+       unsigned int    payload_2b:5;           /* not currently used */
+       /* bits 36:29 */
+
+       /* bits 44:37 land in byte 14 */
+       unsigned int    payload_3:8;            /* not currently used */
+       /* bits 44:37 */
+
+       unsigned int    rsvd_2:7;               /* reserved */
+       /* bits 51:45 */
+       unsigned int    swack_flag:1;           /* software acknowledge flag */
+       /* bit 52 */
+       unsigned int    rsvd_3a:3;              /* must be zero */
+       unsigned int    rsvd_3b:8;              /* must be zero */
+       unsigned int    rsvd_3c:8;              /* must be zero */
+       unsigned int    rsvd_3d:3;              /* must be zero */
+       /* bits 74:53 */
+       unsigned int    fairness:3;             /* usually zero */
+       /* bits 77:75 */
+
+       unsigned int    sequence:16;            /* message sequence number */
+       /* bits 93:78  Suppl_A  */
+       unsigned int    chaining:1;             /* next descriptor is part of
+                                                  this activation*/
+       /* bit 94 */
+       unsigned int    multilevel:1;           /* multi-level multicast
+                                                  format */
+       /* bit 95 */
+       unsigned int    rsvd_4:24;              /* ordered / source node /
+                                                  source subnode / aging
+                                                  must be zero */
+       /* bits 119:96 */
+       unsigned int    command:8;              /* message type */
+       /* bits 127:120 */
+};
+
 /*
  * The activation descriptor:
  * The format of the message to send, plus all accompanying control
  * Should be 64 bytes
  */
 struct bau_desc {
-       struct pnmask                   distribution;
+       struct pnmask                           distribution;
        /*
         * message template, consisting of header and payload:
         */
-       struct bau_msg_header           header;
-       struct bau_msg_payload          payload;
+       union bau_msg_header {
+               struct uv1_bau_msg_header       uv1_hdr;
+               struct uv2_bau_msg_header       uv2_hdr;
+       } header;
+
+       struct bau_msg_payload                  payload;
 };
-/*
+/* UV1:
  *   -payload--    ---------header------
  *   bytes 0-11    bits 41-56  bits 58-81
  *       A           B  (2)      C (3)
@@ -340,6 +409,16 @@ struct bau_desc {
  *   bytes 0-11  bytes 12-14  bytes 16-17  (byte 15 filled in by hw as vector)
  *   ------------payload queue-----------
  */
+/* UV2:
+ *   -payload--    ---------header------
+ *   bytes 0-11    bits 70-78  bits 21-44
+ *       A           B  (2)      C (3)
+ *
+ *            A/B/C are moved to:
+ *       A            C          B
+ *   bytes 0-11  bytes 12-14  bytes 16-17  (byte 15 filled in by hw as vector)
+ *   ------------payload queue-----------
+ */
 
 /*
  * The payload queue on the destination side is an array of these.
@@ -385,7 +464,6 @@ struct bau_pq_entry {
 struct msg_desc {
        struct bau_pq_entry     *msg;
        int                     msg_slot;
-       int                     swack_slot;
        struct bau_pq_entry     *queue_first;
        struct bau_pq_entry     *queue_last;
 };
@@ -405,6 +483,7 @@ struct ptc_stats {
                                                   requests */
        unsigned long   s_stimeout;             /* source side timeouts */
        unsigned long   s_dtimeout;             /* destination side timeouts */
+       unsigned long   s_strongnacks;          /* number of strong nack's */
        unsigned long   s_time;                 /* time spent in sending side */
        unsigned long   s_retriesok;            /* successful retries */
        unsigned long   s_ntargcpu;             /* total number of cpu's
@@ -439,6 +518,9 @@ struct ptc_stats {
        unsigned long   s_retry_messages;       /* retry broadcasts */
        unsigned long   s_bau_reenabled;        /* for bau enable/disable */
        unsigned long   s_bau_disabled;         /* for bau enable/disable */
+       unsigned long   s_uv2_wars;             /* uv2 workaround, perm. busy */
+       unsigned long   s_uv2_wars_hw;          /* uv2 workaround, hiwater */
+       unsigned long   s_uv2_war_waits;        /* uv2 workaround, long waits */
        /* destination statistics */
        unsigned long   d_alltlb;               /* times all tlb's on this
                                                   cpu were flushed */
@@ -511,9 +593,12 @@ struct bau_control {
        short                   osnode;
        short                   uvhub_cpu;
        short                   uvhub;
+       short                   uvhub_version;
        short                   cpus_in_socket;
        short                   cpus_in_uvhub;
        short                   partition_base_pnode;
+       short                   using_desc; /* an index, like uvhub_cpu */
+       unsigned int            inuse_map;
        unsigned short          message_number;
        unsigned short          uvhub_quiesce;
        short                   socket_acknowledge_count[DEST_Q_SIZE];
@@ -531,6 +616,7 @@ struct bau_control {
        int                     cong_response_us;
        int                     cong_reps;
        int                     cong_period;
+       unsigned long           clocks_per_100_usec;
        cycles_t                period_time;
        long                    period_requests;
        struct hub_and_pnode    *thp;
@@ -591,6 +677,11 @@ static inline void write_mmr_sw_ack(unsigned long mr)
        uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
 }
 
+static inline void write_gmmr_sw_ack(int pnode, unsigned long mr)
+{
+       write_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
+}
+
 static inline unsigned long read_mmr_sw_ack(void)
 {
        return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
index 54a13aaebc4006c6a55cdce0fc414e2bd563a06a..21f7385badb8f9eb4249aef142487e27b264b32d 100644 (file)
@@ -318,13 +318,13 @@ uv_gpa_in_mmr_space(unsigned long gpa)
 /* UV global physical address --> socket phys RAM */
 static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
 {
-       unsigned long paddr = gpa & uv_hub_info->gpa_mask;
+       unsigned long paddr;
        unsigned long remap_base = uv_hub_info->lowmem_remap_base;
        unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
 
        gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
                ((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
-       gpa = gpa & uv_hub_info->gpa_mask;
+       paddr = gpa & uv_hub_info->gpa_mask;
        if (paddr >= remap_base && paddr < remap_base + remap_top)
                paddr -= remap_base;
        return paddr;
index d43cad74f1661c2180cc1f9277b9553b3de7cf63..c0f7d68d318f1b7a8a6a27f798250b53c778d50f 100644 (file)
@@ -1044,6 +1044,9 @@ DEFINE_PER_CPU(char *, irq_stack_ptr) =
 
 DEFINE_PER_CPU(unsigned int, irq_count) = -1;
 
+DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
+EXPORT_PER_CPU_SYMBOL(fpu_owner_task);
+
 /*
  * Special IST stacks which the CPU switches to when it calls
  * an IST-marked descriptor entry. Up to 7 stacks (hardware
@@ -1111,6 +1114,8 @@ void debug_stack_reset(void)
 
 DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
 EXPORT_PER_CPU_SYMBOL(current_task);
+DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
+EXPORT_PER_CPU_SYMBOL(fpu_owner_task);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
index 73da6b64f5b788ccbb83eef3317c32161b755fca..d6bd49faa40cf2becce23b0b0807219178588fde 100644 (file)
@@ -439,7 +439,6 @@ void intel_pmu_pebs_enable(struct perf_event *event)
        hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
 
        cpuc->pebs_enabled |= 1ULL << hwc->idx;
-       WARN_ON_ONCE(cpuc->enabled);
 
        if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1)
                intel_pmu_lbr_enable(event);
index 3fab3de3ce96dde8b3bece9bdf65cae8c5b1e466..47a7e63bfe54d4ec466911e75a901fe45ef09eeb 100644 (file)
@@ -72,8 +72,6 @@ void intel_pmu_lbr_enable(struct perf_event *event)
        if (!x86_pmu.lbr_nr)
                return;
 
-       WARN_ON_ONCE(cpuc->enabled);
-
        /*
         * Reset the LBR stack if we changed task context to
         * avoid data leaks.
index 1aae78f775fc18e4f01b2ed568a1934e2de6dd31..4025fe4f928f6f4cb2ddcfc0233197e9e0b3ad44 100644 (file)
@@ -252,7 +252,8 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
        unsigned short ss;
        unsigned long sp;
 #endif
-       printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+       printk(KERN_DEFAULT
+              "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
        printk("PREEMPT ");
 #endif
index 6d728d9284bd0e3b94213206bd93af5afbfb7912..17107bd6e1f0af06b5e59b1c48d452305a8b3214 100644 (file)
@@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
        if (!stack) {
                if (regs)
                        stack = (unsigned long *)regs->sp;
-               else if (task && task != current)
+               else if (task != current)
                        stack = (unsigned long *)task->thread.sp;
                else
                        stack = &dummy;
@@ -269,11 +269,11 @@ void show_registers(struct pt_regs *regs)
                unsigned char c;
                u8 *ip;
 
-               printk(KERN_EMERG "Stack:\n");
+               printk(KERN_DEFAULT "Stack:\n");
                show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
-                                  0, KERN_EMERG);
+                                  0, KERN_DEFAULT);
 
-               printk(KERN_EMERG "Code: ");
+               printk(KERN_DEFAULT "Code: ");
 
                ip = (u8 *)regs->ip - code_prologue;
                if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
index 174d938d576b347365f4fdab2de8e7b85fd36f53..62d61e9976eb0a83bca3aae5c979bb63505c0bbb 100644 (file)
@@ -703,7 +703,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
 }
 #endif
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_ACPI
 /**
  * Mark ACPI NVS memory region, so that we can save/restore it during
  * hibernation and the subsequent resume.
@@ -716,7 +716,7 @@ static int __init e820_mark_nvs_memory(void)
                struct e820entry *ei = &e820.map[i];
 
                if (ei->type == E820_NVS)
-                       suspend_nvs_register(ei->addr, ei->size);
+                       acpi_nvs_register(ei->addr, ei->size);
        }
 
        return 0;
index 4af9fd2450a5e7f319f6077c75cb8a3bfca89fae..79d97e68f04238ac13993e89c016e67a7b647af6 100644 (file)
@@ -42,6 +42,7 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/err.h>
 #include <asm/thread_info.h>
 #include <asm/irqflags.h>
 #include <asm/errno.h>
@@ -453,7 +454,7 @@ sysenter_audit:
        movl %ebx,%ecx                  /* 3rd arg: 1st syscall arg */
        movl %eax,%edx                  /* 2nd arg: syscall number */
        movl $AUDIT_ARCH_I386,%eax      /* 1st arg: audit arch */
-       call audit_syscall_entry
+       call __audit_syscall_entry
        pushl_cfi %ebx
        movl PT_EAX(%esp),%eax          /* reload syscall number */
        jmp sysenter_do_call
@@ -464,11 +465,10 @@ sysexit_audit:
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_ANY)
        movl %eax,%edx          /* second arg, syscall return value */
-       cmpl $0,%eax            /* is it < 0? */
-       setl %al                /* 1 if so, 0 if not */
+       cmpl $-MAX_ERRNO,%eax   /* is it an error ? */
+       setbe %al               /* 1 if so, 0 if not */
        movzbl %al,%eax         /* zero-extend that */
-       inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
-       call audit_syscall_exit
+       call __audit_syscall_exit
        DISABLE_INTERRUPTS(CLBR_ANY)
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
index 940ba711fc286510ddc20c441fd882fe7a632b62..3fe8239fd8fbd8ef692f57517d0d1dbd37f284ae 100644 (file)
@@ -55,6 +55,7 @@
 #include <asm/paravirt.h>
 #include <asm/ftrace.h>
 #include <asm/percpu.h>
+#include <linux/err.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
 #include <linux/elf-em.h>
@@ -548,7 +549,7 @@ badsys:
 #ifdef CONFIG_AUDITSYSCALL
        /*
         * Fast path for syscall audit without full syscall trace.
-        * We just call audit_syscall_entry() directly, and then
+        * We just call __audit_syscall_entry() directly, and then
         * jump back to the normal fast path.
         */
 auditsys:
@@ -558,22 +559,21 @@ auditsys:
        movq %rdi,%rdx                  /* 3rd arg: 1st syscall arg */
        movq %rax,%rsi                  /* 2nd arg: syscall number */
        movl $AUDIT_ARCH_X86_64,%edi    /* 1st arg: audit arch */
-       call audit_syscall_entry
+       call __audit_syscall_entry
        LOAD_ARGS 0             /* reload call-clobbered registers */
        jmp system_call_fastpath
 
        /*
-        * Return fast path for syscall audit.  Call audit_syscall_exit()
+        * Return fast path for syscall audit.  Call __audit_syscall_exit()
         * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
         * masked off.
         */
 sysret_audit:
        movq RAX-ARGOFFSET(%rsp),%rsi   /* second arg, syscall return value */
-       cmpq $0,%rsi            /* is it < 0? */
-       setl %al                /* 1 if so, 0 if not */
+       cmpq $-MAX_ERRNO,%rsi   /* is it < -MAX_ERRNO? */
+       setbe %al               /* 1 if so, 0 if not */
        movzbl %al,%edi         /* zero-extend that into %edi */
-       inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
-       call audit_syscall_exit
+       call __audit_syscall_exit
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
        jmp sysret_check
 #endif /* CONFIG_AUDITSYSCALL */
index fe86493f3ed1cc37912290e7f5461a2471785fc7..ac0417be9131a8d59cd834a61b629dd36ddec5b5 100644 (file)
@@ -311,13 +311,33 @@ out:
        return state;
 }
 
+/*
+ * AMD microcode firmware naming convention, up to family 15h they are in
+ * the legacy file:
+ *
+ *    amd-ucode/microcode_amd.bin
+ *
+ * This legacy file is always smaller than 2K in size.
+ *
+ * Starting at family 15h they are in family specific firmware files:
+ *
+ *    amd-ucode/microcode_amd_fam15h.bin
+ *    amd-ucode/microcode_amd_fam16h.bin
+ *    ...
+ *
+ * These might be larger than 2K.
+ */
 static enum ucode_state request_microcode_amd(int cpu, struct device *device)
 {
-       const char *fw_name = "amd-ucode/microcode_amd.bin";
+       char fw_name[36] = "amd-ucode/microcode_amd.bin";
        const struct firmware *fw;
        enum ucode_state ret = UCODE_NFOUND;
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+       if (c->x86 >= 0x15)
+               snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
 
-       if (request_firmware(&fw, fw_name, device)) {
+       if (request_firmware(&fw, (const char *)fw_name, device)) {
                pr_err("failed to load file %s\n", fw_name);
                goto out;
        }
index 485204f58cdaaf7e8306198375a7dce17450b025..c08d1ff12b7c4087dd01ad6f2ba8ea5bcc8ba04a 100644 (file)
@@ -214,6 +214,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 
        task_user_gs(p) = get_user_gs(regs);
 
+       p->fpu_counter = 0;
        p->thread.io_bitmap_ptr = NULL;
        tsk = current;
        err = -ENOMEM;
@@ -299,22 +300,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
                                 *next = &next_p->thread;
        int cpu = smp_processor_id();
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
-       bool preload_fpu;
+       fpu_switch_t fpu;
 
        /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
-       /*
-        * If the task has used fpu the last 5 timeslices, just do a full
-        * restore of the math state immediately to avoid the trap; the
-        * chances of needing FPU soon are obviously high now
-        */
-       preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
-
-       __unlazy_fpu(prev_p);
-
-       /* we're going to use this soon, after a few expensive things */
-       if (preload_fpu)
-               prefetch(next->fpu.state);
+       fpu = switch_fpu_prepare(prev_p, next_p, cpu);
 
        /*
         * Reload esp0.
@@ -354,11 +344,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
                     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
                __switch_to_xtra(prev_p, next_p, tss);
 
-       /* If we're going to preload the fpu context, make sure clts
-          is run while we're batching the cpu state updates. */
-       if (preload_fpu)
-               clts();
-
        /*
         * Leave lazy mode, flushing any hypercalls made here.
         * This must be done before restoring TLS segments so
@@ -368,15 +353,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
         */
        arch_end_context_switch(next_p);
 
-       if (preload_fpu)
-               __math_state_restore();
-
        /*
         * Restore %gs if needed (which is common)
         */
        if (prev->gs | next->gs)
                lazy_load_gs(next->gs);
 
+       switch_fpu_finish(next_p, fpu);
+
        percpu_write(current_task, next_p);
 
        return prev_p;
index 9b9fe4a85c87fcebcd370c1e4a33d235f67140ec..cfa5c90c01dbe0c170587ae8891a1fa419aa2e36 100644 (file)
@@ -286,6 +286,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 
        set_tsk_thread_flag(p, TIF_FORK);
 
+       p->fpu_counter = 0;
        p->thread.io_bitmap_ptr = NULL;
 
        savesegment(gs, p->thread.gsindex);
@@ -386,18 +387,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        int cpu = smp_processor_id();
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
        unsigned fsindex, gsindex;
-       bool preload_fpu;
+       fpu_switch_t fpu;
 
-       /*
-        * If the task has used fpu the last 5 timeslices, just do a full
-        * restore of the math state immediately to avoid the trap; the
-        * chances of needing FPU soon are obviously high now
-        */
-       preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
-
-       /* we're going to use this soon, after a few expensive things */
-       if (preload_fpu)
-               prefetch(next->fpu.state);
+       fpu = switch_fpu_prepare(prev_p, next_p, cpu);
 
        /*
         * Reload esp0, LDT and the page table pointer:
@@ -427,13 +419,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 
        load_TLS(next, cpu);
 
-       /* Must be after DS reload */
-       __unlazy_fpu(prev_p);
-
-       /* Make sure cpu is ready for new context */
-       if (preload_fpu)
-               clts();
-
        /*
         * Leave lazy mode, flushing any hypercalls made here.
         * This must be done before restoring TLS segments so
@@ -474,6 +459,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
                wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
        prev->gsindex = gsindex;
 
+       switch_fpu_finish(next_p, fpu);
+
        /*
         * Switch the PDA and FPU contexts.
         */
@@ -492,13 +479,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
                     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
                __switch_to_xtra(prev_p, next_p, tss);
 
-       /*
-        * Preload the FPU context, now that we've determined that the
-        * task is likely to be using it. 
-        */
-       if (preload_fpu)
-               __math_state_restore();
-
        return prev_p;
 }
 
index 89a04c7b5bb6f600ff764bf3c91900880e47db4e..50267386b7668d7761f14b2e98a6a032815a792f 100644 (file)
@@ -1392,20 +1392,18 @@ long syscall_trace_enter(struct pt_regs *regs)
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->orig_ax);
 
-       if (unlikely(current->audit_context)) {
-               if (IS_IA32)
-                       audit_syscall_entry(AUDIT_ARCH_I386,
-                                           regs->orig_ax,
-                                           regs->bx, regs->cx,
-                                           regs->dx, regs->si);
+       if (IS_IA32)
+               audit_syscall_entry(AUDIT_ARCH_I386,
+                                   regs->orig_ax,
+                                   regs->bx, regs->cx,
+                                   regs->dx, regs->si);
 #ifdef CONFIG_X86_64
-               else
-                       audit_syscall_entry(AUDIT_ARCH_X86_64,
-                                           regs->orig_ax,
-                                           regs->di, regs->si,
-                                           regs->dx, regs->r10);
+       else
+               audit_syscall_entry(AUDIT_ARCH_X86_64,
+                                   regs->orig_ax,
+                                   regs->di, regs->si,
+                                   regs->dx, regs->r10);
 #endif
-       }
 
        return ret ?: regs->orig_ax;
 }
@@ -1414,8 +1412,7 @@ void syscall_trace_leave(struct pt_regs *regs)
 {
        bool step;
 
-       if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
+       audit_syscall_exit(regs);
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_exit(regs, regs->ax);
index 37a458b521a6020598b69305c782a0f28bd75b27..d840e69a853c0ed3fb48d1bd9f6abc2367275efa 100644 (file)
@@ -39,6 +39,14 @@ static int reboot_mode;
 enum reboot_type reboot_type = BOOT_ACPI;
 int reboot_force;
 
+/* This variable is used privately to keep track of whether or not
+ * reboot_type is still set to its default value (i.e., reboot= hasn't
+ * been set on the command line).  This is needed so that we can
+ * suppress DMI scanning for reboot quirks.  Without it, it's
+ * impossible to override a faulty reboot quirk without recompiling.
+ */
+static int reboot_default = 1;
+
 #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
 static int reboot_cpu = -1;
 #endif
@@ -67,6 +75,12 @@ bool port_cf9_safe = false;
 static int __init reboot_setup(char *str)
 {
        for (;;) {
+               /* Having anything passed on the command line via
+                * reboot= will cause us to disable DMI checking
+                * below.
+                */
+               reboot_default = 0;
+
                switch (*str) {
                case 'w':
                        reboot_mode = 0x1234;
@@ -295,14 +309,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
                },
        },
-       {       /* Handle problems with rebooting on VersaLogic Menlow boards */
-               .callback = set_bios_reboot,
-               .ident = "VersaLogic Menlow based board",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
-                       DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
-               },
-       },
        { /* Handle reboot issue on Acer Aspire one */
                .callback = set_kbd_reboot,
                .ident = "Acer Aspire One A110",
@@ -316,7 +322,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
 
 static int __init reboot_init(void)
 {
-       dmi_check_system(reboot_dmi_table);
+       /* Only do the DMI check if reboot_type hasn't been overridden
+        * on the command line
+        */
+       if (reboot_default) {
+               dmi_check_system(reboot_dmi_table);
+       }
        return 0;
 }
 core_initcall(reboot_init);
@@ -465,7 +476,12 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
 
 static int __init pci_reboot_init(void)
 {
-       dmi_check_system(pci_reboot_dmi_table);
+       /* Only do the DMI check if reboot_type hasn't been overridden
+        * on the command line
+        */
+       if (reboot_default) {
+               dmi_check_system(pci_reboot_dmi_table);
+       }
        return 0;
 }
 core_initcall(pci_reboot_init);
index 482ec3af20671cb771b7b6c166f364144f2dcf64..4bbe04d967441196c3c0a3f3390f9e6826f156a0 100644 (file)
@@ -570,28 +570,6 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
 {
 }
 
-/*
- * __math_state_restore assumes that cr0.TS is already clear and the
- * fpu state is all ready for use.  Used during context switch.
- */
-void __math_state_restore(void)
-{
-       struct thread_info *thread = current_thread_info();
-       struct task_struct *tsk = thread->task;
-
-       /*
-        * Paranoid restore. send a SIGSEGV if we fail to restore the state.
-        */
-       if (unlikely(restore_fpu_checking(tsk))) {
-               stts();
-               force_sig(SIGSEGV, tsk);
-               return;
-       }
-
-       thread->status |= TS_USEDFPU;   /* So we fnsave on switch_to() */
-       tsk->fpu_counter++;
-}
-
 /*
  * 'math_state_restore()' saves the current math information in the
  * old math state array, and gets the new ones from the current task
@@ -599,13 +577,12 @@ void __math_state_restore(void)
  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
  * Don't touch unless you *really* know how it works.
  *
- * Must be called with kernel preemption disabled (in this case,
- * local interrupts are disabled at the call-site in entry.S).
+ * Must be called with kernel preemption disabled (eg with local
+ * local interrupts as in the case of do_device_not_available).
  */
-asmlinkage void math_state_restore(void)
+void math_state_restore(void)
 {
-       struct thread_info *thread = current_thread_info();
-       struct task_struct *tsk = thread->task;
+       struct task_struct *tsk = current;
 
        if (!tsk_used_math(tsk)) {
                local_irq_enable();
@@ -622,9 +599,17 @@ asmlinkage void math_state_restore(void)
                local_irq_disable();
        }
 
-       clts();                         /* Allow maths ops (or we recurse) */
+       __thread_fpu_begin(tsk);
+       /*
+        * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+        */
+       if (unlikely(restore_fpu_checking(tsk))) {
+               __thread_fpu_end(tsk);
+               force_sig(SIGSEGV, tsk);
+               return;
+       }
 
-       __math_state_restore();
+       tsk->fpu_counter++;
 }
 EXPORT_SYMBOL_GPL(math_state_restore);
 
index c0dd5b603749057db73420caacc321d5d714338f..a62c201c97eccf31fa90d05dec5e5cf5102ead74 100644 (file)
@@ -290,14 +290,15 @@ static inline int pit_verify_msb(unsigned char val)
 static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
 {
        int count;
-       u64 tsc = 0;
+       u64 tsc = 0, prev_tsc = 0;
 
        for (count = 0; count < 50000; count++) {
                if (!pit_verify_msb(val))
                        break;
+               prev_tsc = tsc;
                tsc = get_cycles();
        }
-       *deltap = get_cycles() - tsc;
+       *deltap = get_cycles() - prev_tsc;
        *tscp = tsc;
 
        /*
@@ -311,9 +312,9 @@ static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *de
  * How many MSB values do we want to see? We aim for
  * a maximum error rate of 500ppm (in practice the
  * real error is much smaller), but refuse to spend
- * more than 25ms on it.
+ * more than 50ms on it.
  */
-#define MAX_QUICK_PIT_MS 25
+#define MAX_QUICK_PIT_MS 50
 #define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
 
 static unsigned long quick_pit_calibrate(void)
@@ -383,15 +384,12 @@ success:
         *
         * As a result, we can depend on there not being
         * any odd delays anywhere, and the TSC reads are
-        * reliable (within the error). We also adjust the
-        * delta to the middle of the error bars, just
-        * because it looks nicer.
+        * reliable (within the error).
         *
         * kHz = ticks / time-in-seconds / 1000;
         * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000
         * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000)
         */
-       delta += (long)(d2 - d1)/2;
        delta *= PIT_TICK_RATE;
        do_div(delta, i*256*1000);
        printk("Fast TSC calibration using PIT\n");
index 863f8753ab0ae696f8981ef30d9ee031dd0e310b..b466cab5ba15d171cb4b1fd61a1590bd0cca9956 100644 (file)
@@ -335,9 +335,11 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        if (info->flags & VM86_SCREEN_BITMAP)
                mark_screen_rdonly(tsk->mm);
 
-       /*call audit_syscall_exit since we do not exit via the normal paths */
+       /*call __audit_syscall_exit since we do not exit via the normal paths */
+#ifdef CONFIG_AUDITSYSCALL
        if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(0), 0);
+               __audit_syscall_exit(1, 0);
+#endif
 
        __asm__ __volatile__(
                "movl %0,%%esp\n\t"
index a3911343976b8ae50040228b7993d5d90773002f..711091114119532a1c9d2dff819da9c41e8a39b9 100644 (file)
@@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_struct *tsk)
        if (!fx)
                return;
 
-       BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU);
+       BUG_ON(__thread_has_fpu(tsk));
 
        xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
 
@@ -168,7 +168,7 @@ int save_i387_xstate(void __user *buf)
        if (!used_math())
                return 0;
 
-       if (task_thread_info(tsk)->status & TS_USEDFPU) {
+       if (user_has_fpu()) {
                if (use_xsave())
                        err = xsave_user(buf);
                else
@@ -176,8 +176,7 @@ int save_i387_xstate(void __user *buf)
 
                if (err)
                        return err;
-               task_thread_info(tsk)->status &= ~TS_USEDFPU;
-               stts();
+               user_fpu_end();
        } else {
                sanitize_i387_state(tsk);
                if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
@@ -292,10 +291,7 @@ int restore_i387_xstate(void __user *buf)
                        return err;
        }
 
-       if (!(task_thread_info(current)->status & TS_USEDFPU)) {
-               clts();
-               task_thread_info(current)->status |= TS_USEDFPU;
-       }
+       user_fpu_begin();
        if (use_xsave())
                err = restore_user_xstate(buf);
        else
index 05a562b850252b3c480ce67dd4e1e4c6c47f6055..0982507b962a736f3e643d454d4b38c2b1cd1c29 100644 (file)
@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
        ss->p = 1;
 }
 
+static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
+{
+       struct x86_emulate_ops *ops = ctxt->ops;
+       u32 eax, ebx, ecx, edx;
+
+       /*
+        * syscall should always be enabled in longmode - so only become
+        * vendor specific (cpuid) if other modes are active...
+        */
+       if (ctxt->mode == X86EMUL_MODE_PROT64)
+               return true;
+
+       eax = 0x00000000;
+       ecx = 0x00000000;
+       if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
+               /*
+                * Intel ("GenuineIntel")
+                * remark: Intel CPUs only support "syscall" in 64bit
+                * longmode. Also an 64bit guest with a
+                * 32bit compat-app running will #UD !! While this
+                * behaviour can be fixed (by emulating) into AMD
+                * response - CPUs of AMD can't behave like Intel.
+                */
+               if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
+                   ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
+                   edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
+                       return false;
+
+               /* AMD ("AuthenticAMD") */
+               if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
+                   ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
+                   edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
+                       return true;
+
+               /* AMD ("AMDisbetter!") */
+               if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
+                   ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
+                   edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
+                       return true;
+       }
+
+       /* default: (not Intel, not AMD), apply Intel's stricter rules... */
+       return false;
+}
+
 static int em_syscall(struct x86_emulate_ctxt *ctxt)
 {
        struct x86_emulate_ops *ops = ctxt->ops;
@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
            ctxt->mode == X86EMUL_MODE_VM86)
                return emulate_ud(ctxt);
 
+       if (!(em_syscall_is_enabled(ctxt)))
+               return emulate_ud(ctxt);
+
        ops->get_msr(ctxt, MSR_EFER, &efer);
        setup_syscalls_segments(ctxt, &cs, &ss);
 
+       if (!(efer & EFER_SCE))
+               return emulate_ud(ctxt);
+
        ops->get_msr(ctxt, MSR_STAR, &msr_data);
        msr_data >>= 32;
        cs_sel = (u16)(msr_data & 0xfffc);
index d29216c462b3ce56e33c3bf0ecf7595258b9705a..3b4c8d8ad906917070e2ef730090903860f49276 100644 (file)
@@ -1457,7 +1457,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 #ifdef CONFIG_X86_64
        wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
 #endif
-       if (current_thread_info()->status & TS_USEDFPU)
+       if (__thread_has_fpu(current))
                clts();
        load_gdt(&__get_cpu_var(host_gdt));
 }
index 14d6cadc4ba63b9ba3adf5b5e64fff461483de69..9cbfc06981186d96c42d3383122310018fea0d7d 100644 (file)
@@ -1495,6 +1495,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
 
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
+       bool pr = false;
+
        switch (msr) {
        case MSR_EFER:
                return set_efer(vcpu, data);
@@ -1635,6 +1637,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                pr_unimpl(vcpu, "unimplemented perfctr wrmsr: "
                        "0x%x data 0x%llx\n", msr, data);
                break;
+       case MSR_P6_PERFCTR0:
+       case MSR_P6_PERFCTR1:
+               pr = true;
+       case MSR_P6_EVNTSEL0:
+       case MSR_P6_EVNTSEL1:
+               if (kvm_pmu_msr(vcpu, msr))
+                       return kvm_pmu_set_msr(vcpu, msr, data);
+
+               if (pr || data != 0)
+                       pr_unimpl(vcpu, "disabled perfctr wrmsr: "
+                               "0x%x data 0x%llx\n", msr, data);
+               break;
        case MSR_K7_CLK_CTL:
                /*
                 * Ignore all writes to this no longer documented MSR.
@@ -1835,6 +1849,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_FAM10H_MMIO_CONF_BASE:
                data = 0;
                break;
+       case MSR_P6_PERFCTR0:
+       case MSR_P6_PERFCTR1:
+       case MSR_P6_EVNTSEL0:
+       case MSR_P6_EVNTSEL1:
+               if (kvm_pmu_msr(vcpu, msr))
+                       return kvm_pmu_get_msr(vcpu, msr, pdata);
+               data = 0;
+               break;
        case MSR_IA32_UCODE_REV:
                data = 0x100000000ULL;
                break;
@@ -4180,6 +4202,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
        return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
 }
 
+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+                              u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+{
+       struct kvm_cpuid_entry2 *cpuid = NULL;
+
+       if (eax && ecx)
+               cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
+                                           *eax, *ecx);
+
+       if (cpuid) {
+               *eax = cpuid->eax;
+               *ecx = cpuid->ecx;
+               if (ebx)
+                       *ebx = cpuid->ebx;
+               if (edx)
+                       *edx = cpuid->edx;
+               return true;
+       }
+
+       return false;
+}
+
 static struct x86_emulate_ops emulate_ops = {
        .read_std            = kvm_read_guest_virt_system,
        .write_std           = kvm_write_guest_virt_system,
@@ -4211,6 +4255,7 @@ static struct x86_emulate_ops emulate_ops = {
        .get_fpu             = emulator_get_fpu,
        .put_fpu             = emulator_put_fpu,
        .intercept           = emulator_intercept,
+       .get_cpuid           = emulator_get_cpuid,
 };
 
 static void cache_all_regs(struct kvm_vcpu *vcpu)
index 5b83c51c12e02e8146aba31c0236ff1e7d42d4b0..819137904428a4f82444cf5a9d5055bb59dc6d80 100644 (file)
@@ -219,7 +219,9 @@ ab: STOS/W/D/Q Yv,rAX
 ac: LODS/B AL,Xb
 ad: LODS/W/D/Q rAX,Xv
 ae: SCAS/B AL,Yb
-af: SCAS/W/D/Q rAX,Xv
+# Note: The May 2011 Intel manual shows Xv for the second parameter of the
+# next instruction but Yv is correct
+af: SCAS/W/D/Q rAX,Yv
 # 0xb0 - 0xbf
 b0: MOV AL/R8L,Ib
 b1: MOV CL/R9L,Ib
@@ -729,8 +731,8 @@ de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
 df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
 f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2)
 f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2)
-f3: ANDN Gy,By,Ey (v)
-f4: Grp17 (1A)
+f2: ANDN Gy,By,Ey (v)
+f3: Grp17 (1A)
 f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
 f6: MULX By,Gy,rDX,Ey (F2),(v)
 f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
index 9d74824a708dcdd1cd3b0e6ce4798e79fbbf1c01..f0b4caf85c1a8687496b863745f11838a4d430b8 100644 (file)
@@ -673,7 +673,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
        stackend = end_of_stack(tsk);
        if (tsk != &init_task && *stackend != STACK_END_MAGIC)
-               printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+               printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
 
        tsk->thread.cr2         = address;
        tsk->thread.trap_no     = 14;
@@ -684,7 +684,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
                sig = 0;
 
        /* Executive summary in case the body of the oops scrolled away */
-       printk(KERN_EMERG "CR2: %016lx\n", address);
+       printk(KERN_DEFAULT "CR2: %016lx\n", address);
 
        oops_end(flags, regs, sig);
 }
index fd61b3fb73411f89b5a5d1b2805e133bcbd8be94..1c1c4f46a7c15c19c54923c815556d8c253b847c 100644 (file)
@@ -109,6 +109,8 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
        if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
                return;
        pxm = pa->proximity_domain_lo;
+       if (acpi_srat_revision >= 2)
+               pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8;
        node = setup_node(pxm);
        if (node < 0) {
                printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
@@ -160,6 +162,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
        start = ma->base_address;
        end = start + ma->length;
        pxm = ma->proximity_domain;
+       if (acpi_srat_revision <= 1)
+               pxm &= 0xff;
        node = setup_node(pxm);
        if (node < 0) {
                printk(KERN_ERR "SRAT: Too many proximity domains.\n");
index 7b65f752c5f8fd79af2c6b4afb342988bdd8d56c..7c1b765ecc59e3324299dfe34ba04d127fed4878 100644 (file)
@@ -151,17 +151,18 @@ void bpf_jit_compile(struct sk_filter *fp)
        cleanup_addr = proglen; /* epilogue address */
 
        for (pass = 0; pass < 10; pass++) {
+               u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
                /* no prologue/epilogue for trivial filters (RET something) */
                proglen = 0;
                prog = temp;
 
-               if (seen) {
+               if (seen_or_pass0) {
                        EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */
                        EMIT4(0x48, 0x83, 0xec, 96);    /* subq  $96,%rsp       */
                        /* note : must save %rbx in case bpf_error is hit */
-                       if (seen & (SEEN_XREG | SEEN_DATAREF))
+                       if (seen_or_pass0 & (SEEN_XREG | SEEN_DATAREF))
                                EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */
-                       if (seen & SEEN_XREG)
+                       if (seen_or_pass0 & SEEN_XREG)
                                CLEAR_X(); /* make sure we dont leek kernel memory */
 
                        /*
@@ -170,7 +171,7 @@ void bpf_jit_compile(struct sk_filter *fp)
                         *  r9 = skb->len - skb->data_len
                         *  r8 = skb->data
                         */
-                       if (seen & SEEN_DATAREF) {
+                       if (seen_or_pass0 & SEEN_DATAREF) {
                                if (offsetof(struct sk_buff, len) <= 127)
                                        /* mov    off8(%rdi),%r9d */
                                        EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len));
@@ -260,9 +261,14 @@ void bpf_jit_compile(struct sk_filter *fp)
                        case BPF_S_ALU_DIV_X: /* A /= X; */
                                seen |= SEEN_XREG;
                                EMIT2(0x85, 0xdb);      /* test %ebx,%ebx */
-                               if (pc_ret0 != -1)
-                                       EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4));
-                               else {
+                               if (pc_ret0 > 0) {
+                                       /* addrs[pc_ret0 - 1] is start address of target
+                                        * (addrs[i] - 4) is the address following this jmp
+                                        * ("xor %edx,%edx; div %ebx" being 4 bytes long)
+                                        */
+                                       EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] -
+                                                               (addrs[i] - 4));
+                               } else {
                                        EMIT_COND_JMP(X86_JNE, 2 + 5);
                                        CLEAR_A();
                                        EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */
@@ -335,12 +341,12 @@ void bpf_jit_compile(struct sk_filter *fp)
                                }
                                /* fallinto */
                        case BPF_S_RET_A:
-                               if (seen) {
+                               if (seen_or_pass0) {
                                        if (i != flen - 1) {
                                                EMIT_JMP(cleanup_addr - addrs[i]);
                                                break;
                                        }
-                                       if (seen & SEEN_XREG)
+                                       if (seen_or_pass0 & SEEN_XREG)
                                                EMIT4(0x48, 0x8b, 0x5d, 0xf8);  /* mov  -8(%rbp),%rbx */
                                        EMIT1(0xc9);            /* leaveq */
                                }
@@ -483,8 +489,9 @@ common_load:                        seen |= SEEN_DATAREF;
                                goto common_load;
                        case BPF_S_LDX_B_MSH:
                                if ((int)K < 0) {
-                                       if (pc_ret0 != -1) {
-                                               EMIT_JMP(addrs[pc_ret0] - addrs[i]);
+                                       if (pc_ret0 > 0) {
+                                               /* addrs[pc_ret0 - 1] is the start address */
+                                               EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]);
                                                break;
                                        }
                                        CLEAR_A();
@@ -599,13 +606,14 @@ cond_branch:                      f_offset = addrs[i + filter[i].jf] - addrs[i];
                 * use it to give the cleanup instruction(s) addr
                 */
                cleanup_addr = proglen - 1; /* ret */
-               if (seen)
+               if (seen_or_pass0)
                        cleanup_addr -= 1; /* leaveq */
-               if (seen & SEEN_XREG)
+               if (seen_or_pass0 & SEEN_XREG)
                        cleanup_addr -= 4; /* mov  -8(%rbp),%rbx */
 
                if (image) {
-                       WARN_ON(proglen != oldproglen);
+                       if (proglen != oldproglen)
+                               pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n", proglen, oldproglen);
                        break;
                }
                if (proglen == oldproglen) {
index 492ade8c978e3c632003b62e4f31ae10d36b062b..d99346ea8fdb4317b74fded709c6bd971b3a066c 100644 (file)
@@ -374,7 +374,7 @@ int __init pci_xen_init(void)
 
 int __init pci_xen_hvm_init(void)
 {
-       if (!xen_feature(XENFEAT_hvm_pirqs))
+       if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs))
                return 0;
 
 #ifdef CONFIG_ACPI
index 5b552198f774eb1e6c6ab3b9ef42276706d74328..3ae0e61abd23acf7b1de580b8c234873b1870209 100644 (file)
@@ -157,13 +157,14 @@ static int __init uvhub_to_first_apicid(int uvhub)
  * clear of the Timeout bit (as well) will free the resource. No reply will
  * be sent (the hardware will only do one reply per message).
  */
-static void reply_to_message(struct msg_desc *mdp, struct bau_control *bcp)
+static void reply_to_message(struct msg_desc *mdp, struct bau_control *bcp,
+                                               int do_acknowledge)
 {
        unsigned long dw;
        struct bau_pq_entry *msg;
 
        msg = mdp->msg;
-       if (!msg->canceled) {
+       if (!msg->canceled && do_acknowledge) {
                dw = (msg->swack_vec << UV_SW_ACK_NPENDING) | msg->swack_vec;
                write_mmr_sw_ack(dw);
        }
@@ -212,8 +213,8 @@ static void bau_process_retry_msg(struct msg_desc *mdp,
                        if (mmr & (msg_res << UV_SW_ACK_NPENDING)) {
                                unsigned long mr;
                                /*
-                                * is the resource timed out?
-                                * make everyone ignore the cancelled message.
+                                * Is the resource timed out?
+                                * Make everyone ignore the cancelled message.
                                 */
                                msg2->canceled = 1;
                                stat->d_canceled++;
@@ -231,8 +232,8 @@ static void bau_process_retry_msg(struct msg_desc *mdp,
  * Do all the things a cpu should do for a TLB shootdown message.
  * Other cpu's may come here at the same time for this message.
  */
-static void bau_process_message(struct msg_desc *mdp,
-                                       struct bau_control *bcp)
+static void bau_process_message(struct msg_desc *mdp, struct bau_control *bcp,
+                                               int do_acknowledge)
 {
        short socket_ack_count = 0;
        short *sp;
@@ -284,8 +285,9 @@ static void bau_process_message(struct msg_desc *mdp,
                if (msg_ack_count == bcp->cpus_in_uvhub) {
                        /*
                         * All cpus in uvhub saw it; reply
+                        * (unless we are in the UV2 workaround)
                         */
-                       reply_to_message(mdp, bcp);
+                       reply_to_message(mdp, bcp, do_acknowledge);
                }
        }
 
@@ -491,27 +493,138 @@ static int uv1_wait_completion(struct bau_desc *bau_desc,
 /*
  * UV2 has an extra bit of status in the ACTIVATION_STATUS_2 register.
  */
-static unsigned long uv2_read_status(unsigned long offset, int rshft, int cpu)
+static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc)
 {
        unsigned long descriptor_status;
        unsigned long descriptor_status2;
 
        descriptor_status = ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK);
-       descriptor_status2 = (read_mmr_uv2_status() >> cpu) & 0x1UL;
+       descriptor_status2 = (read_mmr_uv2_status() >> desc) & 0x1UL;
        descriptor_status = (descriptor_status << 1) | descriptor_status2;
        return descriptor_status;
 }
 
+/*
+ * Return whether the status of the descriptor that is normally used for this
+ * cpu (the one indexed by its hub-relative cpu number) is busy.
+ * The status of the original 32 descriptors is always reflected in the 64
+ * bits of UVH_LB_BAU_SB_ACTIVATION_STATUS_0.
+ * The bit provided by the activation_status_2 register is irrelevant to
+ * the status if it is only being tested for busy or not busy.
+ */
+int normal_busy(struct bau_control *bcp)
+{
+       int cpu = bcp->uvhub_cpu;
+       int mmr_offset;
+       int right_shift;
+
+       mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0;
+       right_shift = cpu * UV_ACT_STATUS_SIZE;
+       return (((((read_lmmr(mmr_offset) >> right_shift) &
+                               UV_ACT_STATUS_MASK)) << 1) == UV2H_DESC_BUSY);
+}
+
+/*
+ * Entered when a bau descriptor has gone into a permanent busy wait because
+ * of a hardware bug.
+ * Workaround the bug.
+ */
+int handle_uv2_busy(struct bau_control *bcp)
+{
+       int busy_one = bcp->using_desc;
+       int normal = bcp->uvhub_cpu;
+       int selected = -1;
+       int i;
+       unsigned long descriptor_status;
+       unsigned long status;
+       int mmr_offset;
+       struct bau_desc *bau_desc_old;
+       struct bau_desc *bau_desc_new;
+       struct bau_control *hmaster = bcp->uvhub_master;
+       struct ptc_stats *stat = bcp->statp;
+       cycles_t ttm;
+
+       stat->s_uv2_wars++;
+       spin_lock(&hmaster->uvhub_lock);
+       /* try for the original first */
+       if (busy_one != normal) {
+               if (!normal_busy(bcp))
+                       selected = normal;
+       }
+       if (selected < 0) {
+               /* can't use the normal, select an alternate */
+               mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1;
+               descriptor_status = read_lmmr(mmr_offset);
+
+               /* scan available descriptors 32-63 */
+               for (i = 0; i < UV_CPUS_PER_AS; i++) {
+                       if ((hmaster->inuse_map & (1 << i)) == 0) {
+                               status = ((descriptor_status >>
+                                               (i * UV_ACT_STATUS_SIZE)) &
+                                               UV_ACT_STATUS_MASK) << 1;
+                               if (status != UV2H_DESC_BUSY) {
+                                       selected = i + UV_CPUS_PER_AS;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (busy_one != normal)
+               /* mark the busy alternate as not in-use */
+               hmaster->inuse_map &= ~(1 << (busy_one - UV_CPUS_PER_AS));
+
+       if (selected >= 0) {
+               /* switch to the selected descriptor */
+               if (selected != normal) {
+                       /* set the selected alternate as in-use */
+                       hmaster->inuse_map |=
+                                       (1 << (selected - UV_CPUS_PER_AS));
+                       if (selected > stat->s_uv2_wars_hw)
+                               stat->s_uv2_wars_hw = selected;
+               }
+               bau_desc_old = bcp->descriptor_base;
+               bau_desc_old += (ITEMS_PER_DESC * busy_one);
+               bcp->using_desc = selected;
+               bau_desc_new = bcp->descriptor_base;
+               bau_desc_new += (ITEMS_PER_DESC * selected);
+               *bau_desc_new = *bau_desc_old;
+       } else {
+               /*
+                * All are busy. Wait for the normal one for this cpu to
+                * free up.
+                */
+               stat->s_uv2_war_waits++;
+               spin_unlock(&hmaster->uvhub_lock);
+               ttm = get_cycles();
+               do {
+                       cpu_relax();
+               } while (normal_busy(bcp));
+               spin_lock(&hmaster->uvhub_lock);
+               /* switch to the original descriptor */
+               bcp->using_desc = normal;
+               bau_desc_old = bcp->descriptor_base;
+               bau_desc_old += (ITEMS_PER_DESC * bcp->using_desc);
+               bcp->using_desc = (ITEMS_PER_DESC * normal);
+               bau_desc_new = bcp->descriptor_base;
+               bau_desc_new += (ITEMS_PER_DESC * normal);
+               *bau_desc_new = *bau_desc_old; /* copy the entire descriptor */
+       }
+       spin_unlock(&hmaster->uvhub_lock);
+       return FLUSH_RETRY_BUSYBUG;
+}
+
 static int uv2_wait_completion(struct bau_desc *bau_desc,
                                unsigned long mmr_offset, int right_shift,
                                struct bau_control *bcp, long try)
 {
        unsigned long descriptor_stat;
        cycles_t ttm;
-       int cpu = bcp->uvhub_cpu;
+       int desc = bcp->using_desc;
+       long busy_reps = 0;
        struct ptc_stats *stat = bcp->statp;
 
-       descriptor_stat = uv2_read_status(mmr_offset, right_shift, cpu);
+       descriptor_stat = uv2_read_status(mmr_offset, right_shift, desc);
 
        /* spin on the status MMR, waiting for it to go idle */
        while (descriptor_stat != UV2H_DESC_IDLE) {
@@ -522,32 +635,35 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
                 * our message and its state will stay IDLE.
                 */
                if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT) ||
-                   (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) ||
                    (descriptor_stat == UV2H_DESC_DEST_PUT_ERR)) {
                        stat->s_stimeout++;
                        return FLUSH_GIVEUP;
+               } else if (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) {
+                       stat->s_strongnacks++;
+                       bcp->conseccompletes = 0;
+                       return FLUSH_GIVEUP;
                } else if (descriptor_stat == UV2H_DESC_DEST_TIMEOUT) {
                        stat->s_dtimeout++;
-                       ttm = get_cycles();
-                       /*
-                        * Our retries may be blocked by all destination
-                        * swack resources being consumed, and a timeout
-                        * pending.  In that case hardware returns the
-                        * ERROR that looks like a destination timeout.
-                        */
-                       if (cycles_2_us(ttm - bcp->send_message) < timeout_us) {
-                               bcp->conseccompletes = 0;
-                               return FLUSH_RETRY_PLUGGED;
-                       }
                        bcp->conseccompletes = 0;
                        return FLUSH_RETRY_TIMEOUT;
                } else {
+                       busy_reps++;
+                       if (busy_reps > 1000000) {
+                               /* not to hammer on the clock */
+                               busy_reps = 0;
+                               ttm = get_cycles();
+                               if ((ttm - bcp->send_message) >
+                                       (bcp->clocks_per_100_usec)) {
+                                       return handle_uv2_busy(bcp);
+                               }
+                       }
                        /*
                         * descriptor_stat is still BUSY
                         */
                        cpu_relax();
                }
-               descriptor_stat = uv2_read_status(mmr_offset, right_shift, cpu);
+               descriptor_stat = uv2_read_status(mmr_offset, right_shift,
+                                                                       desc);
        }
        bcp->conseccompletes++;
        return FLUSH_COMPLETE;
@@ -563,17 +679,17 @@ static int wait_completion(struct bau_desc *bau_desc,
 {
        int right_shift;
        unsigned long mmr_offset;
-       int cpu = bcp->uvhub_cpu;
+       int desc = bcp->using_desc;
 
-       if (cpu < UV_CPUS_PER_AS) {
+       if (desc < UV_CPUS_PER_AS) {
                mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0;
-               right_shift = cpu * UV_ACT_STATUS_SIZE;
+               right_shift = desc * UV_ACT_STATUS_SIZE;
        } else {
                mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1;
-               right_shift = ((cpu - UV_CPUS_PER_AS) * UV_ACT_STATUS_SIZE);
+               right_shift = ((desc - UV_CPUS_PER_AS) * UV_ACT_STATUS_SIZE);
        }
 
-       if (is_uv1_hub())
+       if (bcp->uvhub_version == 1)
                return uv1_wait_completion(bau_desc, mmr_offset, right_shift,
                                                                bcp, try);
        else
@@ -752,19 +868,22 @@ static void handle_cmplt(int completion_status, struct bau_desc *bau_desc,
  * Returns 1 if it gives up entirely and the original cpu mask is to be
  * returned to the kernel.
  */
-int uv_flush_send_and_wait(struct bau_desc *bau_desc,
-                       struct cpumask *flush_mask, struct bau_control *bcp)
+int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
 {
        int seq_number = 0;
        int completion_stat = 0;
+       int uv1 = 0;
        long try = 0;
        unsigned long index;
        cycles_t time1;
        cycles_t time2;
        struct ptc_stats *stat = bcp->statp;
        struct bau_control *hmaster = bcp->uvhub_master;
+       struct uv1_bau_msg_header *uv1_hdr = NULL;
+       struct uv2_bau_msg_header *uv2_hdr = NULL;
+       struct bau_desc *bau_desc;
 
-       if (is_uv1_hub())
+       if (bcp->uvhub_version == 1)
                uv1_throttle(hmaster, stat);
 
        while (hmaster->uvhub_quiesce)
@@ -772,22 +891,39 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc,
 
        time1 = get_cycles();
        do {
-               if (try == 0) {
-                       bau_desc->header.msg_type = MSG_REGULAR;
+               bau_desc = bcp->descriptor_base;
+               bau_desc += (ITEMS_PER_DESC * bcp->using_desc);
+               if (bcp->uvhub_version == 1) {
+                       uv1 = 1;
+                       uv1_hdr = &bau_desc->header.uv1_hdr;
+               } else
+                       uv2_hdr = &bau_desc->header.uv2_hdr;
+               if ((try == 0) || (completion_stat == FLUSH_RETRY_BUSYBUG)) {
+                       if (uv1)
+                               uv1_hdr->msg_type = MSG_REGULAR;
+                       else
+                               uv2_hdr->msg_type = MSG_REGULAR;
                        seq_number = bcp->message_number++;
                } else {
-                       bau_desc->header.msg_type = MSG_RETRY;
+                       if (uv1)
+                               uv1_hdr->msg_type = MSG_RETRY;
+                       else
+                               uv2_hdr->msg_type = MSG_RETRY;
                        stat->s_retry_messages++;
                }
 
-               bau_desc->header.sequence = seq_number;
-               index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu;
+               if (uv1)
+                       uv1_hdr->sequence = seq_number;
+               else
+                       uv2_hdr->sequence = seq_number;
+               index = (1UL << AS_PUSH_SHIFT) | bcp->using_desc;
                bcp->send_message = get_cycles();
 
                write_mmr_activation(index);
 
                try++;
                completion_stat = wait_completion(bau_desc, bcp, try);
+               /* UV2: wait_completion() may change the bcp->using_desc */
 
                handle_cmplt(completion_stat, bau_desc, bcp, hmaster, stat);
 
@@ -798,6 +934,7 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc,
                }
                cpu_relax();
        } while ((completion_stat == FLUSH_RETRY_PLUGGED) ||
+                (completion_stat == FLUSH_RETRY_BUSYBUG) ||
                 (completion_stat == FLUSH_RETRY_TIMEOUT));
 
        time2 = get_cycles();
@@ -812,6 +949,7 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc,
        record_send_stats(time1, time2, bcp, stat, completion_stat, try);
 
        if (completion_stat == FLUSH_GIVEUP)
+               /* FLUSH_GIVEUP will fall back to using IPI's for tlb flush */
                return 1;
        return 0;
 }
@@ -967,7 +1105,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                stat->s_ntargself++;
 
        bau_desc = bcp->descriptor_base;
-       bau_desc += ITEMS_PER_DESC * bcp->uvhub_cpu;
+       bau_desc += (ITEMS_PER_DESC * bcp->using_desc);
        bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
        if (set_distrib_bits(flush_mask, bcp, bau_desc, &locals, &remotes))
                return NULL;
@@ -980,12 +1118,85 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
         * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
         * or 1 if it gave up and the original cpumask should be returned.
         */
-       if (!uv_flush_send_and_wait(bau_desc, flush_mask, bcp))
+       if (!uv_flush_send_and_wait(flush_mask, bcp))
                return NULL;
        else
                return cpumask;
 }
 
+/*
+ * Search the message queue for any 'other' message with the same software
+ * acknowledge resource bit vector.
+ */
+struct bau_pq_entry *find_another_by_swack(struct bau_pq_entry *msg,
+                       struct bau_control *bcp, unsigned char swack_vec)
+{
+       struct bau_pq_entry *msg_next = msg + 1;
+
+       if (msg_next > bcp->queue_last)
+               msg_next = bcp->queue_first;
+       while ((msg_next->swack_vec != 0) && (msg_next != msg)) {
+               if (msg_next->swack_vec == swack_vec)
+                       return msg_next;
+               msg_next++;
+               if (msg_next > bcp->queue_last)
+                       msg_next = bcp->queue_first;
+       }
+       return NULL;
+}
+
+/*
+ * UV2 needs to work around a bug in which an arriving message has not
+ * set a bit in the UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE register.
+ * Such a message must be ignored.
+ */
+void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp)
+{
+       unsigned long mmr_image;
+       unsigned char swack_vec;
+       struct bau_pq_entry *msg = mdp->msg;
+       struct bau_pq_entry *other_msg;
+
+       mmr_image = read_mmr_sw_ack();
+       swack_vec = msg->swack_vec;
+
+       if ((swack_vec & mmr_image) == 0) {
+               /*
+                * This message was assigned a swack resource, but no
+                * reserved acknowlegment is pending.
+                * The bug has prevented this message from setting the MMR.
+                * And no other message has used the same sw_ack resource.
+                * Do the requested shootdown but do not reply to the msg.
+                * (the 0 means make no acknowledge)
+                */
+               bau_process_message(mdp, bcp, 0);
+               return;
+       }
+
+       /*
+        * Some message has set the MMR 'pending' bit; it might have been
+        * another message.  Look for that message.
+        */
+       other_msg = find_another_by_swack(msg, bcp, msg->swack_vec);
+       if (other_msg) {
+               /* There is another.  Do not ack the current one. */
+               bau_process_message(mdp, bcp, 0);
+               /*
+                * Let the natural processing of that message acknowledge
+                * it. Don't get the processing of sw_ack's out of order.
+                */
+               return;
+       }
+
+       /*
+        * There is no other message using this sw_ack, so it is safe to
+        * acknowledge it.
+        */
+       bau_process_message(mdp, bcp, 1);
+
+       return;
+}
+
 /*
  * The BAU message interrupt comes here. (registered by set_intr_gate)
  * See entry_64.S
@@ -1009,6 +1220,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
        struct ptc_stats *stat;
        struct msg_desc msgdesc;
 
+       ack_APIC_irq();
        time_start = get_cycles();
 
        bcp = &per_cpu(bau_control, smp_processor_id());
@@ -1022,9 +1234,11 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
                count++;
 
                msgdesc.msg_slot = msg - msgdesc.queue_first;
-               msgdesc.swack_slot = ffs(msg->swack_vec) - 1;
                msgdesc.msg = msg;
-               bau_process_message(&msgdesc, bcp);
+               if (bcp->uvhub_version == 2)
+                       process_uv2_message(&msgdesc, bcp);
+               else
+                       bau_process_message(&msgdesc, bcp, 1);
 
                msg++;
                if (msg > msgdesc.queue_last)
@@ -1036,8 +1250,6 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
                stat->d_nomsg++;
        else if (count > 1)
                stat->d_multmsg++;
-
-       ack_APIC_irq();
 }
 
 /*
@@ -1083,7 +1295,7 @@ static void __init enable_timeouts(void)
                 */
                mmr_image |= (1L << SOFTACK_MSHIFT);
                if (is_uv2_hub()) {
-                       mmr_image |= (1L << UV2_LEG_SHFT);
+                       mmr_image &= ~(1L << UV2_LEG_SHFT);
                        mmr_image |= (1L << UV2_EXT_SHFT);
                }
                write_mmr_misc_control(pnode, mmr_image);
@@ -1136,13 +1348,13 @@ static int ptc_seq_show(struct seq_file *file, void *data)
                seq_printf(file,
                        "remotehub numuvhubs numuvhubs16 numuvhubs8 ");
                seq_printf(file,
-                       "numuvhubs4 numuvhubs2 numuvhubs1 dto retries rok ");
+                   "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok ");
                seq_printf(file,
                        "resetp resett giveup sto bz throt swack recv rtime ");
                seq_printf(file,
                        "all one mult none retry canc nocan reset rcan ");
                seq_printf(file,
-                       "disable enable\n");
+                       "disable enable wars warshw warwaits\n");
        }
        if (cpu < num_possible_cpus() && cpu_online(cpu)) {
                stat = &per_cpu(ptcstats, cpu);
@@ -1154,10 +1366,10 @@ static int ptc_seq_show(struct seq_file *file, void *data)
                           stat->s_ntargremotes, stat->s_ntargcpu,
                           stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub,
                           stat->s_ntarguvhub, stat->s_ntarguvhub16);
-               seq_printf(file, "%ld %ld %ld %ld %ld ",
+               seq_printf(file, "%ld %ld %ld %ld %ld %ld ",
                           stat->s_ntarguvhub8, stat->s_ntarguvhub4,
                           stat->s_ntarguvhub2, stat->s_ntarguvhub1,
-                          stat->s_dtimeout);
+                          stat->s_dtimeout, stat->s_strongnacks);
                seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ",
                           stat->s_retry_messages, stat->s_retriesok,
                           stat->s_resets_plug, stat->s_resets_timeout,
@@ -1173,8 +1385,10 @@ static int ptc_seq_show(struct seq_file *file, void *data)
                           stat->d_nomsg, stat->d_retries, stat->d_canceled,
                           stat->d_nocanceled, stat->d_resets,
                           stat->d_rcanceled);
-               seq_printf(file, "%ld %ld\n",
-                       stat->s_bau_disabled, stat->s_bau_reenabled);
+               seq_printf(file, "%ld %ld %ld %ld %ld\n",
+                       stat->s_bau_disabled, stat->s_bau_reenabled,
+                       stat->s_uv2_wars, stat->s_uv2_wars_hw,
+                       stat->s_uv2_war_waits);
        }
        return 0;
 }
@@ -1432,12 +1646,15 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
 {
        int i;
        int cpu;
+       int uv1 = 0;
        unsigned long gpa;
        unsigned long m;
        unsigned long n;
        size_t dsize;
        struct bau_desc *bau_desc;
        struct bau_desc *bd2;
+       struct uv1_bau_msg_header *uv1_hdr;
+       struct uv2_bau_msg_header *uv2_hdr;
        struct bau_control *bcp;
 
        /*
@@ -1451,6 +1668,8 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
        gpa = uv_gpa(bau_desc);
        n = uv_gpa_to_gnode(gpa);
        m = uv_gpa_to_offset(gpa);
+       if (is_uv1_hub())
+               uv1 = 1;
 
        /* the 14-bit pnode */
        write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
@@ -1461,21 +1680,33 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
         */
        for (i = 0, bd2 = bau_desc; i < (ADP_SZ * ITEMS_PER_DESC); i++, bd2++) {
                memset(bd2, 0, sizeof(struct bau_desc));
-               bd2->header.swack_flag =        1;
-               /*
-                * The base_dest_nasid set in the message header is the nasid
-                * of the first uvhub in the partition. The bit map will
-                * indicate destination pnode numbers relative to that base.
-                * They may not be consecutive if nasid striding is being used.
-                */
-               bd2->header.base_dest_nasid =   UV_PNODE_TO_NASID(base_pnode);
-               bd2->header.dest_subnodeid =    UV_LB_SUBNODEID;
-               bd2->header.command =           UV_NET_ENDPOINT_INTD;
-               bd2->header.int_both =          1;
-               /*
-                * all others need to be set to zero:
-                *   fairness chaining multilevel count replied_to
-                */
+               if (uv1) {
+                       uv1_hdr = &bd2->header.uv1_hdr;
+                       uv1_hdr->swack_flag =   1;
+                       /*
+                        * The base_dest_nasid set in the message header
+                        * is the nasid of the first uvhub in the partition.
+                        * The bit map will indicate destination pnode numbers
+                        * relative to that base. They may not be consecutive
+                        * if nasid striding is being used.
+                        */
+                       uv1_hdr->base_dest_nasid =
+                                               UV_PNODE_TO_NASID(base_pnode);
+                       uv1_hdr->dest_subnodeid =       UV_LB_SUBNODEID;
+                       uv1_hdr->command =              UV_NET_ENDPOINT_INTD;
+                       uv1_hdr->int_both =             1;
+                       /*
+                        * all others need to be set to zero:
+                        *   fairness chaining multilevel count replied_to
+                        */
+               } else {
+                       uv2_hdr = &bd2->header.uv2_hdr;
+                       uv2_hdr->swack_flag =   1;
+                       uv2_hdr->base_dest_nasid =
+                                               UV_PNODE_TO_NASID(base_pnode);
+                       uv2_hdr->dest_subnodeid =       UV_LB_SUBNODEID;
+                       uv2_hdr->command =              UV_NET_ENDPOINT_INTD;
+               }
        }
        for_each_present_cpu(cpu) {
                if (pnode != uv_blade_to_pnode(uv_cpu_to_blade_id(cpu)))
@@ -1531,6 +1762,7 @@ static void pq_init(int node, int pnode)
        write_mmr_payload_first(pnode, pn_first);
        write_mmr_payload_tail(pnode, first);
        write_mmr_payload_last(pnode, last);
+       write_gmmr_sw_ack(pnode, 0xffffUL);
 
        /* in effect, all msg_type's are set to MSG_NOOP */
        memset(pqp, 0, sizeof(struct bau_pq_entry) * DEST_Q_SIZE);
@@ -1584,14 +1816,14 @@ static int calculate_destination_timeout(void)
                ts_ns = base * mult1 * mult2;
                ret = ts_ns / 1000;
        } else {
-               /* 4 bits  0/1 for 10/80us, 3 bits of multiplier */
-               mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL);
+               /* 4 bits  0/1 for 10/80us base, 3 bits of multiplier */
+               mmr_image = uv_read_local_mmr(UVH_LB_BAU_MISC_CONTROL);
                mmr_image = (mmr_image & UV_SA_MASK) >> UV_SA_SHFT;
                if (mmr_image & (1L << UV2_ACK_UNITS_SHFT))
-                       mult1 = 80;
+                       base = 80;
                else
-                       mult1 = 10;
-               base = mmr_image & UV2_ACK_MASK;
+                       base = 10;
+               mult1 = mmr_image & UV2_ACK_MASK;
                ret = mult1 * base;
        }
        return ret;
@@ -1618,6 +1850,9 @@ static void __init init_per_cpu_tunables(void)
                bcp->cong_response_us           = congested_respns_us;
                bcp->cong_reps                  = congested_reps;
                bcp->cong_period                = congested_period;
+               bcp->clocks_per_100_usec =      usec_2_cycles(100);
+               spin_lock_init(&bcp->queue_lock);
+               spin_lock_init(&bcp->uvhub_lock);
        }
 }
 
@@ -1728,8 +1963,17 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp,
                bcp->cpus_in_socket = sdp->num_cpus;
                bcp->socket_master = *smasterp;
                bcp->uvhub = bdp->uvhub;
+               if (is_uv1_hub())
+                       bcp->uvhub_version = 1;
+               else if (is_uv2_hub())
+                       bcp->uvhub_version = 2;
+               else {
+                       printk(KERN_EMERG "uvhub version not 1 or 2\n");
+                       return 1;
+               }
                bcp->uvhub_master = *hmasterp;
                bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+               bcp->using_desc = bcp->uvhub_cpu;
                if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) {
                        printk(KERN_EMERG "%d cpus per uvhub invalid\n",
                                bcp->uvhub_cpu);
@@ -1845,6 +2089,8 @@ static int __init uv_bau_init(void)
                        uv_base_pnode = uv_blade_to_pnode(uvhub);
        }
 
+       enable_timeouts();
+
        if (init_per_cpu(nuvhubs, uv_base_pnode)) {
                nobau = 1;
                return 0;
@@ -1855,7 +2101,6 @@ static int __init uv_bau_init(void)
                if (uv_blade_nr_possible_cpus(uvhub))
                        init_uvhub(uvhub, vector, uv_base_pnode);
 
-       enable_timeouts();
        alloc_intr_gate(vector, uv_bau_message_intr1);
 
        for_each_possible_blade(uvhub) {
@@ -1867,7 +2112,8 @@ static int __init uv_bau_init(void)
                        val = 1L << 63;
                        write_gmmr_activation(pnode, val);
                        mmr = 1; /* should be 1 to broadcast to both sockets */
-                       write_mmr_data_broadcast(pnode, mmr);
+                       if (!is_uv1_hub())
+                               write_mmr_data_broadcast(pnode, mmr);
                }
        }
 
index 374a05d8ad22156b9a82e3ae0a643d9de785599f..f25c2765a5c9b48bbac24551dc2e82fc9e2d2ce2 100644 (file)
@@ -25,7 +25,7 @@ struct uv_irq_2_mmr_pnode{
        int                     irq;
 };
 
-static spinlock_t              uv_irq_lock;
+static DEFINE_SPINLOCK(uv_irq_lock);
 static struct rb_root          uv_irq_root;
 
 static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
index 711b1621747f2e45e8497a13c7c81b9bc260916f..2bbe1ec2d96ab1a4d8ae8ab540eae7f9360c2db4 100644 (file)
@@ -1,5 +1,15 @@
+#ifndef __SYSDEP_X86_PTRACE_H
+#define __SYSDEP_X86_PTRACE_H
+
 #ifdef __i386__
 #include "ptrace_32.h"
 #else
 #include "ptrace_64.h"
 #endif
+
+static inline long regs_return_value(struct uml_pt_regs *regs)
+{
+       return UPT_SYSCALL_RET(regs);
+}
+
+#endif /* __SYSDEP_X86_PTRACE_H */
index 041d4fe9dfe4b858773bc30ba1ea05ddab501637..501d4e0244ba229d90eabbe768ae1d25e057574f 100644 (file)
@@ -409,6 +409,13 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
        play_dead_common();
        HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
        cpu_bringup();
+       /*
+        * Balance out the preempt calls - as we are running in cpu_idle
+        * loop which has been called at bootup from cpu_bringup_and_idle.
+        * The cpucpu_bringup_and_idle called cpu_bringup which made a
+        * preempt_disable() So this preempt_enable will balance it out.
+        */
+       preempt_enable();
 }
 
 #else /* !CONFIG_HOTPLUG_CPU */
index cc9b1e182fcfad86bc67b56a8e172fb73d9e9ecf..d69cc6c3f8080aab34f14e0e0b42b1f6ec8e73f1 100644 (file)
@@ -116,9 +116,26 @@ static inline void spin_time_accum_blocked(u64 start)
 }
 #endif  /* CONFIG_XEN_DEBUG_FS */
 
+/*
+ * Size struct xen_spinlock so it's the same as arch_spinlock_t.
+ */
+#if NR_CPUS < 256
+typedef u8 xen_spinners_t;
+# define inc_spinners(xl) \
+       asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory");
+# define dec_spinners(xl) \
+       asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory");
+#else
+typedef u16 xen_spinners_t;
+# define inc_spinners(xl) \
+       asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory");
+# define dec_spinners(xl) \
+       asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory");
+#endif
+
 struct xen_spinlock {
        unsigned char lock;             /* 0 -> free; 1 -> locked */
-       unsigned short spinners;        /* count of waiting cpus */
+       xen_spinners_t spinners;        /* count of waiting cpus */
 };
 
 static int xen_spin_is_locked(struct arch_spinlock *lock)
@@ -164,8 +181,7 @@ static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl)
 
        wmb();                  /* set lock of interest before count */
 
-       asm(LOCK_PREFIX " incw %0"
-           : "+m" (xl->spinners) : : "memory");
+       inc_spinners(xl);
 
        return prev;
 }
@@ -176,8 +192,7 @@ static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl)
  */
 static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock *prev)
 {
-       asm(LOCK_PREFIX " decw %0"
-           : "+m" (xl->spinners) : : "memory");
+       dec_spinners(xl);
        wmb();                  /* decrement count before restoring lock */
        __this_cpu_write(lock_spinners, prev);
 }
@@ -373,6 +388,8 @@ void xen_uninit_lock_cpu(int cpu)
 
 void __init xen_init_spinlocks(void)
 {
+       BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t));
+
        pv_lock_ops.spin_is_locked = xen_spin_is_locked;
        pv_lock_ops.spin_is_contended = xen_spin_is_contended;
        pv_lock_ops.spin_lock = xen_spin_lock;
index 5fb8c27cbef58dd98cb3847e2bc1b286fdad1cd3..405a8c49ff2c991b132ea31539f128069fbb03eb 100644 (file)
@@ -118,7 +118,4 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
 /* Don't build bcopy at all ...  */
 #define __HAVE_ARCH_BCOPY
 
-#define __HAVE_ARCH_MEMSCAN
-#define memscan memchr
-
 #endif /* _XTENSA_STRING_H */
index a0d042aa296755e441fe4266a7103b315a581a34..2dff698ab02e5ce1642248afa0f582b8aa0f112f 100644 (file)
@@ -334,8 +334,7 @@ void do_syscall_trace_enter(struct pt_regs *regs)
                do_syscall_trace();
 
 #if 0
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(current, AUDIT_ARCH_XTENSA..);
+       audit_syscall_entry(current, AUDIT_ARCH_XTENSA..);
 #endif
 }
 
index fa8f26309444d2cdda41cae813cf6f5a70f1de06..75642a352a8f40595069f0833a8e7cef131eca02 100644 (file)
@@ -1659,7 +1659,7 @@ static void blkiocg_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
                ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
                if (ioc) {
                        ioc_cgroup_changed(ioc);
-                       put_io_context(ioc, NULL);
+                       put_io_context(ioc);
                }
        }
 }
index e6c05a97ee2ba94538222d76273d0d2fbae644cc..3a78b00edd71cfb7b667d50c9d3fe3265a5dba28 100644 (file)
@@ -642,7 +642,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq)
        if (rq->cmd_flags & REQ_ELVPRIV) {
                elv_put_request(q, rq);
                if (rq->elv.icq)
-                       put_io_context(rq->elv.icq->ioc, q);
+                       put_io_context(rq->elv.icq->ioc);
        }
 
        mempool_free(rq, q->rq.rq_pool);
@@ -872,13 +872,15 @@ retry:
        spin_unlock_irq(q->queue_lock);
 
        /* create icq if missing */
-       if (unlikely(et->icq_cache && !icq))
+       if ((rw_flags & REQ_ELVPRIV) && unlikely(et->icq_cache && !icq)) {
                icq = ioc_create_icq(q, gfp_mask);
+               if (!icq)
+                       goto fail_icq;
+       }
 
-       /* rqs are guaranteed to have icq on elv_set_request() if requested */
-       if (likely(!et->icq_cache || icq))
-               rq = blk_alloc_request(q, icq, rw_flags, gfp_mask);
+       rq = blk_alloc_request(q, icq, rw_flags, gfp_mask);
 
+fail_icq:
        if (unlikely(!rq)) {
                /*
                 * Allocation failed presumably due to memory. Undo anything
@@ -1210,7 +1212,6 @@ static bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
        req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
 
        drive_stat_acct(req, 0);
-       elv_bio_merged(q, req, bio);
        return true;
 }
 
@@ -1241,7 +1242,6 @@ static bool bio_attempt_front_merge(struct request_queue *q,
        req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
 
        drive_stat_acct(req, 0);
-       elv_bio_merged(q, req, bio);
        return true;
 }
 
@@ -1255,13 +1255,12 @@ static bool bio_attempt_front_merge(struct request_queue *q,
  * on %current's plugged list.  Returns %true if merge was successful,
  * otherwise %false.
  *
- * This function is called without @q->queue_lock; however, elevator is
- * accessed iff there already are requests on the plugged list which in
- * turn guarantees validity of the elevator.
- *
- * Note that, on successful merge, elevator operation
- * elevator_bio_merged_fn() will be called without queue lock.  Elevator
- * must be ready for this.
+ * Plugging coalesces IOs from the same issuer for the same purpose without
+ * going through @q->queue_lock.  As such it's more of an issuing mechanism
+ * than scheduling, and the request, while may have elvpriv data, is not
+ * added on the elevator at this point.  In addition, we don't have
+ * reliable access to the elevator outside queue lock.  Only check basic
+ * merging parameters without querying the elevator.
  */
 static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
                               unsigned int *request_count)
@@ -1280,10 +1279,10 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
 
                (*request_count)++;
 
-               if (rq->q != q)
+               if (rq->q != q || !blk_rq_merge_ok(rq, bio))
                        continue;
 
-               el_ret = elv_try_merge(rq, bio);
+               el_ret = blk_try_merge(rq, bio);
                if (el_ret == ELEVATOR_BACK_MERGE) {
                        ret = bio_attempt_back_merge(q, rq, bio);
                        if (ret)
@@ -1345,12 +1344,14 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio)
        el_ret = elv_merge(q, &req, bio);
        if (el_ret == ELEVATOR_BACK_MERGE) {
                if (bio_attempt_back_merge(q, req, bio)) {
+                       elv_bio_merged(q, req, bio);
                        if (!attempt_back_merge(q, req))
                                elv_merged_request(q, req, el_ret);
                        goto out_unlock;
                }
        } else if (el_ret == ELEVATOR_FRONT_MERGE) {
                if (bio_attempt_front_merge(q, req, bio)) {
+                       elv_bio_merged(q, req, bio);
                        if (!attempt_front_merge(q, req))
                                elv_merged_request(q, req, el_ret);
                        goto out_unlock;
index 27a06e00eaec4312c5596ad58ebaa7fcc8c438ef..8b782a63c29705661dc3ced3a13ead1dd4b42b22 100644 (file)
@@ -29,21 +29,6 @@ void get_io_context(struct io_context *ioc)
 }
 EXPORT_SYMBOL(get_io_context);
 
-/*
- * Releasing ioc may nest into another put_io_context() leading to nested
- * fast path release.  As the ioc's can't be the same, this is okay but
- * makes lockdep whine.  Keep track of nesting and use it as subclass.
- */
-#ifdef CONFIG_LOCKDEP
-#define ioc_release_depth(q)           ((q) ? (q)->ioc_release_depth : 0)
-#define ioc_release_depth_inc(q)       (q)->ioc_release_depth++
-#define ioc_release_depth_dec(q)       (q)->ioc_release_depth--
-#else
-#define ioc_release_depth(q)           0
-#define ioc_release_depth_inc(q)       do { } while (0)
-#define ioc_release_depth_dec(q)       do { } while (0)
-#endif
-
 static void icq_free_icq_rcu(struct rcu_head *head)
 {
        struct io_cq *icq = container_of(head, struct io_cq, __rcu_head);
@@ -75,11 +60,8 @@ static void ioc_exit_icq(struct io_cq *icq)
        if (rcu_dereference_raw(ioc->icq_hint) == icq)
                rcu_assign_pointer(ioc->icq_hint, NULL);
 
-       if (et->ops.elevator_exit_icq_fn) {
-               ioc_release_depth_inc(q);
+       if (et->ops.elevator_exit_icq_fn)
                et->ops.elevator_exit_icq_fn(icq);
-               ioc_release_depth_dec(q);
-       }
 
        /*
         * @icq->q might have gone away by the time RCU callback runs
@@ -98,8 +80,15 @@ static void ioc_release_fn(struct work_struct *work)
        struct io_context *ioc = container_of(work, struct io_context,
                                              release_work);
        struct request_queue *last_q = NULL;
+       unsigned long flags;
 
-       spin_lock_irq(&ioc->lock);
+       /*
+        * Exiting icq may call into put_io_context() through elevator
+        * which will trigger lockdep warning.  The ioc's are guaranteed to
+        * be different, use a different locking subclass here.  Use
+        * irqsave variant as there's no spin_lock_irq_nested().
+        */
+       spin_lock_irqsave_nested(&ioc->lock, flags, 1);
 
        while (!hlist_empty(&ioc->icq_list)) {
                struct io_cq *icq = hlist_entry(ioc->icq_list.first,
@@ -121,15 +110,15 @@ static void ioc_release_fn(struct work_struct *work)
                         */
                        if (last_q) {
                                spin_unlock(last_q->queue_lock);
-                               spin_unlock_irq(&ioc->lock);
+                               spin_unlock_irqrestore(&ioc->lock, flags);
                                blk_put_queue(last_q);
                        } else {
-                               spin_unlock_irq(&ioc->lock);
+                               spin_unlock_irqrestore(&ioc->lock, flags);
                        }
 
                        last_q = this_q;
-                       spin_lock_irq(this_q->queue_lock);
-                       spin_lock(&ioc->lock);
+                       spin_lock_irqsave(this_q->queue_lock, flags);
+                       spin_lock_nested(&ioc->lock, 1);
                        continue;
                }
                ioc_exit_icq(icq);
@@ -137,10 +126,10 @@ static void ioc_release_fn(struct work_struct *work)
 
        if (last_q) {
                spin_unlock(last_q->queue_lock);
-               spin_unlock_irq(&ioc->lock);
+               spin_unlock_irqrestore(&ioc->lock, flags);
                blk_put_queue(last_q);
        } else {
-               spin_unlock_irq(&ioc->lock);
+               spin_unlock_irqrestore(&ioc->lock, flags);
        }
 
        kmem_cache_free(iocontext_cachep, ioc);
@@ -149,79 +138,29 @@ static void ioc_release_fn(struct work_struct *work)
 /**
  * put_io_context - put a reference of io_context
  * @ioc: io_context to put
- * @locked_q: request_queue the caller is holding queue_lock of (hint)
  *
  * Decrement reference count of @ioc and release it if the count reaches
- * zero.  If the caller is holding queue_lock of a queue, it can indicate
- * that with @locked_q.  This is an optimization hint and the caller is
- * allowed to pass in %NULL even when it's holding a queue_lock.
+ * zero.
  */
-void put_io_context(struct io_context *ioc, struct request_queue *locked_q)
+void put_io_context(struct io_context *ioc)
 {
-       struct request_queue *last_q = locked_q;
        unsigned long flags;
 
        if (ioc == NULL)
                return;
 
        BUG_ON(atomic_long_read(&ioc->refcount) <= 0);
-       if (locked_q)
-               lockdep_assert_held(locked_q->queue_lock);
-
-       if (!atomic_long_dec_and_test(&ioc->refcount))
-               return;
 
        /*
-        * Destroy @ioc.  This is a bit messy because icq's are chained
-        * from both ioc and queue, and ioc->lock nests inside queue_lock.
-        * The inner ioc->lock should be held to walk our icq_list and then
-        * for each icq the outer matching queue_lock should be grabbed.
-        * ie. We need to do reverse-order double lock dancing.
-        *
-        * Another twist is that we are often called with one of the
-        * matching queue_locks held as indicated by @locked_q, which
-        * prevents performing double-lock dance for other queues.
-        *
-        * So, we do it in two stages.  The fast path uses the queue_lock
-        * the caller is holding and, if other queues need to be accessed,
-        * uses trylock to avoid introducing locking dependency.  This can
-        * handle most cases, especially if @ioc was performing IO on only
-        * single device.
-        *
-        * If trylock doesn't cut it, we defer to @ioc->release_work which
-        * can do all the double-locking dancing.
+        * Releasing ioc requires reverse order double locking and we may
+        * already be holding a queue_lock.  Do it asynchronously from wq.
         */
-       spin_lock_irqsave_nested(&ioc->lock, flags,
-                                ioc_release_depth(locked_q));
-
-       while (!hlist_empty(&ioc->icq_list)) {
-               struct io_cq *icq = hlist_entry(ioc->icq_list.first,
-                                               struct io_cq, ioc_node);
-               struct request_queue *this_q = icq->q;
-
-               if (this_q != last_q) {
-                       if (last_q && last_q != locked_q)
-                               spin_unlock(last_q->queue_lock);
-                       last_q = NULL;
-
-                       if (!spin_trylock(this_q->queue_lock))
-                               break;
-                       last_q = this_q;
-                       continue;
-               }
-               ioc_exit_icq(icq);
+       if (atomic_long_dec_and_test(&ioc->refcount)) {
+               spin_lock_irqsave(&ioc->lock, flags);
+               if (!hlist_empty(&ioc->icq_list))
+                       schedule_work(&ioc->release_work);
+               spin_unlock_irqrestore(&ioc->lock, flags);
        }
-
-       if (last_q && last_q != locked_q)
-               spin_unlock(last_q->queue_lock);
-
-       spin_unlock_irqrestore(&ioc->lock, flags);
-
-       /* if no icq is left, we're done; otherwise, kick release_work */
-       if (hlist_empty(&ioc->icq_list))
-               kmem_cache_free(iocontext_cachep, ioc);
-       else
-               schedule_work(&ioc->release_work);
 }
 EXPORT_SYMBOL(put_io_context);
 
@@ -236,7 +175,7 @@ void exit_io_context(struct task_struct *task)
        task_unlock(task);
 
        atomic_dec(&ioc->nr_tasks);
-       put_io_context(ioc, NULL);
+       put_io_context(ioc);
 }
 
 /**
index cfcc37cb222b63722bc048814c0f392205d1a898..160035f548823482968bcd58298fcf9c309e7d62 100644 (file)
@@ -471,3 +471,40 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
 {
        return attempt_merge(q, rq, next);
 }
+
+bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
+{
+       if (!rq_mergeable(rq))
+               return false;
+
+       /* don't merge file system requests and discard requests */
+       if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
+               return false;
+
+       /* don't merge discard requests and secure discard requests */
+       if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE))
+               return false;
+
+       /* different data direction or already started, don't merge */
+       if (bio_data_dir(bio) != rq_data_dir(rq))
+               return false;
+
+       /* must be same device and not a special request */
+       if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
+               return false;
+
+       /* only merge integrity protected bio into ditto rq */
+       if (bio_integrity(bio) != blk_integrity_rq(rq))
+               return false;
+
+       return true;
+}
+
+int blk_try_merge(struct request *rq, struct bio *bio)
+{
+       if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_sector)
+               return ELEVATOR_BACK_MERGE;
+       else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_sector)
+               return ELEVATOR_FRONT_MERGE;
+       return ELEVATOR_NO_MERGE;
+}
index 7efd772336de998be8c53b01a1805ae63069de62..9c12f80882b0a9f9cc4bbafcb25a2c75707e732d 100644 (file)
@@ -137,6 +137,8 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
                                struct request *next);
 void blk_recalc_rq_segments(struct request *rq);
 void blk_rq_set_mixed_merge(struct request *rq);
+bool blk_rq_merge_ok(struct request *rq, struct bio *bio);
+int blk_try_merge(struct request *rq, struct bio *bio);
 
 void blk_queue_congestion_threshold(struct request_queue *q);
 
index 4cf703fd98bb8916fe74ae3b42d4856958d57950..ff64ae3bacee90c7ad93cd4859772003f8079cb4 100644 (file)
@@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q)
 
        mutex_lock(&bsg_mutex);
        idr_remove(&bsg_minor_idr, bcd->minor);
-       sysfs_remove_link(&q->kobj, "bsg");
+       if (q->kobj.sd)
+               sysfs_remove_link(&q->kobj, "bsg");
        device_unregister(bcd->class_dev);
        bcd->class_dev = NULL;
        kref_put(&bcd->ref, bsg_kref_release_function);
index 163263ddd3814e3f087eb1a7e1461242fabbd702..d0ba505336685ffbf3b36c3d24b6ff90a2cdb377 100644 (file)
@@ -1699,18 +1699,11 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
 
        /*
         * Lookup the cfqq that this bio will be queued with and allow
-        * merge only if rq is queued there.  This function can be called
-        * from plug merge without queue_lock.  In such cases, ioc of @rq
-        * and %current are guaranteed to be equal.  Avoid lookup which
-        * requires queue_lock by using @rq's cic.
+        * merge only if rq is queued there.
         */
-       if (current->io_context == RQ_CIC(rq)->icq.ioc) {
-               cic = RQ_CIC(rq);
-       } else {
-               cic = cfq_cic_lookup(cfqd, current->io_context);
-               if (!cic)
-                       return false;
-       }
+       cic = cfq_cic_lookup(cfqd, current->io_context);
+       if (!cic)
+               return false;
 
        cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
        return cfqq == RQ_CFQQ(rq);
@@ -1794,7 +1787,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                cfqd->active_queue = NULL;
 
        if (cfqd->active_cic) {
-               put_io_context(cfqd->active_cic->icq.ioc, cfqd->queue);
+               put_io_context(cfqd->active_cic->icq.ioc);
                cfqd->active_cic = NULL;
        }
 }
@@ -3117,7 +3110,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
  */
 static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-       struct cfq_queue *old_cfqq = cfqd->active_queue;
+       enum wl_type_t old_type = cfqq_type(cfqd->active_queue);
 
        cfq_log_cfqq(cfqd, cfqq, "preempt");
        cfq_slice_expired(cfqd, 1);
@@ -3126,7 +3119,7 @@ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
         * workload type is changed, don't save slice, otherwise preempt
         * doesn't happen
         */
-       if (cfqq_type(old_cfqq) != cfqq_type(cfqq))
+       if (old_type != cfqq_type(cfqq))
                cfqq->cfqg->saved_workload_slice = 0;
 
        /*
index 91e18f8af9becaace380cc687d279eb1f47cb79a..f016855a46b094628190f68e698ae21a936912e6 100644 (file)
@@ -70,39 +70,9 @@ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
 /*
  * can we safely merge with this request?
  */
-int elv_rq_merge_ok(struct request *rq, struct bio *bio)
+bool elv_rq_merge_ok(struct request *rq, struct bio *bio)
 {
-       if (!rq_mergeable(rq))
-               return 0;
-
-       /*
-        * Don't merge file system requests and discard requests
-        */
-       if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
-               return 0;
-
-       /*
-        * Don't merge discard requests and secure discard requests
-        */
-       if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE))
-               return 0;
-
-       /*
-        * different data direction or already started, don't merge
-        */
-       if (bio_data_dir(bio) != rq_data_dir(rq))
-               return 0;
-
-       /*
-        * must be same device and not a special request
-        */
-       if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
-               return 0;
-
-       /*
-        * only merge integrity protected bio into ditto rq
-        */
-       if (bio_integrity(bio) != blk_integrity_rq(rq))
+       if (!blk_rq_merge_ok(rq, bio))
                return 0;
 
        if (!elv_iosched_allow_merge(rq, bio))
@@ -112,23 +82,6 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
 }
 EXPORT_SYMBOL(elv_rq_merge_ok);
 
-int elv_try_merge(struct request *__rq, struct bio *bio)
-{
-       int ret = ELEVATOR_NO_MERGE;
-
-       /*
-        * we can merge and sequence is ok, check if it's possible
-        */
-       if (elv_rq_merge_ok(__rq, bio)) {
-               if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector)
-                       ret = ELEVATOR_BACK_MERGE;
-               else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector)
-                       ret = ELEVATOR_FRONT_MERGE;
-       }
-
-       return ret;
-}
-
 static struct elevator_type *elevator_find(const char *name)
 {
        struct elevator_type *e;
@@ -478,8 +431,8 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
        /*
         * First try one-hit cache.
         */
-       if (q->last_merge) {
-               ret = elv_try_merge(q->last_merge, bio);
+       if (q->last_merge && elv_rq_merge_ok(q->last_merge, bio)) {
+               ret = blk_try_merge(q->last_merge, bio);
                if (ret != ELEVATOR_NO_MERGE) {
                        *req = q->last_merge;
                        return ret;
index 9ed9f60316e545b6bc0ad68f9ef8c50413450685..107f6f7be5e139129a1666f1f20aa3a6967c1ef0 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/percpu.h>
 #include <asm/byteorder.h>
 
-static DEFINE_PER_CPU(u64[80], msg_schedule);
-
 static inline u64 Ch(u64 x, u64 y, u64 z)
 {
         return z ^ (x & (y ^ z));
@@ -33,11 +31,6 @@ static inline u64 Maj(u64 x, u64 y, u64 z)
         return (x & y) | (z & (x | y));
 }
 
-static inline u64 RORu64(u64 x, u64 y)
-{
-        return (x >> y) | (x << (64 - y));
-}
-
 static const u64 sha512_K[80] = {
         0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
         0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
@@ -68,10 +61,10 @@ static const u64 sha512_K[80] = {
         0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
 };
 
-#define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
-#define e1(x)       (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
-#define s0(x)       (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
-#define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
+#define e0(x)       (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
+#define e1(x)       (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
+#define s0(x)       (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
+#define s1(x)       (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
 
 static inline void LOAD_OP(int I, u64 *W, const u8 *input)
 {
@@ -80,7 +73,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input)
 
 static inline void BLEND_OP(int I, u64 *W)
 {
-       W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+       W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
 }
 
 static void
@@ -89,15 +82,7 @@ sha512_transform(u64 *state, const u8 *input)
        u64 a, b, c, d, e, f, g, h, t1, t2;
 
        int i;
-       u64 *W = get_cpu_var(msg_schedule);
-
-       /* load the input */
-        for (i = 0; i < 16; i++)
-                LOAD_OP(i, W, input);
-
-        for (i = 16; i < 80; i++) {
-                BLEND_OP(i, W);
-        }
+       u64 W[16];
 
        /* load the state into our registers */
        a=state[0];   b=state[1];   c=state[2];   d=state[3];
@@ -105,21 +90,35 @@ sha512_transform(u64 *state, const u8 *input)
 
        /* now iterate */
        for (i=0; i<80; i+=8) {
-               t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ];
+               if (!(i & 8)) {
+                       int j;
+
+                       if (i < 16) {
+                               /* load the input */
+                               for (j = 0; j < 16; j++)
+                                       LOAD_OP(i + j, W, input);
+                       } else {
+                               for (j = 0; j < 16; j++) {
+                                       BLEND_OP(i + j, W);
+                               }
+                       }
+               }
+
+               t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[(i & 15)];
                t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
-               t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
+               t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1];
                t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
-               t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
+               t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2];
                t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
-               t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
+               t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3];
                t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
-               t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
+               t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4];
                t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
-               t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
+               t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5];
                t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
-               t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
+               t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6];
                t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
-               t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
+               t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7];
                t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
        }
 
@@ -128,8 +127,6 @@ sha512_transform(u64 *state, const u8 *input)
 
        /* erase our data */
        a = b = c = d = e = f = g = h = t1 = t2 = 0;
-       memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
-       put_cpu_var(msg_schedule);
 }
 
 static int
index ecb26b4f29a0581d697a26c69fa9b52532e0f327..1567028d2038ecbe853bfebc7b4e4debd03be8fe 100644 (file)
@@ -19,12 +19,12 @@ obj-y                               += acpi.o \
 
 # All the builtin files are in the "acpi." module_param namespace.
 acpi-y                         += osl.o utils.o reboot.o
-acpi-y                         += atomicio.o
+acpi-y                         += nvs.o
 
 # sleep related files
 acpi-y                         += wakeup.o
 acpi-y                         += sleep.o
-acpi-$(CONFIG_ACPI_SLEEP)      += proc.o nvs.o
+acpi-$(CONFIG_ACPI_SLEEP)      += proc.o
 
 
 #
index 301bd2d388ad1dc7a6a00268ebbec4266470150a..0ca208b6dcf099e4b012ed29efa0d564227f20c6 100644 (file)
@@ -8,41 +8,151 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
 # use acpi.o to put all files here into acpi.o modparam namespace
 obj-y  += acpi.o
 
-acpi-y := dsfield.o   dsmthdat.o  dsopcode.o  dswexec.o  dswscope.o \
-        dsmethod.o  dsobject.o  dsutils.o   dswload.o  dswstate.o \
-        dsinit.o dsargs.o dscontrol.o dswload2.o
+acpi-y :=              \
+       dsargs.o        \
+       dscontrol.o     \
+       dsfield.o       \
+       dsinit.o        \
+       dsmethod.o      \
+       dsmthdat.o      \
+       dsobject.o      \
+       dsopcode.o      \
+       dsutils.o       \
+       dswexec.o       \
+       dswload.o       \
+       dswload2.o      \
+       dswscope.o      \
+       dswstate.o
 
-acpi-y += evevent.o  evregion.o  evsci.o    evxfevnt.o \
-        evmisc.o   evrgnini.o  evxface.o  evxfregn.o \
-        evgpe.o    evgpeblk.o evgpeinit.o  evgpeutil.o evxfgpe.o evglock.o
+acpi-y +=              \
+       evevent.o       \
+       evgpe.o         \
+       evgpeblk.o      \
+       evgpeinit.o     \
+       evgpeutil.o     \
+       evglock.o       \
+       evmisc.o        \
+       evregion.o      \
+       evrgnini.o      \
+       evsci.o         \
+       evxface.o       \
+       evxfevnt.o      \
+       evxfgpe.o       \
+       evxfregn.o
 
-acpi-y += exconfig.o  exfield.o  exnames.o   exoparg6.o  exresolv.o  exstorob.o\
-        exconvrt.o  exfldio.o  exoparg1.o  exprep.o    exresop.o   exsystem.o\
-        excreate.o  exmisc.o   exoparg2.o  exregion.o  exstore.o   exutils.o \
-        exdump.o    exmutex.o  exoparg3.o  exresnte.o  exstoren.o  exdebug.o
+acpi-y +=              \
+       exconfig.o      \
+       exconvrt.o      \
+       excreate.o      \
+       exdebug.o       \
+       exdump.o        \
+       exfield.o       \
+       exfldio.o       \
+       exmutex.o       \
+       exnames.o       \
+       exoparg1.o      \
+       exoparg2.o      \
+       exoparg3.o      \
+       exoparg6.o      \
+       exprep.o        \
+       exmisc.o        \
+       exregion.o      \
+       exresnte.o      \
+       exresolv.o      \
+       exresop.o       \
+       exstore.o       \
+       exstoren.o      \
+       exstorob.o      \
+       exsystem.o      \
+       exutils.o
 
-acpi-y += hwacpi.o  hwgpe.o  hwregs.o  hwsleep.o hwxface.o hwvalid.o hwpci.o
+acpi-y +=              \
+       hwacpi.o        \
+       hwgpe.o         \
+       hwpci.o         \
+       hwregs.o        \
+       hwsleep.o       \
+       hwvalid.o       \
+       hwxface.o
 
 acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
-acpi-y += nsaccess.o  nsload.o    nssearch.o  nsxfeval.o \
-        nsalloc.o   nseval.o    nsnames.o   nsutils.o   nsxfname.o \
-        nsdump.o    nsinit.o    nsobject.o  nswalk.o    nsxfobj.o  \
-        nsparse.o   nspredef.o  nsrepair.o  nsrepair2.o
+acpi-y +=              \
+       nsaccess.o      \
+       nsalloc.o       \
+       nsdump.o        \
+       nseval.o        \
+       nsinit.o        \
+       nsload.o        \
+       nsnames.o       \
+       nsobject.o      \
+       nsparse.o       \
+       nspredef.o      \
+       nsrepair.o      \
+       nsrepair2.o     \
+       nssearch.o      \
+       nsutils.o       \
+       nswalk.o        \
+       nsxfeval.o      \
+       nsxfname.o      \
+       nsxfobj.o
 
 acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
 
-acpi-y += psargs.o    psparse.o  psloop.o pstree.o   pswalk.o  \
-        psopcode.o  psscope.o  psutils.o  psxface.o
+acpi-y +=              \
+       psargs.o        \
+       psloop.o        \
+       psopcode.o      \
+       psparse.o       \
+       psscope.o       \
+       pstree.o        \
+       psutils.o       \
+       pswalk.o        \
+       psxface.o
 
-acpi-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
-        rscalc.o  rsirq.o  rsmemory.o  rsutils.o
+acpi-y +=              \
+       rsaddr.o        \
+       rscalc.o        \
+       rscreate.o      \
+       rsinfo.o        \
+       rsio.o          \
+       rsirq.o         \
+       rslist.o        \
+       rsmemory.o      \
+       rsmisc.o        \
+       rsserial.o      \
+       rsutils.o       \
+       rsxface.o
 
 acpi-$(ACPI_FUTURE_USAGE) += rsdump.o
 
-acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
+acpi-y +=              \
+       tbfadt.o        \
+       tbfind.o        \
+       tbinstal.o      \
+       tbutils.o       \
+       tbxface.o       \
+       tbxfroot.o
 
-acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
-               utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
-               utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
-               utosi.o utxferror.o utdecode.o
+acpi-y +=              \
+       utaddress.o     \
+       utalloc.o       \
+       utcopy.o        \
+       utdebug.o       \
+       utdecode.o      \
+       utdelete.o      \
+       uteval.o        \
+       utglobal.o      \
+       utids.o         \
+       utinit.o        \
+       utlock.o        \
+       utmath.o        \
+       utmisc.o        \
+       utmutex.o       \
+       utobject.o      \
+       utosi.o         \
+       utresrc.o       \
+       utstate.o       \
+       utxface.o       \
+       utxferror.o     \
+       utxfmutex.o
index e0ba17f0a7c89acc590ab487e5c51c1360697579..a44bd424f9f4137b58a722e313d3454b0fbc2243 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f895a244ca7ea187588356475e6ca4d700804b52..1f30af613e87619d4ab7cfeec3d45dad1d15d386 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #define ACPI_MAX_SLEEP                  2000   /* Two seconds */
 
+/* Address Range lists are per-space_id (Memory and I/O only) */
+
+#define ACPI_ADDRESS_RANGE_MAX          2
+
 /******************************************************************************
  *
  * ACPI Specification constants (Do not change unless the specification changes)
 #define ACPI_RSDP_CHECKSUM_LENGTH       20
 #define ACPI_RSDP_XCHECKSUM_LENGTH      36
 
-/* SMBus and IPMI bidirectional buffer size */
+/* SMBus, GSBus and IPMI bidirectional buffer size */
 
 #define ACPI_SMBUS_BUFFER_SIZE          34
+#define ACPI_GSBUS_BUFFER_SIZE          34
 #define ACPI_IPMI_BUFFER_SIZE           66
 
 /* _sx_d and _sx_w control methods */
index eb0b1f8dee6dca011b447504b7654ca5243b3f63..deaa8197956133850767828e05dd248ea41378cf 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 2d1b7ffa377a030d9e30490bcdcfef225bdb1d89..5935ba6707e2614cddcd39d3bb0220a3bc9a2bd1 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index bea3b4899183bae0fce0ecfa44238160d438a9d3..c53caa521a30e90b46f3d6de1d70db4c7d4ea12b 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -162,6 +162,7 @@ acpi_status acpi_ev_initialize_op_regions(void);
 
 acpi_status
 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+                              union acpi_operand_object *field_obj,
                               u32 function,
                               u32 region_offset, u32 bit_width, u64 *value);
 
index e6652d716e45727cf992838b4420902b80436ce7..2853f7673f3bdf05235384b21a614bd1ac331084 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -140,8 +140,19 @@ u32 acpi_gbl_trace_flags;
 acpi_name acpi_gbl_trace_method_name;
 u8 acpi_gbl_system_awake_and_running;
 
+/*
+ * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning
+ * that the ACPI hardware is no longer required. A flag in the FADT indicates
+ * a reduced HW machine, and that flag is duplicated here for convenience.
+ */
+u8 acpi_gbl_reduced_hardware;
+
 #endif
 
+/* Do not disassemble buffers to resource descriptors */
+
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE);
+
 /*****************************************************************************
  *
  * Debug support
@@ -207,7 +218,7 @@ ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
 
 /*****************************************************************************
  *
- * Mutual exlusion within ACPICA subsystem
+ * Mutual exclusion within ACPICA subsystem
  *
  ****************************************************************************/
 
@@ -295,6 +306,8 @@ ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8 acpi_gbl_events_initialized;
 ACPI_EXTERN u8 acpi_gbl_osi_data;
 ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
+ACPI_EXTERN struct acpi_address_range
+    *acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX];
 
 #ifndef DEFINE_ACPI_GLOBALS
 
index e7213beaafc7914322f72520d40bcfd437b4ea5b..677793e938f5d83e31241206724b58fec3e01630 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 3731e1c34b83b5d75ab25f08d0eefb706d7f85bc..eb308635da7247f0e1ae0554f322d082869b3eb9 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -468,6 +468,8 @@ void acpi_ex_eisa_id_to_string(char *dest, u64 compressed_id);
 
 void acpi_ex_integer_to_string(char *dest, u64 value);
 
+u8 acpi_is_valid_space_id(u8 space_id);
+
 /*
  * exregion - default op_region handlers
  */
index 5552125d8340ef11782f4aec94595e7444cb1774..3f24068837d5ad8e80c7603ac864fa86673bf7b3 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@ typedef u32 acpi_mutex_handle;
 
 /* Total number of aml opcodes defined */
 
-#define AML_NUM_OPCODES                 0x7F
+#define AML_NUM_OPCODES                 0x81
 
 /* Forward declarations */
 
@@ -249,12 +249,16 @@ struct acpi_create_field_info {
        struct acpi_namespace_node *field_node;
        struct acpi_namespace_node *register_node;
        struct acpi_namespace_node *data_register_node;
+       struct acpi_namespace_node *connection_node;
+       u8 *resource_buffer;
        u32 bank_value;
        u32 field_bit_position;
        u32 field_bit_length;
+       u16 resource_length;
        u8 field_flags;
        u8 attribute;
        u8 field_type;
+       u8 access_length;
 };
 
 typedef
@@ -315,7 +319,8 @@ struct acpi_name_info {
 
 /*
  * Used for ACPI_PTYPE1_FIXED, ACPI_PTYPE1_VAR, ACPI_PTYPE2,
- * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT
+ * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT,
+ * ACPI_PTYPE2_FIX_VAR
  */
 struct acpi_package_info {
        u8 type;
@@ -625,6 +630,15 @@ union acpi_generic_state {
 
 typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
 
+/* Address Range info block */
+
+struct acpi_address_range {
+       struct acpi_address_range *next;
+       struct acpi_namespace_node *region_node;
+       acpi_physical_address start_address;
+       acpi_physical_address end_address;
+};
+
 /*****************************************************************************
  *
  * Parser typedefs and structs
@@ -951,7 +965,7 @@ struct acpi_port_info {
 #define ACPI_RESOURCE_NAME_END_DEPENDENT        0x38
 #define ACPI_RESOURCE_NAME_IO                   0x40
 #define ACPI_RESOURCE_NAME_FIXED_IO             0x48
-#define ACPI_RESOURCE_NAME_RESERVED_S1          0x50
+#define ACPI_RESOURCE_NAME_FIXED_DMA            0x50
 #define ACPI_RESOURCE_NAME_RESERVED_S2          0x58
 #define ACPI_RESOURCE_NAME_RESERVED_S3          0x60
 #define ACPI_RESOURCE_NAME_RESERVED_S4          0x68
@@ -973,7 +987,9 @@ struct acpi_port_info {
 #define ACPI_RESOURCE_NAME_EXTENDED_IRQ         0x89
 #define ACPI_RESOURCE_NAME_ADDRESS64            0x8A
 #define ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64   0x8B
-#define ACPI_RESOURCE_NAME_LARGE_MAX            0x8B
+#define ACPI_RESOURCE_NAME_GPIO                 0x8C
+#define ACPI_RESOURCE_NAME_SERIAL_BUS           0x8E
+#define ACPI_RESOURCE_NAME_LARGE_MAX            0x8E
 
 /*****************************************************************************
  *
index b7491ee1fba642447242705c5a7ba48c677cce94..ef338a96f5b28761b77840851d73fedd8f25da8f 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 79a598c67fe3ad30ae599aacaefa2f776b6d0303..2c9e0f049523120f4c03a094ab8b16e0563aea08 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 1055769f2f01ae97f4f69780fd93b1015512d870..c065078ca83bbbb0f3a09a22a609121d0d7785d7 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -254,6 +254,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
        u32                             base_byte_offset;   /* Byte offset within containing object */\
        u32                             value;              /* Value to store into the Bank or Index register */\
        u8                              start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
+       u8                              access_length;  /* For serial regions/fields */
 
 
 struct acpi_object_field_common {      /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
@@ -261,7 +262,9 @@ struct acpi_object_field_common {   /* COMMON FIELD (for BUFFER, REGION, BANK, and
 };
 
 struct acpi_object_region_field {
-       ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */
+       ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
+       union acpi_operand_object *region_obj;  /* Containing op_region object */
+       u8 *resource_buffer;    /* resource_template for serial regions/fields */
 };
 
 struct acpi_object_bank_field {
@@ -358,6 +361,7 @@ typedef enum {
  */
 struct acpi_object_extra {
        ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG;       /* _REG method for this region (if any) */
+       struct acpi_namespace_node *scope_node;
        void *region_context;   /* Region-specific data */
        u8 *aml_start;
        u32 aml_length;
index bb2ccfad7376548569f99ed46653c4ee710f958e..9440d053fbb3f83e6f60217bb4fc6e08cafe4a98 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,6 +93,7 @@
 #define ARGP_CONCAT_OP                  ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_CONCAT_RES_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SUPERNAME)
+#define ARGP_CONNECTFIELD_OP            ARGP_LIST1 (ARGP_NAMESTRING)
 #define ARGP_CONTINUE_OP                ARG_NONE
 #define ARGP_COPY_OP                    ARGP_LIST2 (ARGP_TERMARG,    ARGP_SIMPLENAME)
 #define ARGP_CREATE_BIT_FIELD_OP        ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
 #define ARGP_RETURN_OP                  ARGP_LIST1 (ARGP_TERMARG)
 #define ARGP_REVISION_OP                ARG_NONE
 #define ARGP_SCOPE_OP                   ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_TERMLIST)
+#define ARGP_SERIALFIELD_OP             ARGP_LIST1 (ARGP_NAMESTRING)
 #define ARGP_SHIFT_LEFT_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_SHIFT_RIGHT_OP             ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_SIGNAL_OP                  ARGP_LIST1 (ARGP_SUPERNAME)
 #define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA,   ARGI_TARGETREF)
 #define ARGI_CONCAT_RES_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_BUFFER,        ARGI_TARGETREF)
 #define ARGI_COND_REF_OF_OP             ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
+#define ARGI_CONNECTFIELD_OP            ARGI_INVALID_OPCODE
 #define ARGI_CONTINUE_OP                ARGI_INVALID_OPCODE
 #define ARGI_COPY_OP                    ARGI_LIST2 (ARGI_ANYTYPE,    ARGI_SIMPLE_TARGET)
 #define ARGI_CREATE_BIT_FIELD_OP        ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
 #define ARGI_RETURN_OP                  ARGI_INVALID_OPCODE
 #define ARGI_REVISION_OP                ARG_NONE
 #define ARGI_SCOPE_OP                   ARGI_INVALID_OPCODE
+#define ARGI_SERIALFIELD_OP             ARGI_INVALID_OPCODE
 #define ARGI_SHIFT_LEFT_OP              ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
 #define ARGI_SHIFT_RIGHT_OP             ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
 #define ARGI_SIGNAL_OP                  ARGI_LIST1 (ARGI_EVENT)
index 5ea1e06afa20637b652f87cbe9ee60b91fb62023..b725d780d34dafec0ecd1d2166a30dd8c078d1f0 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index c445cca490ea4b1489983ba4866b0fb746c3de21..bbb34c9be4e84de95f0d0922fe72ba5558f1b3e0 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length
  *      (Used for _ART, _FPS)
  *
+ * ACPI_PTYPE2_FIX_VAR: Each subpackage consists of some fixed-length elements
+ *      followed by an optional element
+ *      object type
+ *      count
+ *      object type
+ *      count = 0 (optional)
+ *      (Used for _DLM)
+ *
  *****************************************************************************/
 
 enum acpi_return_package_types {
@@ -105,7 +113,8 @@ enum acpi_return_package_types {
        ACPI_PTYPE2_PKG_COUNT = 6,
        ACPI_PTYPE2_FIXED = 7,
        ACPI_PTYPE2_MIN = 8,
-       ACPI_PTYPE2_REV_FIXED = 9
+       ACPI_PTYPE2_REV_FIXED = 9,
+       ACPI_PTYPE2_FIX_VAR = 10
 };
 
 #ifdef ACPI_CREATE_PREDEFINED_TABLE
@@ -154,6 +163,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_AC8", 0, ACPI_RTYPE_INTEGER}},
        {{"_AC9", 0, ACPI_RTYPE_INTEGER}},
        {{"_ADR", 0, ACPI_RTYPE_INTEGER}},
+       {{"_AEI", 0, ACPI_RTYPE_BUFFER}},
        {{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
                          {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
 
@@ -229,6 +239,13 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */
                          {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}},
 
+       {{"_CLS", 0, ACPI_RTYPE_PACKAGE}},      /* Fixed-length (3 Int) */
+       {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}},
+
+       {{"_CPC", 0, ACPI_RTYPE_PACKAGE}},      /* Variable-length (Ints/Bufs) */
+       {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, 0}, 0,
+         0}},
+
        {{"_CRS", 0, ACPI_RTYPE_BUFFER}},
        {{"_CRT", 0, ACPI_RTYPE_INTEGER}},
        {{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */
@@ -237,12 +254,21 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */
                          {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}},
 
+       {{"_CWS", 1, ACPI_RTYPE_INTEGER}},
        {{"_DCK", 1, ACPI_RTYPE_INTEGER}},
        {{"_DCS", 0, ACPI_RTYPE_INTEGER}},
        {{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}},
        {{"_DDN", 0, ACPI_RTYPE_STRING}},
+       {{"_DEP", 0, ACPI_RTYPE_PACKAGE}},      /* Variable-length (Refs) */
+       {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
+
        {{"_DGS", 0, ACPI_RTYPE_INTEGER}},
        {{"_DIS", 0, 0}},
+
+       {{"_DLM", 0, ACPI_RTYPE_PACKAGE}},      /* Variable-length (Pkgs) each (1 Ref, 0/1 Optional Buf/Ref) */
+       {{{ACPI_PTYPE2_FIX_VAR, ACPI_RTYPE_REFERENCE, 1,
+          ACPI_RTYPE_REFERENCE | ACPI_RTYPE_BUFFER}, 0, 0}},
+
        {{"_DMA", 0, ACPI_RTYPE_BUFFER}},
        {{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */
                          {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}},
@@ -262,6 +288,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_EJ3", 1, 0}},
        {{"_EJ4", 1, 0}},
        {{"_EJD", 0, ACPI_RTYPE_STRING}},
+       {{"_EVT", 1, 0}},
        {{"_FDE", 0, ACPI_RTYPE_BUFFER}},
        {{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */
                          {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}},
@@ -281,14 +308,17 @@ static const union acpi_predefined_info predefined_names[] =
        {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}},
 
        {{"_GAI", 0, ACPI_RTYPE_INTEGER}},
+       {{"_GCP", 0, ACPI_RTYPE_INTEGER}},
        {{"_GHL", 0, ACPI_RTYPE_INTEGER}},
        {{"_GLK", 0, ACPI_RTYPE_INTEGER}},
        {{"_GPD", 0, ACPI_RTYPE_INTEGER}},
        {{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */
+       {{"_GRT", 0, ACPI_RTYPE_BUFFER}},
        {{"_GSB", 0, ACPI_RTYPE_INTEGER}},
        {{"_GTF", 0, ACPI_RTYPE_BUFFER}},
        {{"_GTM", 0, ACPI_RTYPE_BUFFER}},
        {{"_GTS", 1, 0}},
+       {{"_GWS", 1, ACPI_RTYPE_INTEGER}},
        {{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}},
        {{"_HOT", 0, ACPI_RTYPE_INTEGER}},
        {{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */
@@ -303,6 +333,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */
                          {{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}},
 
+       {{"_HRV", 0, ACPI_RTYPE_INTEGER}},
        {{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */
        {{"_INI", 0, 0}},
        {{"_IRC", 0, 0}},
@@ -361,6 +392,9 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_PR3", 0, ACPI_RTYPE_PACKAGE}},      /* Variable-length (Refs) */
        {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
 
+       {{"_PRE", 0, ACPI_RTYPE_PACKAGE}},      /* Variable-length (Refs) */
+       {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
+
        {{"_PRL", 0, ACPI_RTYPE_PACKAGE}},      /* Variable-length (Refs) */
        {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
 
@@ -391,6 +425,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */
                          {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}},
 
+       {{"_PSE", 1, 0}},
        {{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
                          {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
 
@@ -457,6 +492,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_SLI", 0, ACPI_RTYPE_BUFFER}},
        {{"_SPD", 1, ACPI_RTYPE_INTEGER}},
        {{"_SRS", 1, 0}},
+       {{"_SRT", 1, ACPI_RTYPE_INTEGER}},
        {{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */
        {{"_SST", 1, 0}},
        {{"_STA", 0, ACPI_RTYPE_INTEGER}},
@@ -464,6 +500,7 @@ static const union acpi_predefined_info predefined_names[] =
        {{"_STP", 2, ACPI_RTYPE_INTEGER}},
        {{"_STR", 0, ACPI_RTYPE_BUFFER}},
        {{"_STV", 2, ACPI_RTYPE_INTEGER}},
+       {{"_SUB", 0, ACPI_RTYPE_STRING}},
        {{"_SUN", 0, ACPI_RTYPE_INTEGER}},
        {{"_SWS", 0, ACPI_RTYPE_INTEGER}},
        {{"_TC1", 0, ACPI_RTYPE_INTEGER}},
index f08b55b7f3a08f5dff5209ad52268e78b59cacc6..0347d099349708a6f21035467ac96e2eb5578105 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -73,28 +73,40 @@ typedef const struct acpi_rsconvert_info {
 
 /* Resource conversion opcodes */
 
-#define ACPI_RSC_INITGET                0
-#define ACPI_RSC_INITSET                1
-#define ACPI_RSC_FLAGINIT               2
-#define ACPI_RSC_1BITFLAG               3
-#define ACPI_RSC_2BITFLAG               4
-#define ACPI_RSC_COUNT                  5
-#define ACPI_RSC_COUNT16                6
-#define ACPI_RSC_LENGTH                 7
-#define ACPI_RSC_MOVE8                  8
-#define ACPI_RSC_MOVE16                 9
-#define ACPI_RSC_MOVE32                 10
-#define ACPI_RSC_MOVE64                 11
-#define ACPI_RSC_SET8                   12
-#define ACPI_RSC_DATA8                  13
-#define ACPI_RSC_ADDRESS                14
-#define ACPI_RSC_SOURCE                 15
-#define ACPI_RSC_SOURCEX                16
-#define ACPI_RSC_BITMASK                17
-#define ACPI_RSC_BITMASK16              18
-#define ACPI_RSC_EXIT_NE                19
-#define ACPI_RSC_EXIT_LE                20
-#define ACPI_RSC_EXIT_EQ                21
+typedef enum {
+       ACPI_RSC_INITGET = 0,
+       ACPI_RSC_INITSET,
+       ACPI_RSC_FLAGINIT,
+       ACPI_RSC_1BITFLAG,
+       ACPI_RSC_2BITFLAG,
+       ACPI_RSC_3BITFLAG,
+       ACPI_RSC_ADDRESS,
+       ACPI_RSC_BITMASK,
+       ACPI_RSC_BITMASK16,
+       ACPI_RSC_COUNT,
+       ACPI_RSC_COUNT16,
+       ACPI_RSC_COUNT_GPIO_PIN,
+       ACPI_RSC_COUNT_GPIO_RES,
+       ACPI_RSC_COUNT_GPIO_VEN,
+       ACPI_RSC_COUNT_SERIAL_RES,
+       ACPI_RSC_COUNT_SERIAL_VEN,
+       ACPI_RSC_DATA8,
+       ACPI_RSC_EXIT_EQ,
+       ACPI_RSC_EXIT_LE,
+       ACPI_RSC_EXIT_NE,
+       ACPI_RSC_LENGTH,
+       ACPI_RSC_MOVE_GPIO_PIN,
+       ACPI_RSC_MOVE_GPIO_RES,
+       ACPI_RSC_MOVE_SERIAL_RES,
+       ACPI_RSC_MOVE_SERIAL_VEN,
+       ACPI_RSC_MOVE8,
+       ACPI_RSC_MOVE16,
+       ACPI_RSC_MOVE32,
+       ACPI_RSC_MOVE64,
+       ACPI_RSC_SET8,
+       ACPI_RSC_SOURCE,
+       ACPI_RSC_SOURCEX
+} ACPI_RSCONVERT_OPCODES;
 
 /* Resource Conversion sub-opcodes */
 
@@ -106,6 +118,9 @@ typedef const struct acpi_rsconvert_info {
 #define ACPI_RS_OFFSET(f)               (u8) ACPI_OFFSET (struct acpi_resource,f)
 #define AML_OFFSET(f)                   (u8) ACPI_OFFSET (union aml_resource,f)
 
+/*
+ * Individual entry for the resource dump tables
+ */
 typedef const struct acpi_rsdump_info {
        u8 opcode;
        u8 offset;
@@ -116,20 +131,25 @@ typedef const struct acpi_rsdump_info {
 
 /* Values for the Opcode field above */
 
-#define ACPI_RSD_TITLE                  0
-#define ACPI_RSD_LITERAL                1
-#define ACPI_RSD_STRING                 2
-#define ACPI_RSD_UINT8                  3
-#define ACPI_RSD_UINT16                 4
-#define ACPI_RSD_UINT32                 5
-#define ACPI_RSD_UINT64                 6
-#define ACPI_RSD_1BITFLAG               7
-#define ACPI_RSD_2BITFLAG               8
-#define ACPI_RSD_SHORTLIST              9
-#define ACPI_RSD_LONGLIST               10
-#define ACPI_RSD_DWORDLIST              11
-#define ACPI_RSD_ADDRESS                12
-#define ACPI_RSD_SOURCE                 13
+typedef enum {
+       ACPI_RSD_TITLE = 0,
+       ACPI_RSD_1BITFLAG,
+       ACPI_RSD_2BITFLAG,
+       ACPI_RSD_3BITFLAG,
+       ACPI_RSD_ADDRESS,
+       ACPI_RSD_DWORDLIST,
+       ACPI_RSD_LITERAL,
+       ACPI_RSD_LONGLIST,
+       ACPI_RSD_SHORTLIST,
+       ACPI_RSD_SHORTLISTX,
+       ACPI_RSD_SOURCE,
+       ACPI_RSD_STRING,
+       ACPI_RSD_UINT8,
+       ACPI_RSD_UINT16,
+       ACPI_RSD_UINT32,
+       ACPI_RSD_UINT64,
+       ACPI_RSD_WORDLIST
+} ACPI_RSDUMP_OPCODES;
 
 /* restore default alignment */
 
@@ -138,13 +158,18 @@ typedef const struct acpi_rsdump_info {
 /* Resource tables indexed by internal resource type */
 
 extern const u8 acpi_gbl_aml_resource_sizes[];
+extern const u8 acpi_gbl_aml_resource_serial_bus_sizes[];
 extern struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[];
 
 /* Resource tables indexed by raw AML resource descriptor type */
 
 extern const u8 acpi_gbl_resource_struct_sizes[];
+extern const u8 acpi_gbl_resource_struct_serial_bus_sizes[];
 extern struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[];
 
+extern struct acpi_rsconvert_info
+    *acpi_gbl_convert_resource_serial_bus_dispatch[];
+
 struct acpi_vendor_walk_info {
        struct acpi_vendor_uuid *uuid;
        struct acpi_buffer *buffer;
@@ -190,6 +215,10 @@ acpi_status
 acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
                            struct acpi_buffer *ret_buffer);
 
+acpi_status
+acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
+                           struct acpi_buffer *ret_buffer);
+
 /*
  * rscalc
  */
@@ -293,6 +322,11 @@ extern struct acpi_rsconvert_info acpi_rs_convert_address16[];
 extern struct acpi_rsconvert_info acpi_rs_convert_ext_irq[];
 extern struct acpi_rsconvert_info acpi_rs_convert_address64[];
 extern struct acpi_rsconvert_info acpi_rs_convert_ext_address64[];
+extern struct acpi_rsconvert_info acpi_rs_convert_gpio[];
+extern struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[];
+extern struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[];
+extern struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[];
+extern struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[];
 
 /* These resources require separate get/set tables */
 
@@ -310,6 +344,7 @@ extern struct acpi_rsconvert_info acpi_rs_set_vendor[];
  * rsinfo
  */
 extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[];
+extern struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[];
 
 /*
  * rsdump
@@ -331,6 +366,12 @@ extern struct acpi_rsdump_info acpi_rs_dump_address64[];
 extern struct acpi_rsdump_info acpi_rs_dump_ext_address64[];
 extern struct acpi_rsdump_info acpi_rs_dump_ext_irq[];
 extern struct acpi_rsdump_info acpi_rs_dump_generic_reg[];
+extern struct acpi_rsdump_info acpi_rs_dump_gpio[];
+extern struct acpi_rsdump_info acpi_rs_dump_fixed_dma[];
+extern struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[];
+extern struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[];
+extern struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[];
+extern struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[];
 #endif
 
 #endif                         /* __ACRESRC_H__ */
index 1623b245dde23b226ae70d1c8233e89425b507d2..0404df605bc187940b0a82c51b5905bb83a4acc9 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 967f08124eba46ae53684bfd0347ca5da14f740f..d5bec304c823387bfc652cf7140b5e47dfb0516f 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 99c140d8e348b38c364c94352af16c86de7b164d..925ccf22101b45adcb66817c736195adbcbf975f 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
 #define _ACUTILS_H
 
 extern const u8 acpi_gbl_resource_aml_sizes[];
+extern const u8 acpi_gbl_resource_aml_serial_bus_sizes[];
 
 /* Strings used by the disassembler and debugger resource dump routines */
 
@@ -578,6 +579,24 @@ acpi_ut_create_list(char *list_name,
 
 #endif                         /* ACPI_DBG_TRACK_ALLOCATIONS */
 
+/*
+ * utaddress - address range check
+ */
+acpi_status
+acpi_ut_add_address_range(acpi_adr_space_type space_id,
+                         acpi_physical_address address,
+                         u32 length, struct acpi_namespace_node *region_node);
+
+void
+acpi_ut_remove_address_range(acpi_adr_space_type space_id,
+                            struct acpi_namespace_node *region_node);
+
+u32
+acpi_ut_check_address_range(acpi_adr_space_type space_id,
+                           acpi_physical_address address, u32 length, u8 warn);
+
+void acpi_ut_delete_address_lists(void);
+
 /*
  * utxferror - various error/warning output functions
  */
index 1077f17859ed3d3fb74d2280966b2a847025e424..905280fec0fa0a132049318fa36953b347a0c324 100644 (file)
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #define AML_LLESSEQUAL_OP           (u16) 0x9294
 #define AML_LNOTEQUAL_OP            (u16) 0x9293
 
+/*
+ * Opcodes for "Field" operators
+ */
+#define AML_FIELD_OFFSET_OP         (u8) 0x00
+#define AML_FIELD_ACCESS_OP         (u8) 0x01
+#define AML_FIELD_CONNECTION_OP     (u8) 0x02  /* ACPI 5.0 */
+#define AML_FIELD_EXT_ACCESS_OP     (u8) 0x03  /* ACPI 5.0 */
+
 /*
  * Internal opcodes
  * Use only "Unknown" AML opcodes, don't attempt to use
 #define AML_INT_METHODCALL_OP       (u16) 0x0035
 #define AML_INT_RETURN_VALUE_OP     (u16) 0x0036
 #define AML_INT_EVAL_SUBTREE_OP     (u16) 0x0037
+#define AML_INT_CONNECTION_OP       (u16) 0x0038
+#define AML_INT_EXTACCESSFIELD_OP   (u16) 0x0039
 
 #define ARG_NONE                    0x0
 
@@ -456,13 +466,16 @@ typedef enum {
  * access_as keyword
  */
 typedef enum {
-       AML_FIELD_ATTRIB_SMB_QUICK = 0x02,
-       AML_FIELD_ATTRIB_SMB_SEND_RCV = 0x04,
-       AML_FIELD_ATTRIB_SMB_BYTE = 0x06,
-       AML_FIELD_ATTRIB_SMB_WORD = 0x08,
-       AML_FIELD_ATTRIB_SMB_BLOCK = 0x0A,
-       AML_FIELD_ATTRIB_SMB_WORD_CALL = 0x0C,
-       AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D
+       AML_FIELD_ATTRIB_QUICK = 0x02,
+       AML_FIELD_ATTRIB_SEND_RCV = 0x04,
+       AML_FIELD_ATTRIB_BYTE = 0x06,
+       AML_FIELD_ATTRIB_WORD = 0x08,
+       AML_FIELD_ATTRIB_BLOCK = 0x0A,
+       AML_FIELD_ATTRIB_MULTIBYTE = 0x0B,
+       AML_FIELD_ATTRIB_WORD_CALL = 0x0C,
+       AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D,
+       AML_FIELD_ATTRIB_RAW_BYTES = 0x0E,
+       AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F
 } AML_ACCESS_ATTRIBUTE;
 
 /* Bit fields in the AML method_flags byte */
index 59122cde247c2042e1121e6f33926eba1ec61cc1..7b2128f274e71a10f2331ca8d42abd78af166677 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #define ACPI_RESTAG_TYPESPECIFICATTRIBUTES      "_ATT"
 #define ACPI_RESTAG_BASEADDRESS                 "_BAS"
 #define ACPI_RESTAG_BUSMASTER                   "_BM_" /* Master(1), Slave(0) */
+#define ACPI_RESTAG_DEBOUNCETIME                "_DBT"
 #define ACPI_RESTAG_DECODE                      "_DEC"
+#define ACPI_RESTAG_DEVICEPOLARITY              "_DPL"
 #define ACPI_RESTAG_DMA                         "_DMA"
 #define ACPI_RESTAG_DMATYPE                     "_TYP" /* Compatible(0), A(1), B(2), F(3) */
+#define ACPI_RESTAG_DRIVESTRENGTH               "_DRS"
+#define ACPI_RESTAG_ENDIANNESS                  "_END"
+#define ACPI_RESTAG_FLOWCONTROL                 "_FLC"
 #define ACPI_RESTAG_GRANULARITY                 "_GRA"
 #define ACPI_RESTAG_INTERRUPT                   "_INT"
 #define ACPI_RESTAG_INTERRUPTLEVEL              "_LL_" /* active_lo(1), active_hi(0) */
 #define ACPI_RESTAG_INTERRUPTSHARE              "_SHR" /* Shareable(1), no_share(0) */
 #define ACPI_RESTAG_INTERRUPTTYPE               "_HE_" /* Edge(1), Level(0) */
+#define ACPI_RESTAG_IORESTRICTION               "_IOR"
 #define ACPI_RESTAG_LENGTH                      "_LEN"
+#define ACPI_RESTAG_LINE                        "_LIN"
 #define ACPI_RESTAG_MEMATTRIBUTES               "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */
 #define ACPI_RESTAG_MEMTYPE                     "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
 #define ACPI_RESTAG_MAXADDR                     "_MAX"
 #define ACPI_RESTAG_MINADDR                     "_MIN"
 #define ACPI_RESTAG_MAXTYPE                     "_MAF"
 #define ACPI_RESTAG_MINTYPE                     "_MIF"
+#define ACPI_RESTAG_MODE                        "_MOD"
+#define ACPI_RESTAG_PARITY                      "_PAR"
+#define ACPI_RESTAG_PHASE                       "_PHA"
+#define ACPI_RESTAG_PIN                         "_PIN"
+#define ACPI_RESTAG_PINCONFIG                   "_PPI"
+#define ACPI_RESTAG_POLARITY                    "_POL"
 #define ACPI_RESTAG_REGISTERBITOFFSET           "_RBO"
 #define ACPI_RESTAG_REGISTERBITWIDTH            "_RBW"
 #define ACPI_RESTAG_RANGETYPE                   "_RNG"
 #define ACPI_RESTAG_READWRITETYPE               "_RW_" /* read_only(0), Writeable (1) */
+#define ACPI_RESTAG_LENGTH_RX                   "_RXL"
+#define ACPI_RESTAG_LENGTH_TX                   "_TXL"
+#define ACPI_RESTAG_SLAVEMODE                   "_SLV"
+#define ACPI_RESTAG_SPEED                       "_SPE"
+#define ACPI_RESTAG_STOPBITS                    "_STB"
 #define ACPI_RESTAG_TRANSLATION                 "_TRA"
 #define ACPI_RESTAG_TRANSTYPE                   "_TRS" /* Sparse(1), Dense(0) */
 #define ACPI_RESTAG_TYPE                        "_TTP" /* Translation(1), Static (0) */
 #define ACPI_RESTAG_XFERTYPE                    "_SIZ" /* 8(0), 8_and16(1), 16(2) */
+#define ACPI_RESTAG_VENDORDATA                  "_VEN"
 
 /* Default sizes for "small" resource descriptors */
 
 #define ASL_RDESC_END_DEPEND_SIZE               0x00
 #define ASL_RDESC_IO_SIZE                       0x07
 #define ASL_RDESC_FIXED_IO_SIZE                 0x03
+#define ASL_RDESC_FIXED_DMA_SIZE                0x05
 #define ASL_RDESC_END_TAG_SIZE                  0x01
 
 struct asl_resource_node {
@@ -164,6 +184,12 @@ struct aml_resource_end_tag {
        AML_RESOURCE_SMALL_HEADER_COMMON u8 checksum;
 };
 
+struct aml_resource_fixed_dma {
+       AML_RESOURCE_SMALL_HEADER_COMMON u16 request_lines;
+       u16 channels;
+       u8 width;
+};
+
 /*
  * LARGE descriptors
  */
@@ -263,6 +289,110 @@ struct aml_resource_generic_register {
        u64 address;
 };
 
+/* Common descriptor for gpio_int and gpio_io (ACPI 5.0) */
+
+struct aml_resource_gpio {
+       AML_RESOURCE_LARGE_HEADER_COMMON u8 revision_id;
+       u8 connection_type;
+       u16 flags;
+       u16 int_flags;
+       u8 pin_config;
+       u16 drive_strength;
+       u16 debounce_timeout;
+       u16 pin_table_offset;
+       u8 res_source_index;
+       u16 res_source_offset;
+       u16 vendor_offset;
+       u16 vendor_length;
+       /*
+        * Optional fields follow immediately:
+        * 1) PIN list (Words)
+        * 2) Resource Source String
+        * 3) Vendor Data bytes
+        */
+};
+
+#define AML_RESOURCE_GPIO_REVISION              1      /* ACPI 5.0 */
+
+/* Values for connection_type above */
+
+#define AML_RESOURCE_GPIO_TYPE_INT              0
+#define AML_RESOURCE_GPIO_TYPE_IO               1
+#define AML_RESOURCE_MAX_GPIOTYPE               1
+
+/* Common preamble for all serial descriptors (ACPI 5.0) */
+
+#define AML_RESOURCE_SERIAL_COMMON \
+       u8                              revision_id; \
+       u8                              res_source_index; \
+       u8                              type; \
+       u8                              flags; \
+       u16                             type_specific_flags; \
+       u8                              type_revision_id; \
+       u16                             type_data_length; \
+
+/* Values for the type field above */
+
+#define AML_RESOURCE_I2C_SERIALBUSTYPE          1
+#define AML_RESOURCE_SPI_SERIALBUSTYPE          2
+#define AML_RESOURCE_UART_SERIALBUSTYPE         3
+#define AML_RESOURCE_MAX_SERIALBUSTYPE          3
+#define AML_RESOURCE_VENDOR_SERIALBUSTYPE       192    /* Vendor defined is 0xC0-0xFF (NOT SUPPORTED) */
+
+struct aml_resource_common_serialbus {
+AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_SERIAL_COMMON};
+
+struct aml_resource_i2c_serialbus {
+       AML_RESOURCE_LARGE_HEADER_COMMON
+           AML_RESOURCE_SERIAL_COMMON u32 connection_speed;
+       u16 slave_address;
+       /*
+        * Optional fields follow immediately:
+        * 1) Vendor Data bytes
+        * 2) Resource Source String
+        */
+};
+
+#define AML_RESOURCE_I2C_REVISION               1      /* ACPI 5.0 */
+#define AML_RESOURCE_I2C_TYPE_REVISION          1      /* ACPI 5.0 */
+#define AML_RESOURCE_I2C_MIN_DATA_LEN           6
+
+struct aml_resource_spi_serialbus {
+       AML_RESOURCE_LARGE_HEADER_COMMON
+           AML_RESOURCE_SERIAL_COMMON u32 connection_speed;
+       u8 data_bit_length;
+       u8 clock_phase;
+       u8 clock_polarity;
+       u16 device_selection;
+       /*
+        * Optional fields follow immediately:
+        * 1) Vendor Data bytes
+        * 2) Resource Source String
+        */
+};
+
+#define AML_RESOURCE_SPI_REVISION               1      /* ACPI 5.0 */
+#define AML_RESOURCE_SPI_TYPE_REVISION          1      /* ACPI 5.0 */
+#define AML_RESOURCE_SPI_MIN_DATA_LEN           9
+
+struct aml_resource_uart_serialbus {
+       AML_RESOURCE_LARGE_HEADER_COMMON
+           AML_RESOURCE_SERIAL_COMMON u32 default_baud_rate;
+       u16 rx_fifo_size;
+       u16 tx_fifo_size;
+       u8 parity;
+       u8 lines_enabled;
+       /*
+        * Optional fields follow immediately:
+        * 1) Vendor Data bytes
+        * 2) Resource Source String
+        */
+};
+
+#define AML_RESOURCE_UART_REVISION              1      /* ACPI 5.0 */
+#define AML_RESOURCE_UART_TYPE_REVISION         1      /* ACPI 5.0 */
+#define AML_RESOURCE_UART_MIN_DATA_LEN          10
+
 /* restore default alignment */
 
 #pragma pack()
@@ -284,6 +414,7 @@ union aml_resource {
        struct aml_resource_end_dependent end_dpf;
        struct aml_resource_io io;
        struct aml_resource_fixed_io fixed_io;
+       struct aml_resource_fixed_dma fixed_dma;
        struct aml_resource_vendor_small vendor_small;
        struct aml_resource_end_tag end_tag;
 
@@ -299,6 +430,11 @@ union aml_resource {
        struct aml_resource_address64 address64;
        struct aml_resource_extended_address64 ext_address64;
        struct aml_resource_extended_irq extended_irq;
+       struct aml_resource_gpio gpio;
+       struct aml_resource_i2c_serialbus i2c_serial_bus;
+       struct aml_resource_spi_serialbus spi_serial_bus;
+       struct aml_resource_uart_serialbus uart_serial_bus;
+       struct aml_resource_common_serialbus common_serial_bus;
 
        /* Utility overlays */
 
index 8c7b99728aa23163e77178a6748ddd5e699c8e45..80eb1900297f549f8191b8d3deb4b90ad80863b8 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -250,6 +250,13 @@ acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
        status = acpi_ds_execute_arguments(node, node->parent,
                                           extra_desc->extra.aml_length,
                                           extra_desc->extra.aml_start);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       status = acpi_ut_add_address_range(obj_desc->region.space_id,
+                                          obj_desc->region.address,
+                                          obj_desc->region.length, node);
        return_ACPI_STATUS(status);
 }
 
@@ -384,8 +391,15 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
 
        /* Execute the argument AML */
 
-       status = acpi_ds_execute_arguments(node, node->parent,
+       status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
                                           extra_desc->extra.aml_length,
                                           extra_desc->extra.aml_start);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       status = acpi_ut_add_address_range(obj_desc->region.space_id,
+                                          obj_desc->region.address,
+                                          obj_desc->region.length, node);
        return_ACPI_STATUS(status);
 }
index 26c49fff58da0fecbe83c2d70bfaa825eb2c90b2..effe4ca1133fd7cd93ebb1ab397d8be0ffe68e72 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 34be60c0e4484b880f6bf2da883e7ba1e7311ecd..cd243cf2cab2373f25c40f076b2d211b8f5641a2 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -221,6 +221,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
 {
        acpi_status status;
        u64 position;
+       union acpi_parse_object *child;
 
        ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
 
@@ -232,10 +233,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
 
        while (arg) {
                /*
-                * Three types of field elements are handled:
-                * 1) Offset - specifies a bit offset
-                * 2) access_as - changes the access mode
-                * 3) Name - Enters a new named field into the namespace
+                * Four types of field elements are handled:
+                * 1) Name - Enters a new named field into the namespace
+                * 2) Offset - specifies a bit offset
+                * 3) access_as - changes the access mode/attributes
+                * 4) Connection - Associate a resource template with the field
                 */
                switch (arg->common.aml_opcode) {
                case AML_INT_RESERVEDFIELD_OP:
@@ -253,21 +255,70 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
                        break;
 
                case AML_INT_ACCESSFIELD_OP:
-
+               case AML_INT_EXTACCESSFIELD_OP:
                        /*
-                        * Get a new access_type and access_attribute -- to be used for all
-                        * field units that follow, until field end or another access_as
-                        * keyword.
+                        * Get new access_type, access_attribute, and access_length fields
+                        * -- to be used for all field units that follow, until the
+                        * end-of-field or another access_as keyword is encountered.
+                        * NOTE. These three bytes are encoded in the integer value
+                        * of the parseop for convenience.
                         *
                         * In field_flags, preserve the flag bits other than the
-                        * ACCESS_TYPE bits
+                        * ACCESS_TYPE bits.
                         */
+
+                       /* access_type (byte_acc, word_acc, etc.) */
+
                        info->field_flags = (u8)
                            ((info->
                              field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
-                            ((u8) ((u32) arg->common.value.integer >> 8)));
+                            ((u8)((u32)(arg->common.value.integer & 0x07))));
+
+                       /* access_attribute (attrib_quick, attrib_byte, etc.) */
+
+                       info->attribute =
+                           (u8)((arg->common.value.integer >> 8) & 0xFF);
+
+                       /* access_length (for serial/buffer protocols) */
+
+                       info->access_length =
+                           (u8)((arg->common.value.integer >> 16) & 0xFF);
+                       break;
+
+               case AML_INT_CONNECTION_OP:
+                       /*
+                        * Clear any previous connection. New connection is used for all
+                        * fields that follow, similar to access_as
+                        */
+                       info->resource_buffer = NULL;
+                       info->connection_node = NULL;
 
-                       info->attribute = (u8) (arg->common.value.integer);
+                       /*
+                        * A Connection() is either an actual resource descriptor (buffer)
+                        * or a named reference to a resource template
+                        */
+                       child = arg->common.value.arg;
+                       if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
+                               info->resource_buffer = child->named.data;
+                               info->resource_length =
+                                   (u16)child->named.value.integer;
+                       } else {
+                               /* Lookup the Connection() namepath, it should already exist */
+
+                               status = acpi_ns_lookup(walk_state->scope_info,
+                                                       child->common.value.
+                                                       name, ACPI_TYPE_ANY,
+                                                       ACPI_IMODE_EXECUTE,
+                                                       ACPI_NS_DONT_OPEN_SCOPE,
+                                                       walk_state,
+                                                       &info->connection_node);
+                               if (ACPI_FAILURE(status)) {
+                                       ACPI_ERROR_NAMESPACE(child->common.
+                                                            value.name,
+                                                            status);
+                                       return_ACPI_STATUS(status);
+                               }
+                       }
                        break;
 
                case AML_INT_NAMEDFIELD_OP:
@@ -374,6 +425,8 @@ acpi_ds_create_field(union acpi_parse_object *op,
                }
        }
 
+       ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info));
+
        /* Second arg is the field flags */
 
        arg = arg->common.next;
@@ -386,7 +439,6 @@ acpi_ds_create_field(union acpi_parse_object *op,
        info.region_node = region_node;
 
        status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
-
        return_ACPI_STATUS(status);
 }
 
@@ -474,8 +526,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
         */
        while (arg) {
                /*
-                * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
-                * field names in order to enter them into the namespace.
+                * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
+                * in the field names in order to enter them into the namespace.
                 */
                if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
                        status = acpi_ns_lookup(walk_state->scope_info,
@@ -651,6 +703,5 @@ acpi_ds_create_index_field(union acpi_parse_object *op,
        info.region_node = region_node;
 
        status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
-
        return_ACPI_STATUS(status);
 }
index a7718bf2b9a18a24e0bdee7554736caa07976c2b..9e5ac7f780a7e1f006bd7bd1dd256a9367859e32 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 5d797751e205b363a48e43b6484e2a9cc37fc317..00f5dab5bcc0e7414cb4ea910daf37a6536bbf5c 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 905ce29a92e1784c82430c64e527d536e1c7f579..b40bd507be5dc33993e96667b5e2c50ad6395cff 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f42e17e5c252cc98331da46b45270090b093195c..d7045ca3e32a59269e036bac0e05893e0a5d4795 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index c627a288e027644d5ef537eb1776098085811ed4..e5eff758510266c0c68a1b772c8004598d1fc2a1 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 2c477ce172fad15d44218da1cc66e3377822590e..1abcda31037f20e6988fc073cdc00764f86d7357 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index fe40e4c6554f2554310e055cfd96a289c1bf0d89..642f3c053e878e95d1a55fc9b149de42dce19f79 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 324acec1179abaef80d5bb6fdbbd50e2f4106469..552aa3a50c84882ce9c9aa152d1b231bf7f6cd20 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 976318138c56aa983f74f3786f4016040354d44c..ae71477247631074fcc627b1345e307e77b334a9 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 76a661fc1e0933cfa84aba0a6d90a449ac1e5da1..9e9490a9cbf0e22ab16bfa9c32972afbc1971962 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index a6c374ef9914e8bb57ad092498ba55feef512145..c9c2ac13e7cc926d977ad8cb3052af532416badc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index d458b041e6510aec0c91cd4b20c0080147975524..6729ebe2f1e669b78f7a30e86efd6445720113e5 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -71,6 +71,12 @@ acpi_status acpi_ev_initialize_events(void)
 
        ACPI_FUNCTION_TRACE(ev_initialize_events);
 
+       /* If Hardware Reduced flag is set, there are no fixed events */
+
+       if (acpi_gbl_reduced_hardware) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
        /*
         * Initialize the Fixed and General Purpose Events. This is done prior to
         * enabling SCIs to prevent interrupts from occurring before the handlers
@@ -111,6 +117,12 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
 
        ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
 
+       /* If Hardware Reduced flag is set, there is no ACPI h/w */
+
+       if (acpi_gbl_reduced_hardware) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
        /* Install the SCI handler */
 
        status = acpi_ev_install_sci_handler();
index 56a562a1e5d7bde44f5d15b40dc250843b2de41f..5e5683cb1f0d9445e3d0e0330eaebe3335866cf2 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,12 @@ acpi_status acpi_ev_init_global_lock_handler(void)
 
        ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
 
+       /* If Hardware Reduced flag is set, there is no global lock */
+
+       if (acpi_gbl_reduced_hardware) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
        /* Attempt installation of the global lock handler */
 
        status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
index 65c79add3b1982ae3432a830c4c94f37be60f39d..9e88cb6fb25ea6b05a0befc926b3986a66ac9fd3 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ca2c41a5331177707e46bf7b0d4f9407e8a24478..be75339cd5dd2c31731187a791d94b1829b97945 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ce9aa9f9a9724e818d5d6e6fe568e35a3bf9d39c..adf7494da9dbdcfb03e1843ea559adbbf945a889 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 80a81d0c4a80d36049aceac84b78ead5dffe0481..25073932aa10d373d2e838d8517f7209fe0b4425 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index d0b3318444273977a382afb74ffcc5a0ed2ddb65..84966f4164638573082ce23373460df4297b6eb2 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f0edf5c43c035f0da64345ffe30894099beecc2d..1b0180a1b798bb0184241ac12d75937b55d74902 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -329,6 +329,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
  * FUNCTION:    acpi_ev_address_space_dispatch
  *
  * PARAMETERS:  region_obj          - Internal region object
+ *              field_obj           - Corresponding field. Can be NULL.
  *              Function            - Read or Write operation
  *              region_offset       - Where in the region to read or write
  *              bit_width           - Field width in bits (8, 16, 32, or 64)
@@ -344,6 +345,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
 
 acpi_status
 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+                              union acpi_operand_object *field_obj,
                               u32 function,
                               u32 region_offset, u32 bit_width, u64 *value)
 {
@@ -353,6 +355,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
        union acpi_operand_object *handler_desc;
        union acpi_operand_object *region_obj2;
        void *region_context = NULL;
+       struct acpi_connection_info *context;
 
        ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
 
@@ -375,6 +378,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
 
+       context = handler_desc->address_space.context;
+
        /*
         * It may be the case that the region has never been initialized.
         * Some types of regions require special init code
@@ -404,8 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                acpi_ex_exit_interpreter();
 
                status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
-                                     handler_desc->address_space.context,
-                                     &region_context);
+                                     context, &region_context);
 
                /* Re-enter the interpreter */
 
@@ -455,6 +459,25 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                          acpi_ut_get_region_name(region_obj->region.
                                                  space_id)));
 
+       /*
+        * Special handling for generic_serial_bus and general_purpose_io:
+        * There are three extra parameters that must be passed to the
+        * handler via the context:
+        *   1) Connection buffer, a resource template from Connection() op.
+        *   2) Length of the above buffer.
+        *   3) Actual access length from the access_as() op.
+        */
+       if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
+            (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
+           context && field_obj) {
+
+               /* Get the Connection (resource_template) buffer */
+
+               context->connection = field_obj->field.resource_buffer;
+               context->length = field_obj->field.resource_length;
+               context->access_length = field_obj->field.access_length;
+       }
+
        if (!(handler_desc->address_space.handler_flags &
              ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
                /*
@@ -469,7 +492,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 
        status = handler(function,
                         (region_obj->region.address + region_offset),
-                        bit_width, value, handler_desc->address_space.context,
+                        bit_width, value, context,
                         region_obj2->extra.region_context);
 
        if (ACPI_FAILURE(status)) {
index 55a5d35ef34a0d2f85e86020b96d305dd25b356f..819c17f5897ab664b67f9656803986ae6912ad58 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 2ebd40e1a3ef947ff7672afde21c6f211d33ae00..26065c612e7673d2c376741da9dbcef3dceefb2b 100644 (file)
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f4f523bf59390108e5095a303038da3ce872f345..61944e89565a31aa7d82dcc291da7296e28a6c93 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 20516e599476c6b59cbb100d7dfdd01357ef0273..1768bbec10023613fdce37d84f400907a69c8f8b 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f06a3ee356ba72048b8a2fac77faeaf0324ec5e0..33388fd69df448155c51154bfe1f5eb332580600 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index aee887e3ca5c6ca57ac76de607e622b581f60e03..6019208cd4b6f522227b70cb5577f13406b5b221 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 745a42b401f5030bc88b11b1b89aa2b21a455b14..c86d44e41bc85bf8935a56c4a2f5c4e348bd0dc7 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -297,9 +297,9 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
        /* Bytewise reads */
 
        for (i = 0; i < length; i++) {
-               status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
-                                                       region_offset, 8,
-                                                       &value);
+               status =
+                   acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
+                                                  region_offset, 8, &value);
                if (ACPI_FAILURE(status)) {
                        return status;
                }
index 74162a11817dc9b6bff8e30ba2d039a7c1ec47a9..e385436bd42422ef81ad64ca2decfa9a14eaeae7 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 110711afada8be5c0b769c693c6fd3b624251ef4..3f5bc998c1cb15fc7f9e212faa97552b0e87465e 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -267,7 +267,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
  *
  * PARAMETERS:  aml_start           - Pointer to the region declaration AML
  *              aml_length          - Max length of the declaration AML
- *              region_space        - space_iD for the region
+ *              space_id            - Address space ID for the region
  *              walk_state          - Current state
  *
  * RETURN:      Status
@@ -279,7 +279,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
 acpi_status
 acpi_ex_create_region(u8 * aml_start,
                      u32 aml_length,
-                     u8 region_space, struct acpi_walk_state *walk_state)
+                     u8 space_id, struct acpi_walk_state *walk_state)
 {
        acpi_status status;
        union acpi_operand_object *obj_desc;
@@ -304,16 +304,19 @@ acpi_ex_create_region(u8 * aml_start,
         * Space ID must be one of the predefined IDs, or in the user-defined
         * range
         */
-       if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
-           (region_space < ACPI_USER_REGION_BEGIN) &&
-           (region_space != ACPI_ADR_SPACE_DATA_TABLE)) {
-               ACPI_ERROR((AE_INFO, "Invalid AddressSpace type 0x%X",
-                           region_space));
-               return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
+       if (!acpi_is_valid_space_id(space_id)) {
+               /*
+                * Print an error message, but continue. We don't want to abort
+                * a table load for this exception. Instead, if the region is
+                * actually used at runtime, abort the executing method.
+                */
+               ACPI_ERROR((AE_INFO,
+                           "Invalid/unknown Address Space ID: 0x%2.2X",
+                           space_id));
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
-                         acpi_ut_get_region_name(region_space), region_space));
+                         acpi_ut_get_region_name(space_id), space_id));
 
        /* Create the region descriptor */
 
@@ -330,10 +333,16 @@ acpi_ex_create_region(u8 * aml_start,
        region_obj2 = obj_desc->common.next_object;
        region_obj2->extra.aml_start = aml_start;
        region_obj2->extra.aml_length = aml_length;
+       if (walk_state->scope_info) {
+               region_obj2->extra.scope_node =
+                   walk_state->scope_info->scope.node;
+       } else {
+               region_obj2->extra.scope_node = node;
+       }
 
        /* Init the region from the operands */
 
-       obj_desc->region.space_id = region_space;
+       obj_desc->region.space_id = space_id;
        obj_desc->region.address = 0;
        obj_desc->region.length = 0;
        obj_desc->region.node = node;
index c7a2f1edd28276389d0a61bc5674ea6ee7e89b5d..e211e9c192159b10af4c9a68bc17dfba742b57fd 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 61b8c0e8b74d1b5bc115addeb1d04da535401b03..2a6ac0a3bc1e661b25876a1247fbe763279ef91d 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -192,10 +192,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = {
         "Buffer Object"}
 };
 
-static struct acpi_exdump_info acpi_ex_dump_region_field[3] = {
+static struct acpi_exdump_info acpi_ex_dump_region_field[5] = {
        {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL},
        {ACPI_EXD_FIELD, 0, NULL},
-       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"}
+       {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(field.access_length), "AccessLength"},
+       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"},
+       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.resource_buffer),
+        "ResourceBuffer"}
 };
 
 static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = {
index 0bde2230c028ed0f0cc28689e98eacccd7a9bd8b..dc092f5b35d6b8ed0198535a39be122280d7828e 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -100,18 +100,25 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
                   (obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_SMBUS
                    || obj_desc->field.region_obj->region.space_id ==
+                   ACPI_ADR_SPACE_GSBUS
+                   || obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_IPMI)) {
                /*
-                * This is an SMBus or IPMI read. We must create a buffer to hold
+                * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold
                 * the data and then directly access the region handler.
                 *
-                * Note: Smbus protocol value is passed in upper 16-bits of Function
+                * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function
                 */
                if (obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_SMBUS) {
                        length = ACPI_SMBUS_BUFFER_SIZE;
                        function =
                            ACPI_READ | (obj_desc->field.attribute << 16);
+               } else if (obj_desc->field.region_obj->region.space_id ==
+                          ACPI_ADR_SPACE_GSBUS) {
+                       length = ACPI_GSBUS_BUFFER_SIZE;
+                       function =
+                           ACPI_READ | (obj_desc->field.attribute << 16);
                } else {        /* IPMI */
 
                        length = ACPI_IPMI_BUFFER_SIZE;
@@ -248,21 +255,23 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
                   (obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_SMBUS
                    || obj_desc->field.region_obj->region.space_id ==
+                   ACPI_ADR_SPACE_GSBUS
+                   || obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_IPMI)) {
                /*
-                * This is an SMBus or IPMI write. We will bypass the entire field
+                * This is an SMBus, GSBus or IPMI write. We will bypass the entire field
                 * mechanism and handoff the buffer directly to the handler. For
                 * these address spaces, the buffer is bi-directional; on a write,
                 * return data is returned in the same buffer.
                 *
                 * Source must be a buffer of sufficient size:
-                * ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE.
+                * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
                 *
-                * Note: SMBus protocol type is passed in upper 16-bits of Function
+                * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function
                 */
                if (source_desc->common.type != ACPI_TYPE_BUFFER) {
                        ACPI_ERROR((AE_INFO,
-                                   "SMBus or IPMI write requires Buffer, found type %s",
+                                   "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",
                                    acpi_ut_get_object_type_name(source_desc)));
 
                        return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
@@ -273,6 +282,11 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
                        length = ACPI_SMBUS_BUFFER_SIZE;
                        function =
                            ACPI_WRITE | (obj_desc->field.attribute << 16);
+               } else if (obj_desc->field.region_obj->region.space_id ==
+                          ACPI_ADR_SPACE_GSBUS) {
+                       length = ACPI_GSBUS_BUFFER_SIZE;
+                       function =
+                           ACPI_WRITE | (obj_desc->field.attribute << 16);
                } else {        /* IPMI */
 
                        length = ACPI_IPMI_BUFFER_SIZE;
@@ -281,7 +295,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
 
                if (source_desc->buffer.length < length) {
                        ACPI_ERROR((AE_INFO,
-                                   "SMBus or IPMI write requires Buffer of length %u, found length %u",
+                                   "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",
                                    length, source_desc->buffer.length));
 
                        return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
index f915a7f3f921ea6fd43d195425cb9783946cae60..149de45fdaddc659e134903e96689ce64289f31c 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -86,6 +86,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
 {
        acpi_status status = AE_OK;
        union acpi_operand_object *rgn_desc;
+       u8 space_id;
 
        ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
 
@@ -101,6 +102,17 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
        }
 
+       space_id = rgn_desc->region.space_id;
+
+       /* Validate the Space ID */
+
+       if (!acpi_is_valid_space_id(space_id)) {
+               ACPI_ERROR((AE_INFO,
+                           "Invalid/unknown Address Space ID: 0x%2.2X",
+                           space_id));
+               return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
+       }
+
        /*
         * If the Region Address and Length have not been previously evaluated,
         * evaluate them now and save the results.
@@ -119,11 +131,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
        }
 
        /*
-        * Exit now for SMBus or IPMI address space, it has a non-linear
+        * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
         * address space and the request cannot be directly validated
         */
-       if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
-           rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
+       if (space_id == ACPI_ADR_SPACE_SMBUS ||
+           space_id == ACPI_ADR_SPACE_GSBUS ||
+           space_id == ACPI_ADR_SPACE_IPMI) {
 
                /* SMBus or IPMI has a non-linear address space */
 
@@ -271,11 +284,12 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
 
        /* Invoke the appropriate address_space/op_region handler */
 
-       status =
-           acpi_ev_address_space_dispatch(rgn_desc, function, region_offset,
-                                          ACPI_MUL_8(obj_desc->common_field.
-                                                     access_byte_width),
-                                          value);
+       status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
+                                               function, region_offset,
+                                               ACPI_MUL_8(obj_desc->
+                                                          common_field.
+                                                          access_byte_width),
+                                               value);
 
        if (ACPI_FAILURE(status)) {
                if (status == AE_NOT_IMPLEMENTED) {
@@ -316,6 +330,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
 static u8
 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
 {
+       ACPI_FUNCTION_NAME(ex_register_overflow);
 
        if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
                /*
@@ -330,6 +345,11 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
                 * The Value is larger than the maximum value that can fit into
                 * the register.
                 */
+               ACPI_ERROR((AE_INFO,
+                           "Index value 0x%8.8X%8.8X overflows field width 0x%X",
+                           ACPI_FORMAT_UINT64(value),
+                           obj_desc->common_field.bit_length));
+
                return (TRUE);
        }
 
index 703d88ed0b3df53dbcfede8511ee95e83d7658d4..0a0893310348e6ad35a8cf6cf1f56d9f1ba18961 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index be1c56ead6535e68b5b73bb22a3a9451506f840d..60933e9dc3c0a6cf07f207cdb8d86894ce03c0da 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 49ec049c157e6b4e86e0d9b1de72f60fe9452b40..fcc75fa27d323d4aa870f4c78c06473830653550 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 236ead14b7f7a2c84f4b381bad84b468f2119456..9ba8c73cea16c2018d2bd1b6baf15f847328add6 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 2571b4a310f4bd31119f506a6441877886c1390b..879e8a277b9485ccb7e8deb0cba6742357744db9 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 1b48d9d28c9ae055b92e53a06302ae66a079b08f..71fcc65c9ffae718495cb4862d3517e4b4581b62 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f4a2787e8e92b1c178dbbf85b97e2c7218f2054f..0786b86590610e5d64d8a7b8d75344733cbaac2d 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index cc95e2000406c3a7a6ff6a9bf63b27752ce008fa..30157f5a12d7d774386ab834c6ee819232f23b2e 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
 #include "acinterp.h"
 #include "amlcode.h"
 #include "acnamesp.h"
+#include "acdispat.h"
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exprep")
@@ -455,6 +456,30 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
                obj_desc->field.region_obj =
                    acpi_ns_get_attached_object(info->region_node);
 
+               /* Fields specific to generic_serial_bus fields */
+
+               obj_desc->field.access_length = info->access_length;
+
+               if (info->connection_node) {
+                       second_desc = info->connection_node->object;
+                       if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
+                               status =
+                                   acpi_ds_get_buffer_arguments(second_desc);
+                               if (ACPI_FAILURE(status)) {
+                                       acpi_ut_delete_object_desc(obj_desc);
+                                       return_ACPI_STATUS(status);
+                               }
+                       }
+
+                       obj_desc->field.resource_buffer =
+                           second_desc->buffer.pointer;
+                       obj_desc->field.resource_length =
+                           (u16)second_desc->buffer.length;
+               } else if (info->resource_buffer) {
+                       obj_desc->field.resource_buffer = info->resource_buffer;
+                       obj_desc->field.resource_length = info->resource_length;
+               }
+
                /* Allow full data read from EC address space */
 
                if ((obj_desc->field.region_obj->region.space_id ==
index f0d5e14f1f2c0040ff84c18a9a0dbaa6e73bcbed..12d51df6d3bf6ad354dc1dd9a3c095d725d61839 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 55997e46948bfed2843f4a603f3871223b8abb4a..fa50e77e64a8cedff0d23c49f9ed46ff11340156 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index db502cd7d9349c2e1b6617319023d3d9f1ed3a5a..6e335dc345285a1bd0523b82c1a3cb3406261b1c 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index e3bb00ccdff5982338d5e422e3c4aa643523de1c..a67b1d925dddca807fe3525dd5e2dee4826a53ac 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index c0c8842dd344b088649c3bc041d2df787f645ba5..c6cf843cc4c990492441b61fad0839bd6e89efd6 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index a979017d56b8e5cf23e7672574ed66f83c7b4a79..b35bed52e0616ec34ef94715d21f2e941631f3ee 100644 (file)
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index dc665cc554de762c455f801f57d1e03673c85e9d..65a45d8335c8418882c8dff45b69966406270c06 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index df66e7b686bec836ae4fb2e13e64ac0f21756473..191a129452263e858e35e27551f291156ebda12a 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 8ad93146dd3282a984918a1a9b6a4b57b4e5ed41..eb6798ba8b59b092f88019d96d46a04b8637c27f 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -435,4 +435,29 @@ void acpi_ex_integer_to_string(char *out_string, u64 value)
        }
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_is_valid_space_id
+ *
+ * PARAMETERS:  space_id            - ID to be validated
+ *
+ * RETURN:      TRUE if valid/supported ID.
+ *
+ * DESCRIPTION: Validate an operation region space_iD.
+ *
+ ******************************************************************************/
+
+u8 acpi_is_valid_space_id(u8 space_id)
+{
+
+       if ((space_id >= ACPI_NUM_PREDEFINED_REGIONS) &&
+           (space_id < ACPI_USER_REGION_BEGIN) &&
+           (space_id != ACPI_ADR_SPACE_DATA_TABLE) &&
+           (space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+               return (FALSE);
+       }
+
+       return (TRUE);
+}
+
 #endif
index fc380d3d45ab0f01ca413b7c6795532d65e45ca3..d21ec5f0b3a9a3138da2cd21058b5ecdb7cc9259 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f610d88a66be86b823f6ceed6abd7e2876c3a81e..1a6894afef7972052a08abf756c52f5e8ccad828 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 050fd227951b6835d3be95bfa828fbae7951a3d5..1455ddcdc32ceebcfcdf309c8c1d6627d7d47559 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index cc70f3fdcdd1a0f1d4222f6f7e6a84ca9ff7ebf5..4ea4eeb51bfdf588dcbc14e5b8830060e7a42378 100644 (file)
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index d52da307365006f36a067a3f033cad82fd93ff42..3c4a922a9fc2810b607e47ffd3d799277ffcea5e 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 50d21c40b5c1bdd9767aeee49851cd754f0c917b..d4973d9da9f1ce3ed876941609fda18a83928678 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 5f1605874655a2f425aa0c0abd79befcb9684a3c..6e5c43a60bb723a54d7cc15543a11a89b8bcd056 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -134,6 +134,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
        /* Supported widths are 8/16/32 */
 
        if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) {
+               ACPI_ERROR((AE_INFO,
+                           "Bad BitWidth parameter: %8.8X", bit_width));
                return AE_BAD_PARAMETER;
        }
 
index d707756228c2eaddec8d4c99cd00ce3d19b92da8..9d38eb6c0d0b9107866f355c4aa9419937ebb883 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index d93172fd15a8cfb38f7102cb799527a0f5a4b2ff..61623f3f6826ccdb6286de6e61e4611be4f6675a 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 1d0ef15d158ff72779f32c814238130f13954425..7c3d3ceb98b37798dedaaf059ff50ffedb6a4c8b 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index b683cc2ff9d3cc15d0acd687f11a8d70bbcf17b3..b7f2b3be79ac110182f9c17a3d4cecee4462ebf4 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 2ed294b7a4db9c401d094071c6c104d0c7b974a4..30ea5bc53a78bf75572169b282752f1d70ebf37c 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index c1bd02b1a058746f820988639baecb4ed73fc2b8..f375cb82e321b7958932be9e4c5bc00e65e3e30c 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index fd7c6380e2941b9cf61500ace2d3a6021b80affe..9d84ec2f0211bde65d30d10b6a79b5e0fd313fd0 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 5f7dc691c1838e0ea65d8d78ba5417e1a056c5ad..5cbf15ffe7d8ed38a38782b26f10114374b109cb 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index d5fa520c3de5cb026ec5a4b4c09ff7a410da5552..b20e7c8c3ffbcc7414689f28c242ec8c266a1a21 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 3bb8bf105ea2abb151f4e862db5d00339a9972a0..dd77a3ce6e508eb6bb6fa74d3be1a45e268d59f1 100644 (file)
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index b3234fa795b8591f62db87c30051c144ec250ee2..ec7ba2d3463ccd00a7f3986c8979bec197ff3e57 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index c845c8089f39c4190f4896889d308ef546195549..bbe46a447d34d2c9597f0894060e6f05af1645de 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -620,6 +620,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
        case ACPI_PTYPE2_FIXED:
        case ACPI_PTYPE2_MIN:
        case ACPI_PTYPE2_COUNT:
+       case ACPI_PTYPE2_FIX_VAR:
 
                /*
                 * These types all return a single Package that consists of a
@@ -759,6 +760,34 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
                        }
                        break;
 
+               case ACPI_PTYPE2_FIX_VAR:
+                       /*
+                        * Each subpackage has a fixed number of elements and an
+                        * optional element
+                        */
+                       expected_count =
+                           package->ret_info.count1 + package->ret_info.count2;
+                       if (sub_package->package.count < expected_count) {
+                               goto package_too_small;
+                       }
+
+                       status =
+                           acpi_ns_check_package_elements(data, sub_elements,
+                                                          package->ret_info.
+                                                          object_type1,
+                                                          package->ret_info.
+                                                          count1,
+                                                          package->ret_info.
+                                                          object_type2,
+                                                          sub_package->package.
+                                                          count -
+                                                          package->ret_info.
+                                                          count1, 0);
+                       if (ACPI_FAILURE(status)) {
+                               return (status);
+                       }
+                       break;
+
                case ACPI_PTYPE2_FIXED:
 
                        /* Each sub-package has a fixed length */
index ac7b854b0bd740fb16ee73c6f5df978d79952900..9c35d20eb52b14fc9c4a5e238017852d934aee7c 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -634,6 +634,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
        case ACPI_PTYPE2_FIXED:
        case ACPI_PTYPE2_MIN:
        case ACPI_PTYPE2_REV_FIXED:
+       case ACPI_PTYPE2_FIX_VAR:
                break;
 
        default:
index 024c4f263f872fc550567e56a5d4a32c369071de..726bc8e687f7a68bca895b881ce2bea09823fd87 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -467,11 +467,12 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data,
        }
 
        /*
-        * Copy and uppercase the string. From the ACPI specification:
+        * Copy and uppercase the string. From the ACPI 5.0 specification:
         *
         * A valid PNP ID must be of the form "AAA####" where A is an uppercase
         * letter and # is a hex digit. A valid ACPI ID must be of the form
-        * "ACPI####" where # is a hex digit.
+        * "NNNN####" where N is an uppercase letter or decimal digit, and
+        * # is a hex digit.
         */
        for (dest = new_string->string.pointer; *source; dest++, source++) {
                *dest = (char)ACPI_TOUPPER(*source);
index 28b0d7a62b9976c5cf04e1043f5293f81f8189f0..507043d6611428e939182515449eb288fde51395 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index cb1b104a69a20211804e8c5124f07c8d6c9ea9b9..a535b7afda5cc3daf2cb80a28fd03fa18c22a6df 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 345f0c3c6ad2a336a1e8982a318ec2ca7742ce7a..f69895a548957761476e6ee4f5f29805729b6187 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index e7f016d1b226edcd295f5a60adc73a0632d8b3ac..71d15f61807ba312e9f60b617c215a23ce643f9e 100644 (file)
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 83bf930243034608eeda0b5467883c1782c7c3c8..af401c9c4dfc04f51c5d2091b8aac799873fbd10 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 57e6d825ed8411c8d0bd16c1de6208686a920244..880a605cee20e24b59d8173c0010c9ed456b11c2 100644 (file)
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index e1fad0ee0136760806f8e3dcf1e1cb76b1509e7a..5ac36aba507c348192485115399f9cd8b02944fc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -484,34 +484,54 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
 static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
                                                       *parser_state)
 {
-       u32 aml_offset = (u32)
-           ACPI_PTR_DIFF(parser_state->aml,
-                         parser_state->aml_start);
+       u32 aml_offset;
        union acpi_parse_object *field;
+       union acpi_parse_object *arg = NULL;
        u16 opcode;
        u32 name;
+       u8 access_type;
+       u8 access_attribute;
+       u8 access_length;
+       u32 pkg_length;
+       u8 *pkg_end;
+       u32 buffer_length;
 
        ACPI_FUNCTION_TRACE(ps_get_next_field);
 
+       aml_offset =
+           (u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start);
+
        /* Determine field type */
 
        switch (ACPI_GET8(parser_state->aml)) {
-       default:
+       case AML_FIELD_OFFSET_OP:
 
-               opcode = AML_INT_NAMEDFIELD_OP;
+               opcode = AML_INT_RESERVEDFIELD_OP;
+               parser_state->aml++;
                break;
 
-       case 0x00:
+       case AML_FIELD_ACCESS_OP:
 
-               opcode = AML_INT_RESERVEDFIELD_OP;
+               opcode = AML_INT_ACCESSFIELD_OP;
                parser_state->aml++;
                break;
 
-       case 0x01:
+       case AML_FIELD_CONNECTION_OP:
 
-               opcode = AML_INT_ACCESSFIELD_OP;
+               opcode = AML_INT_CONNECTION_OP;
+               parser_state->aml++;
+               break;
+
+       case AML_FIELD_EXT_ACCESS_OP:
+
+               opcode = AML_INT_EXTACCESSFIELD_OP;
                parser_state->aml++;
                break;
+
+       default:
+
+               opcode = AML_INT_NAMEDFIELD_OP;
+               break;
        }
 
        /* Allocate a new field op */
@@ -549,16 +569,111 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
                break;
 
        case AML_INT_ACCESSFIELD_OP:
+       case AML_INT_EXTACCESSFIELD_OP:
 
                /*
                 * Get access_type and access_attrib and merge into the field Op
-                * access_type is first operand, access_attribute is second
+                * access_type is first operand, access_attribute is second. stuff
+                * these bytes into the node integer value for convenience.
                 */
-               field->common.value.integer =
-                   (((u32) ACPI_GET8(parser_state->aml) << 8));
+
+               /* Get the two bytes (Type/Attribute) */
+
+               access_type = ACPI_GET8(parser_state->aml);
                parser_state->aml++;
-               field->common.value.integer |= ACPI_GET8(parser_state->aml);
+               access_attribute = ACPI_GET8(parser_state->aml);
                parser_state->aml++;
+
+               field->common.value.integer = (u8)access_type;
+               field->common.value.integer |= (u16)(access_attribute << 8);
+
+               /* This opcode has a third byte, access_length */
+
+               if (opcode == AML_INT_EXTACCESSFIELD_OP) {
+                       access_length = ACPI_GET8(parser_state->aml);
+                       parser_state->aml++;
+
+                       field->common.value.integer |=
+                           (u32)(access_length << 16);
+               }
+               break;
+
+       case AML_INT_CONNECTION_OP:
+
+               /*
+                * Argument for Connection operator can be either a Buffer
+                * (resource descriptor), or a name_string.
+                */
+               if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) {
+                       parser_state->aml++;
+
+                       pkg_end = parser_state->aml;
+                       pkg_length =
+                           acpi_ps_get_next_package_length(parser_state);
+                       pkg_end += pkg_length;
+
+                       if (parser_state->aml < pkg_end) {
+
+                               /* Non-empty list */
+
+                               arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
+                               if (!arg) {
+                                       return_PTR(NULL);
+                               }
+
+                               /* Get the actual buffer length argument */
+
+                               opcode = ACPI_GET8(parser_state->aml);
+                               parser_state->aml++;
+
+                               switch (opcode) {
+                               case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
+                                       buffer_length =
+                                           ACPI_GET8(parser_state->aml);
+                                       parser_state->aml += 1;
+                                       break;
+
+                               case AML_WORD_OP:       /* AML_WORDDATA_ARG */
+                                       buffer_length =
+                                           ACPI_GET16(parser_state->aml);
+                                       parser_state->aml += 2;
+                                       break;
+
+                               case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
+                                       buffer_length =
+                                           ACPI_GET32(parser_state->aml);
+                                       parser_state->aml += 4;
+                                       break;
+
+                               default:
+                                       buffer_length = 0;
+                                       break;
+                               }
+
+                               /* Fill in bytelist data */
+
+                               arg->named.value.size = buffer_length;
+                               arg->named.data = parser_state->aml;
+                       }
+
+                       /* Skip to End of byte data */
+
+                       parser_state->aml = pkg_end;
+               } else {
+                       arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
+                       if (!arg) {
+                               return_PTR(NULL);
+                       }
+
+                       /* Get the Namestring argument */
+
+                       arg->common.value.name =
+                           acpi_ps_get_next_namestring(parser_state);
+               }
+
+               /* Link the buffer/namestring to parent (CONNECTION_OP) */
+
+               acpi_ps_append_arg(field, arg);
                break;
 
        default:
index 01dd70d1de514eb8e8a03dfbc94995e35a6f90e3..9547ad8a620bfc1e801e30a6bc8dfb1891288fb5 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index bed08de7528c20e1762a8c989e89fece2a368bdf..a0226fdcf75c0406e7f8bc0a9388000985d44637 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -638,7 +638,16 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 
 /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
                 AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
-                AML_FLAGS_EXEC_0A_0T_1R)
+                        AML_FLAGS_EXEC_0A_0T_1R),
+
+/* ACPI 5.0 opcodes */
+
+/* 7F */ ACPI_OP("-ConnectField-", ARGP_CONNECTFIELD_OP,
+                        ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 80 */ ACPI_OP("-ExtAccessField-", ARGP_CONNECTFIELD_OP,
+                        ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0)
 
 /*! [End] no source code translation !*/
 };
@@ -657,7 +666,7 @@ static const u8 acpi_gbl_short_op_index[256] = {
 /* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
 /* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
 /* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
 /* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
index 9bb0cbd37b5e678d462702d909d7a165396f2342..2ff9c35a19686be19b16a1b203936a6ca45982bc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index a5faa1323a0290f77676419a07ccc05eed2313e5..c872aa4b926ec52bc1ddbec6921871529b97edcc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f1464c03aa427865f4601cd01d58712ce7024b39..2b03cdbbe1c0dc49436b6bc089b5a7bd771904db 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -74,6 +74,12 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
 
        ACPI_FUNCTION_ENTRY();
 
+/*
+       if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP)
+       {
+               return (Op->Common.Value.Arg);
+       }
+*/
        /* Get the info structure for this opcode */
 
        op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
index 7eda78503422b7d651b046c2b05a76ac895d1fb0..13bb131ae12517040401a7cbfa02b8c3c0735422 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 3312d6368bf15bba6e193b14e2d3c47cf01dd804..ab96cf47896d33e9a28b7854306c5011dbfff970 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 8086805d44946ba73f0f2819271d2077d3755721..9d98c5ff66a5f8c08a0704a658d962b1f2d82ff7 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 9e66f90784269243cb5e30f815b50f299c16ccf9..a0305652394f1f03fbebc050e55ce5ad28bd1856 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 3a8a89ec2ca4195d14a90b620918f6f4aa9cd881..3c6df4b7eb2ddc200575ea8849b905519efe6f87 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -313,6 +313,38 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
                                                          resource_source));
                        break;
 
+               case ACPI_RESOURCE_TYPE_GPIO:
+
+                       total_size =
+                           (acpi_rs_length) (total_size +
+                                             (resource->data.gpio.
+                                              pin_table_length * 2) +
+                                             resource->data.gpio.
+                                             resource_source.string_length +
+                                             resource->data.gpio.
+                                             vendor_length);
+
+                       break;
+
+               case ACPI_RESOURCE_TYPE_SERIAL_BUS:
+
+                       total_size =
+                           acpi_gbl_aml_resource_serial_bus_sizes[resource->
+                                                                  data.
+                                                                  common_serial_bus.
+                                                                  type];
+
+                       total_size = (acpi_rs_length) (total_size +
+                                                      resource->data.
+                                                      i2c_serial_bus.
+                                                      resource_source.
+                                                      string_length +
+                                                      resource->data.
+                                                      i2c_serial_bus.
+                                                      vendor_length);
+
+                       break;
+
                default:
                        break;
                }
@@ -362,10 +394,11 @@ acpi_rs_get_list_length(u8 * aml_buffer,
        u32 extra_struct_bytes;
        u8 resource_index;
        u8 minimum_aml_resource_length;
+       union aml_resource *aml_resource;
 
        ACPI_FUNCTION_TRACE(rs_get_list_length);
 
-       *size_needed = 0;
+       *size_needed = ACPI_RS_SIZE_MIN;        /* Minimum size is one end_tag */
        end_aml = aml_buffer + aml_buffer_length;
 
        /* Walk the list of AML resource descriptors */
@@ -376,9 +409,15 @@ acpi_rs_get_list_length(u8 * aml_buffer,
 
                status = acpi_ut_validate_resource(aml_buffer, &resource_index);
                if (ACPI_FAILURE(status)) {
+                       /*
+                        * Exit on failure. Cannot continue because the descriptor length
+                        * may be bogus also.
+                        */
                        return_ACPI_STATUS(status);
                }
 
+               aml_resource = (void *)aml_buffer;
+
                /* Get the resource length and base (minimum) AML size */
 
                resource_length = acpi_ut_get_resource_length(aml_buffer);
@@ -422,10 +461,8 @@ acpi_rs_get_list_length(u8 * aml_buffer,
 
                case ACPI_RESOURCE_NAME_END_TAG:
                        /*
-                        * End Tag:
-                        * This is the normal exit, add size of end_tag
+                        * End Tag: This is the normal exit
                         */
-                       *size_needed += ACPI_RS_SIZE_MIN;
                        return_ACPI_STATUS(AE_OK);
 
                case ACPI_RESOURCE_NAME_ADDRESS32:
@@ -457,6 +494,33 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                                                         minimum_aml_resource_length);
                        break;
 
+               case ACPI_RESOURCE_NAME_GPIO:
+
+                       /* Vendor data is optional */
+
+                       if (aml_resource->gpio.vendor_length) {
+                               extra_struct_bytes +=
+                                   aml_resource->gpio.vendor_offset -
+                                   aml_resource->gpio.pin_table_offset +
+                                   aml_resource->gpio.vendor_length;
+                       } else {
+                               extra_struct_bytes +=
+                                   aml_resource->large_header.resource_length +
+                                   sizeof(struct aml_resource_large_header) -
+                                   aml_resource->gpio.pin_table_offset;
+                       }
+                       break;
+
+               case ACPI_RESOURCE_NAME_SERIAL_BUS:
+
+                       minimum_aml_resource_length =
+                           acpi_gbl_resource_aml_serial_bus_sizes
+                           [aml_resource->common_serial_bus.type];
+                       extra_struct_bytes +=
+                           aml_resource->common_serial_bus.resource_length -
+                           minimum_aml_resource_length;
+                       break;
+
                default:
                        break;
                }
@@ -467,9 +531,18 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                 * Important: Round the size up for the appropriate alignment. This
                 * is a requirement on IA64.
                 */
-               buffer_size = acpi_gbl_resource_struct_sizes[resource_index] +
-                   extra_struct_bytes;
-               buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
+               if (acpi_ut_get_resource_type(aml_buffer) ==
+                   ACPI_RESOURCE_NAME_SERIAL_BUS) {
+                       buffer_size =
+                           acpi_gbl_resource_struct_serial_bus_sizes
+                           [aml_resource->common_serial_bus.type] +
+                           extra_struct_bytes;
+               } else {
+                       buffer_size =
+                           acpi_gbl_resource_struct_sizes[resource_index] +
+                           extra_struct_bytes;
+               }
+               buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
 
                *size_needed += buffer_size;
 
index 4ce6e1147e807993cccc251af32632d0eabca6e8..46d6eb38ae66f5598faba40c70ffaf4466e0459b 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rscreate")
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_buffer_to_resource
+ *
+ * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
+ *              aml_buffer_length   - Length of the aml_buffer
+ *              resource_ptr        - Where the converted resource is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert a raw AML buffer to a resource list
+ *
+ ******************************************************************************/
+acpi_status
+acpi_buffer_to_resource(u8 *aml_buffer,
+                       u16 aml_buffer_length,
+                       struct acpi_resource **resource_ptr)
+{
+       acpi_status status;
+       acpi_size list_size_needed;
+       void *resource;
+       void *current_resource_ptr;
+
+       /*
+        * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag
+        * is not required here.
+        */
+
+       /* Get the required length for the converted resource */
+
+       status = acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
+                                        &list_size_needed);
+       if (status == AE_AML_NO_RESOURCE_END_TAG) {
+               status = AE_OK;
+       }
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /* Allocate a buffer for the converted resource */
+
+       resource = ACPI_ALLOCATE_ZEROED(list_size_needed);
+       current_resource_ptr = resource;
+       if (!resource) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* Perform the AML-to-Resource conversion */
+
+       status = acpi_ut_walk_aml_resources(aml_buffer, aml_buffer_length,
+                                           acpi_rs_convert_aml_to_resources,
+                                           &current_resource_ptr);
+       if (status == AE_AML_NO_RESOURCE_END_TAG) {
+               status = AE_OK;
+       }
+       if (ACPI_FAILURE(status)) {
+               ACPI_FREE(resource);
+       } else {
+               *resource_ptr = resource;
+       }
+
+       return (status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_rs_create_resource_list
@@ -66,9 +130,10 @@ ACPI_MODULE_NAME("rscreate")
  *              of device resources.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
-                            struct acpi_buffer *output_buffer)
+                            struct acpi_buffer * output_buffer)
 {
 
        acpi_status status;
index 33db7520c74be0c2937b837b31512dcec49fde58..b4c5811323932324becf8a803a85fc542dc20579 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,11 +61,13 @@ static void acpi_rs_out_integer64(char *title, u64 value);
 
 static void acpi_rs_out_title(char *title);
 
-static void acpi_rs_dump_byte_list(u16 length, u8 * data);
+static void acpi_rs_dump_byte_list(u16 length, u8 *data);
 
-static void acpi_rs_dump_dword_list(u8 length, u32 * data);
+static void acpi_rs_dump_word_list(u16 length, u16 *data);
 
-static void acpi_rs_dump_short_byte_list(u8 length, u8 * data);
+static void acpi_rs_dump_dword_list(u8 length, u32 *data);
+
+static void acpi_rs_dump_short_byte_list(u8 length, u8 *data);
 
 static void
 acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source);
@@ -309,6 +311,125 @@ struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = {
        {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL}
 };
 
+struct acpi_rsdump_info acpi_rs_dump_gpio[16] = {
+       {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type),
+        "ConnectionType", acpi_gbl_ct_decode},
+       {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer),
+        "ProducerConsumer", acpi_gbl_consume_decode},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig",
+        acpi_gbl_ppc_decode},
+       {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharable",
+        acpi_gbl_shr_decode},
+       {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction),
+        "IoRestriction", acpi_gbl_ior_decode},
+       {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering",
+        acpi_gbl_he_decode},
+       {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity",
+        acpi_gbl_ll_decode},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength",
+        NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout),
+        "DebounceTimeout", NULL},
+       {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source),
+        "ResourceSource", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length),
+        "PinTableLength", NULL},
+       {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength",
+        NULL},
+       {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData",
+        NULL},
+};
+
+struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = {
+       {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma),
+        "FixedDma", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines),
+        "RequestLines", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels",
+        NULL},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth",
+        acpi_gbl_dts_decode},
+};
+
+#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \
+       {ACPI_RSD_UINT8,    ACPI_RSD_OFFSET (common_serial_bus.revision_id),    "RevisionId",               NULL}, \
+       {ACPI_RSD_UINT8,    ACPI_RSD_OFFSET (common_serial_bus.type),           "Type",                     acpi_gbl_sbt_decode}, \
+       {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer",      acpi_gbl_consume_decode}, \
+       {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode),     "SlaveMode",                acpi_gbl_sm_decode}, \
+       {ACPI_RSD_UINT8,    ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId",         NULL}, \
+       {ACPI_RSD_UINT16,   ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength",         NULL}, \
+       {ACPI_RSD_SOURCE,   ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource",          NULL}, \
+       {ACPI_RSD_UINT16,   ACPI_RSD_OFFSET (common_serial_bus.vendor_length),  "VendorLength",             NULL}, \
+       {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data),   "VendorData",               NULL},
+
+struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = {
+       {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus),
+        "Common Serial Bus", NULL},
+       ACPI_RS_DUMP_COMMON_SERIAL_BUS
+};
+
+struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = {
+       {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus),
+        "I2C Serial Bus", NULL},
+       ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
+                                       ACPI_RSD_OFFSET(i2c_serial_bus.
+                                                       access_mode),
+                                       "AccessMode", acpi_gbl_am_decode},
+       {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed),
+        "ConnectionSpeed", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address),
+        "SlaveAddress", NULL},
+};
+
+struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = {
+       {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus),
+        "Spi Serial Bus", NULL},
+       ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
+                                       ACPI_RSD_OFFSET(spi_serial_bus.
+                                                       wire_mode), "WireMode",
+                                       acpi_gbl_wm_decode},
+       {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity),
+        "DevicePolarity", acpi_gbl_dp_decode},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length),
+        "DataBitLength", NULL},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase),
+        "ClockPhase", acpi_gbl_cph_decode},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity),
+        "ClockPolarity", acpi_gbl_cpo_decode},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection),
+        "DeviceSelection", NULL},
+       {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed),
+        "ConnectionSpeed", NULL},
+};
+
+struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = {
+       {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus),
+        "Uart Serial Bus", NULL},
+       ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG,
+                                       ACPI_RSD_OFFSET(uart_serial_bus.
+                                                       flow_control),
+                                       "FlowControl", acpi_gbl_fc_decode},
+       {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits),
+        "StopBits", acpi_gbl_sb_decode},
+       {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits),
+        "DataBits", acpi_gbl_bpb_decode},
+       {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian",
+        acpi_gbl_ed_decode},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity",
+        acpi_gbl_pt_decode},
+       {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled),
+        "LinesEnabled", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size),
+        "RxFifoSize", NULL},
+       {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size),
+        "TxFifoSize", NULL},
+       {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate),
+        "ConnectionSpeed", NULL},
+};
+
 /*
  * Tables used for common address descriptor flag fields
  */
@@ -413,7 +534,14 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
                        /* Data items, 8/16/32/64 bit */
 
                case ACPI_RSD_UINT8:
-                       acpi_rs_out_integer8(name, ACPI_GET8(target));
+                       if (table->pointer) {
+                               acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+                                                                      table->
+                                                                      pointer
+                                                                      [*target]));
+                       } else {
+                               acpi_rs_out_integer8(name, ACPI_GET8(target));
+                       }
                        break;
 
                case ACPI_RSD_UINT16:
@@ -444,6 +572,13 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
                                                                       0x03]));
                        break;
 
+               case ACPI_RSD_3BITFLAG:
+                       acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+                                                              table->
+                                                              pointer[*target &
+                                                                      0x07]));
+                       break;
+
                case ACPI_RSD_SHORTLIST:
                        /*
                         * Short byte list (single line output) for DMA and IRQ resources
@@ -456,6 +591,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
                        }
                        break;
 
+               case ACPI_RSD_SHORTLISTX:
+                       /*
+                        * Short byte list (single line output) for GPIO vendor data
+                        * Note: The list length is obtained from the previous table entry
+                        */
+                       if (previous_target) {
+                               acpi_rs_out_title(name);
+                               acpi_rs_dump_short_byte_list(*previous_target,
+                                                            *
+                                                            (ACPI_CAST_INDIRECT_PTR
+                                                             (u8, target)));
+                       }
+                       break;
+
                case ACPI_RSD_LONGLIST:
                        /*
                         * Long byte list for Vendor resource data
@@ -480,6 +629,18 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
                        }
                        break;
 
+               case ACPI_RSD_WORDLIST:
+                       /*
+                        * Word list for GPIO Pin Table
+                        * Note: The list length is obtained from the previous table entry
+                        */
+                       if (previous_target) {
+                               acpi_rs_dump_word_list(*previous_target,
+                                                      *(ACPI_CAST_INDIRECT_PTR
+                                                        (u16, target)));
+                       }
+                       break;
+
                case ACPI_RSD_ADDRESS:
                        /*
                         * Common flags for all Address resources
@@ -627,14 +788,20 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
 
                /* Dump the resource descriptor */
 
-               acpi_rs_dump_descriptor(&resource_list->data,
-                                       acpi_gbl_dump_resource_dispatch[type]);
+               if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+                       acpi_rs_dump_descriptor(&resource_list->data,
+                                               acpi_gbl_dump_serial_bus_dispatch
+                                               [resource_list->data.
+                                                common_serial_bus.type]);
+               } else {
+                       acpi_rs_dump_descriptor(&resource_list->data,
+                                               acpi_gbl_dump_resource_dispatch
+                                               [type]);
+               }
 
                /* Point to the next resource structure */
 
-               resource_list =
-                   ACPI_ADD_PTR(struct acpi_resource, resource_list,
-                                resource_list->length);
+               resource_list = ACPI_NEXT_RESOURCE(resource_list);
 
                /* Exit when END_TAG descriptor is reached */
 
@@ -768,4 +935,13 @@ static void acpi_rs_dump_dword_list(u8 length, u32 * data)
        }
 }
 
+static void acpi_rs_dump_word_list(u16 length, u16 *data)
+{
+       u16 i;
+
+       for (i = 0; i < length; i++) {
+               acpi_os_printf("%25s%2.2X : %4.4X\n", "Word", i, data[i]);
+       }
+}
+
 #endif
index f9ea60872aa4ddad8cf1cd77c20a61a0ec7c0b41..a9fa5158200b30712155cefbfc9987501cc4142e 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -76,7 +76,10 @@ struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = {
        acpi_rs_convert_address64,      /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */
        acpi_rs_convert_ext_address64,  /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
        acpi_rs_convert_ext_irq,        /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
-       acpi_rs_convert_generic_reg     /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+       acpi_rs_convert_generic_reg,    /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+       acpi_rs_convert_gpio,   /* 0x11, ACPI_RESOURCE_TYPE_GPIO */
+       acpi_rs_convert_fixed_dma,      /* 0x12, ACPI_RESOURCE_TYPE_FIXED_DMA */
+       NULL,                   /* 0x13, ACPI_RESOURCE_TYPE_SERIAL_BUS - Use subtype table below */
 };
 
 /* Dispatch tables for AML-to-resource (Get Resource) conversion functions */
@@ -94,7 +97,7 @@ struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {
        acpi_rs_convert_end_dpf,        /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
        acpi_rs_convert_io,     /* 0x08, ACPI_RESOURCE_NAME_IO */
        acpi_rs_convert_fixed_io,       /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */
-       NULL,                   /* 0x0A, Reserved */
+       acpi_rs_convert_fixed_dma,      /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */
        NULL,                   /* 0x0B, Reserved */
        NULL,                   /* 0x0C, Reserved */
        NULL,                   /* 0x0D, Reserved */
@@ -114,7 +117,19 @@ struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {
        acpi_rs_convert_address16,      /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */
        acpi_rs_convert_ext_irq,        /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */
        acpi_rs_convert_address64,      /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */
-       acpi_rs_convert_ext_address64   /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */
+       acpi_rs_convert_ext_address64,  /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */
+       acpi_rs_convert_gpio,   /* 0x0C, ACPI_RESOURCE_NAME_GPIO */
+       NULL,                   /* 0x0D, Reserved */
+       NULL,                   /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use subtype table below */
+};
+
+/* Subtype table for serial_bus -- I2C, SPI, and UART */
+
+struct acpi_rsconvert_info *acpi_gbl_convert_resource_serial_bus_dispatch[] = {
+       NULL,
+       acpi_rs_convert_i2c_serial_bus,
+       acpi_rs_convert_spi_serial_bus,
+       acpi_rs_convert_uart_serial_bus,
 };
 
 #ifdef ACPI_FUTURE_USAGE
@@ -140,6 +155,16 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = {
        acpi_rs_dump_ext_address64,     /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
        acpi_rs_dump_ext_irq,   /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
        acpi_rs_dump_generic_reg,       /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+       acpi_rs_dump_gpio,      /* ACPI_RESOURCE_TYPE_GPIO */
+       acpi_rs_dump_fixed_dma, /* ACPI_RESOURCE_TYPE_FIXED_DMA */
+       NULL,                   /* ACPI_RESOURCE_TYPE_SERIAL_BUS */
+};
+
+struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[] = {
+       NULL,
+       acpi_rs_dump_i2c_serial_bus,    /* AML_RESOURCE_I2C_BUS_TYPE */
+       acpi_rs_dump_spi_serial_bus,    /* AML_RESOURCE_SPI_BUS_TYPE */
+       acpi_rs_dump_uart_serial_bus,   /* AML_RESOURCE_UART_BUS_TYPE */
 };
 #endif
 
@@ -166,7 +191,10 @@ const u8 acpi_gbl_aml_resource_sizes[] = {
        sizeof(struct aml_resource_address64),  /* ACPI_RESOURCE_TYPE_ADDRESS64 */
        sizeof(struct aml_resource_extended_address64), /*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
        sizeof(struct aml_resource_extended_irq),       /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
-       sizeof(struct aml_resource_generic_register)    /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+       sizeof(struct aml_resource_generic_register),   /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+       sizeof(struct aml_resource_gpio),       /* ACPI_RESOURCE_TYPE_GPIO */
+       sizeof(struct aml_resource_fixed_dma),  /* ACPI_RESOURCE_TYPE_FIXED_DMA */
+       sizeof(struct aml_resource_common_serialbus),   /* ACPI_RESOURCE_TYPE_SERIAL_BUS */
 };
 
 const u8 acpi_gbl_resource_struct_sizes[] = {
@@ -182,7 +210,7 @@ const u8 acpi_gbl_resource_struct_sizes[] = {
        ACPI_RS_SIZE_MIN,
        ACPI_RS_SIZE(struct acpi_resource_io),
        ACPI_RS_SIZE(struct acpi_resource_fixed_io),
-       0,
+       ACPI_RS_SIZE(struct acpi_resource_fixed_dma),
        0,
        0,
        0,
@@ -202,5 +230,21 @@ const u8 acpi_gbl_resource_struct_sizes[] = {
        ACPI_RS_SIZE(struct acpi_resource_address16),
        ACPI_RS_SIZE(struct acpi_resource_extended_irq),
        ACPI_RS_SIZE(struct acpi_resource_address64),
-       ACPI_RS_SIZE(struct acpi_resource_extended_address64)
+       ACPI_RS_SIZE(struct acpi_resource_extended_address64),
+       ACPI_RS_SIZE(struct acpi_resource_gpio),
+       ACPI_RS_SIZE(struct acpi_resource_common_serialbus)
+};
+
+const u8 acpi_gbl_aml_resource_serial_bus_sizes[] = {
+       0,
+       sizeof(struct aml_resource_i2c_serialbus),
+       sizeof(struct aml_resource_spi_serialbus),
+       sizeof(struct aml_resource_uart_serialbus),
+};
+
+const u8 acpi_gbl_resource_struct_serial_bus_sizes[] = {
+       0,
+       ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus),
+       ACPI_RS_SIZE(struct acpi_resource_spi_serialbus),
+       ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),
 };
index 0c7efef008bed3c2bcd652fae16bf9d0ae80ca29..f6a081057a22d24ca6e06a40db2df63890eedd45 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 50b8ad21116736185832c802d63529bbfa9532cd..e23a9ec248cbc7c8b0e5bfbcc90f1b4d552865b2 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -264,3 +264,34 @@ struct acpi_rsconvert_info acpi_rs_convert_dma[6] = {
         AML_OFFSET(dma.dma_channel_mask),
         ACPI_RS_OFFSET(data.dma.channel_count)}
 };
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_fixed_dma
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = {
+       {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_DMA,
+        ACPI_RS_SIZE(struct acpi_resource_fixed_dma),
+        ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_dma)},
+
+       {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_DMA,
+        sizeof(struct aml_resource_fixed_dma),
+        0},
+
+       /*
+        * These fields are contiguous in both the source and destination:
+        * request_lines
+        * Channels
+        */
+
+       {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_dma.request_lines),
+        AML_OFFSET(fixed_dma.request_lines),
+        2},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_dma.width),
+        AML_OFFSET(fixed_dma.width),
+        1},
+
+};
index 1bfcef736c5079695dd871d4490ae34bb612600b..9be129f5d6f4ec431469a4bebf76a6f0b900df9a 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,8 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
        struct acpi_resource **resource_ptr =
            ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context);
        struct acpi_resource *resource;
+       union aml_resource *aml_resource;
+       struct acpi_rsconvert_info *conversion_table;
        acpi_status status;
 
        ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources);
@@ -84,14 +86,37 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
                              "Misaligned resource pointer %p", resource));
        }
 
+       /* Get the appropriate conversion info table */
+
+       aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
+       if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) {
+               if (aml_resource->common_serial_bus.type >
+                   AML_RESOURCE_MAX_SERIALBUSTYPE) {
+                       conversion_table = NULL;
+               } else {
+                       /* This is an I2C, SPI, or UART serial_bus descriptor */
+
+                       conversion_table =
+                           acpi_gbl_convert_resource_serial_bus_dispatch
+                           [aml_resource->common_serial_bus.type];
+               }
+       } else {
+               conversion_table =
+                   acpi_gbl_get_resource_dispatch[resource_index];
+       }
+
+       if (!conversion_table) {
+               ACPI_ERROR((AE_INFO,
+                           "Invalid/unsupported resource descriptor: Type 0x%2.2X",
+                           resource_index));
+               return (AE_AML_INVALID_RESOURCE_TYPE);
+       }
+
        /* Convert the AML byte stream resource to a local resource struct */
 
        status =
-           acpi_rs_convert_aml_to_resource(resource,
-                                           ACPI_CAST_PTR(union aml_resource,
-                                                         aml),
-                                           acpi_gbl_get_resource_dispatch
-                                           [resource_index]);
+           acpi_rs_convert_aml_to_resource(resource, aml_resource,
+                                           conversion_table);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
                                "Could not convert AML resource (Type 0x%X)",
@@ -106,7 +131,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
 
        /* Point to the next structure in the output buffer */
 
-       *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length);
+       *resource_ptr = ACPI_NEXT_RESOURCE(resource);
        return_ACPI_STATUS(AE_OK);
 }
 
@@ -135,6 +160,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
 {
        u8 *aml = output_buffer;
        u8 *end_aml = output_buffer + aml_size_needed;
+       struct acpi_rsconvert_info *conversion_table;
        acpi_status status;
 
        ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml);
@@ -154,11 +180,34 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
 
                /* Perform the conversion */
 
-               status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union
-                                                                                aml_resource,
-                                                                                aml),
-                                                        acpi_gbl_set_resource_dispatch
-                                                        [resource->type]);
+               if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+                       if (resource->data.common_serial_bus.type >
+                           AML_RESOURCE_MAX_SERIALBUSTYPE) {
+                               conversion_table = NULL;
+                       } else {
+                               /* This is an I2C, SPI, or UART serial_bus descriptor */
+
+                               conversion_table =
+                                   acpi_gbl_convert_resource_serial_bus_dispatch
+                                   [resource->data.common_serial_bus.type];
+                       }
+               } else {
+                       conversion_table =
+                           acpi_gbl_set_resource_dispatch[resource->type];
+               }
+
+               if (!conversion_table) {
+                       ACPI_ERROR((AE_INFO,
+                                   "Invalid/unsupported resource descriptor: Type 0x%2.2X",
+                                   resource->type));
+                       return (AE_AML_INVALID_RESOURCE_TYPE);
+               }
+
+               status = acpi_rs_convert_resource_to_aml(resource,
+                                                        ACPI_CAST_PTR(union
+                                                                      aml_resource,
+                                                                      aml),
+                                                        conversion_table);
                if (ACPI_FAILURE(status)) {
                        ACPI_EXCEPTION((AE_INFO, status,
                                        "Could not convert resource (type 0x%X) to AML",
@@ -192,9 +241,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
 
                /* Point to the next input resource descriptor */
 
-               resource =
-                   ACPI_ADD_PTR(struct acpi_resource, resource,
-                                resource->length);
+               resource = ACPI_NEXT_RESOURCE(resource);
        }
 
        /* Completed buffer, but did not find an end_tag resource descriptor */
index 7cc6d8625f1e66d488b3e8c0da0c885e2483db42..4fd611ad02b48d9d706cfe886d347c345f2bbdda 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 410264b22a296011108454e353b21dbaaf646b2c..8073b371cc7cd32b44a4cab6dba88e3ae19b149f 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -83,6 +83,10 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
 
        ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
 
+       if (!info) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
        if (((acpi_size) resource) & 0x3) {
 
                /* Each internal resource struct is expected to be 32-bit aligned */
@@ -101,7 +105,6 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
         * table length (# of table entries)
         */
        count = INIT_TABLE_LENGTH(info);
-
        while (count) {
                /*
                 * Source is the external AML byte stream buffer,
@@ -145,6 +148,14 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
                            ((ACPI_GET8(source) >> info->value) & 0x03);
                        break;
 
+               case ACPI_RSC_3BITFLAG:
+                       /*
+                        * Mask and shift the flag bits
+                        */
+                       ACPI_SET8(destination) = (u8)
+                           ((ACPI_GET8(source) >> info->value) & 0x07);
+                       break;
+
                case ACPI_RSC_COUNT:
 
                        item_count = ACPI_GET8(source);
@@ -163,6 +174,69 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
                            (info->value * (item_count - 1));
                        break;
 
+               case ACPI_RSC_COUNT_GPIO_PIN:
+
+                       target = ACPI_ADD_PTR(void, aml, info->value);
+                       item_count = ACPI_GET16(target) - ACPI_GET16(source);
+
+                       resource->length = resource->length + item_count;
+                       item_count = item_count / 2;
+                       ACPI_SET16(destination) = item_count;
+                       break;
+
+               case ACPI_RSC_COUNT_GPIO_VEN:
+
+                       item_count = ACPI_GET8(source);
+                       ACPI_SET8(destination) = (u8)item_count;
+
+                       resource->length = resource->length +
+                           (info->value * item_count);
+                       break;
+
+               case ACPI_RSC_COUNT_GPIO_RES:
+
+                       /*
+                        * Vendor data is optional (length/offset may both be zero)
+                        * Examine vendor data length field first
+                        */
+                       target = ACPI_ADD_PTR(void, aml, (info->value + 2));
+                       if (ACPI_GET16(target)) {
+
+                               /* Use vendor offset to get resource source length */
+
+                               target = ACPI_ADD_PTR(void, aml, info->value);
+                               item_count =
+                                   ACPI_GET16(target) - ACPI_GET16(source);
+                       } else {
+                               /* No vendor data to worry about */
+
+                               item_count = aml->large_header.resource_length +
+                                   sizeof(struct aml_resource_large_header) -
+                                   ACPI_GET16(source);
+                       }
+
+                       resource->length = resource->length + item_count;
+                       ACPI_SET16(destination) = item_count;
+                       break;
+
+               case ACPI_RSC_COUNT_SERIAL_VEN:
+
+                       item_count = ACPI_GET16(source) - info->value;
+
+                       resource->length = resource->length + item_count;
+                       ACPI_SET16(destination) = item_count;
+                       break;
+
+               case ACPI_RSC_COUNT_SERIAL_RES:
+
+                       item_count = (aml_resource_length +
+                                     sizeof(struct aml_resource_large_header))
+                           - ACPI_GET16(source) - info->value;
+
+                       resource->length = resource->length + item_count;
+                       ACPI_SET16(destination) = item_count;
+                       break;
+
                case ACPI_RSC_LENGTH:
 
                        resource->length = resource->length + info->value;
@@ -183,6 +257,72 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
                                          info->opcode);
                        break;
 
+               case ACPI_RSC_MOVE_GPIO_PIN:
+
+                       /* Generate and set the PIN data pointer */
+
+                       target = (char *)ACPI_ADD_PTR(void, resource,
+                                                     (resource->length -
+                                                      item_count * 2));
+                       *(u16 **)destination = ACPI_CAST_PTR(u16, target);
+
+                       /* Copy the PIN data */
+
+                       source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
+                       acpi_rs_move_data(target, source, item_count,
+                                         info->opcode);
+                       break;
+
+               case ACPI_RSC_MOVE_GPIO_RES:
+
+                       /* Generate and set the resource_source string pointer */
+
+                       target = (char *)ACPI_ADD_PTR(void, resource,
+                                                     (resource->length -
+                                                      item_count));
+                       *(u8 **)destination = ACPI_CAST_PTR(u8, target);
+
+                       /* Copy the resource_source string */
+
+                       source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
+                       acpi_rs_move_data(target, source, item_count,
+                                         info->opcode);
+                       break;
+
+               case ACPI_RSC_MOVE_SERIAL_VEN:
+
+                       /* Generate and set the Vendor Data pointer */
+
+                       target = (char *)ACPI_ADD_PTR(void, resource,
+                                                     (resource->length -
+                                                      item_count));
+                       *(u8 **)destination = ACPI_CAST_PTR(u8, target);
+
+                       /* Copy the Vendor Data */
+
+                       source = ACPI_ADD_PTR(void, aml, info->value);
+                       acpi_rs_move_data(target, source, item_count,
+                                         info->opcode);
+                       break;
+
+               case ACPI_RSC_MOVE_SERIAL_RES:
+
+                       /* Generate and set the resource_source string pointer */
+
+                       target = (char *)ACPI_ADD_PTR(void, resource,
+                                                     (resource->length -
+                                                      item_count));
+                       *(u8 **)destination = ACPI_CAST_PTR(u8, target);
+
+                       /* Copy the resource_source string */
+
+                       source =
+                           ACPI_ADD_PTR(void, aml,
+                                        (ACPI_GET16(source) + info->value));
+                       acpi_rs_move_data(target, source, item_count,
+                                         info->opcode);
+                       break;
+
                case ACPI_RSC_SET8:
 
                        ACPI_MEMSET(destination, info->aml_offset, info->value);
@@ -219,13 +359,18 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
                         * Optional resource_source (Index and String). This is the more
                         * complicated case used by the Interrupt() macro
                         */
-                       target =
-                           ACPI_ADD_PTR(char, resource,
-                                        info->aml_offset + (item_count * 4));
+                       target = ACPI_ADD_PTR(char, resource,
+                                             info->aml_offset +
+                                             (item_count * 4));
 
                        resource->length +=
                            acpi_rs_get_resource_source(aml_resource_length,
-                                                       (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target);
+                                                       (acpi_rs_length)
+                                                       (((item_count -
+                                                          1) * sizeof(u32)) +
+                                                        info->value),
+                                                       destination, aml,
+                                                       target);
                        break;
 
                case ACPI_RSC_BITMASK:
@@ -327,6 +472,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
 {
        void *source = NULL;
        void *destination;
+       char *target;
        acpi_rsdesc_size aml_length = 0;
        u8 count;
        u16 temp16 = 0;
@@ -334,6 +480,10 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
 
        ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml);
 
+       if (!info) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
        /*
         * First table entry must be ACPI_RSC_INITxxx and must contain the
         * table length (# of table entries)
@@ -383,6 +533,14 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
                            ((ACPI_GET8(source) & 0x03) << info->value);
                        break;
 
+               case ACPI_RSC_3BITFLAG:
+                       /*
+                        * Mask and shift the flag bits
+                        */
+                       ACPI_SET8(destination) |= (u8)
+                           ((ACPI_GET8(source) & 0x07) << info->value);
+                       break;
+
                case ACPI_RSC_COUNT:
 
                        item_count = ACPI_GET8(source);
@@ -400,6 +558,63 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
                        acpi_rs_set_resource_length(aml_length, aml);
                        break;
 
+               case ACPI_RSC_COUNT_GPIO_PIN:
+
+                       item_count = ACPI_GET16(source);
+                       ACPI_SET16(destination) = (u16)aml_length;
+
+                       aml_length = (u16)(aml_length + item_count * 2);
+                       target = ACPI_ADD_PTR(void, aml, info->value);
+                       ACPI_SET16(target) = (u16)aml_length;
+                       acpi_rs_set_resource_length(aml_length, aml);
+                       break;
+
+               case ACPI_RSC_COUNT_GPIO_VEN:
+
+                       item_count = ACPI_GET16(source);
+                       ACPI_SET16(destination) = (u16)item_count;
+
+                       aml_length =
+                           (u16)(aml_length + (info->value * item_count));
+                       acpi_rs_set_resource_length(aml_length, aml);
+                       break;
+
+               case ACPI_RSC_COUNT_GPIO_RES:
+
+                       /* Set resource source string length */
+
+                       item_count = ACPI_GET16(source);
+                       ACPI_SET16(destination) = (u16)aml_length;
+
+                       /* Compute offset for the Vendor Data */
+
+                       aml_length = (u16)(aml_length + item_count);
+                       target = ACPI_ADD_PTR(void, aml, info->value);
+
+                       /* Set vendor offset only if there is vendor data */
+
+                       if (resource->data.gpio.vendor_length) {
+                               ACPI_SET16(target) = (u16)aml_length;
+                       }
+
+                       acpi_rs_set_resource_length(aml_length, aml);
+                       break;
+
+               case ACPI_RSC_COUNT_SERIAL_VEN:
+
+                       item_count = ACPI_GET16(source);
+                       ACPI_SET16(destination) = item_count + info->value;
+                       aml_length = (u16)(aml_length + item_count);
+                       acpi_rs_set_resource_length(aml_length, aml);
+                       break;
+
+               case ACPI_RSC_COUNT_SERIAL_RES:
+
+                       item_count = ACPI_GET16(source);
+                       aml_length = (u16)(aml_length + item_count);
+                       acpi_rs_set_resource_length(aml_length, aml);
+                       break;
+
                case ACPI_RSC_LENGTH:
 
                        acpi_rs_set_resource_length(info->value, aml);
@@ -417,6 +632,48 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
                                          info->opcode);
                        break;
 
+               case ACPI_RSC_MOVE_GPIO_PIN:
+
+                       destination = (char *)ACPI_ADD_PTR(void, aml,
+                                                          ACPI_GET16
+                                                          (destination));
+                       source = *(u16 **)source;
+                       acpi_rs_move_data(destination, source, item_count,
+                                         info->opcode);
+                       break;
+
+               case ACPI_RSC_MOVE_GPIO_RES:
+
+                       /* Used for both resource_source string and vendor_data */
+
+                       destination = (char *)ACPI_ADD_PTR(void, aml,
+                                                          ACPI_GET16
+                                                          (destination));
+                       source = *(u8 **)source;
+                       acpi_rs_move_data(destination, source, item_count,
+                                         info->opcode);
+                       break;
+
+               case ACPI_RSC_MOVE_SERIAL_VEN:
+
+                       destination = (char *)ACPI_ADD_PTR(void, aml,
+                                                          (aml_length -
+                                                           item_count));
+                       source = *(u8 **)source;
+                       acpi_rs_move_data(destination, source, item_count,
+                                         info->opcode);
+                       break;
+
+               case ACPI_RSC_MOVE_SERIAL_RES:
+
+                       destination = (char *)ACPI_ADD_PTR(void, aml,
+                                                          (aml_length -
+                                                           item_count));
+                       source = *(u8 **)source;
+                       acpi_rs_move_data(destination, source, item_count,
+                                         info->opcode);
+                       break;
+
                case ACPI_RSC_ADDRESS:
 
                        /* Set the Resource Type, General Flags, and Type-Specific Flags */
diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c
new file mode 100644 (file)
index 0000000..9aa5e68
--- /dev/null
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ *
+ * Module Name: rsserial - GPIO/serial_bus resource descriptors
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acresrc.h"
+
+#define _COMPONENT          ACPI_RESOURCES
+ACPI_MODULE_NAME("rsserial")
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_gpio
+ *
+ ******************************************************************************/
+struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = {
+       {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO,
+        ACPI_RS_SIZE(struct acpi_resource_gpio),
+        ACPI_RSC_TABLE_SIZE(acpi_rs_convert_gpio)},
+
+       {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GPIO,
+        sizeof(struct aml_resource_gpio),
+        0},
+
+       /*
+        * These fields are contiguous in both the source and destination:
+        * revision_id
+        * connection_type
+        */
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.revision_id),
+        AML_OFFSET(gpio.revision_id),
+        2},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.producer_consumer),
+        AML_OFFSET(gpio.flags),
+        0},
+
+       {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable),
+        AML_OFFSET(gpio.int_flags),
+        3},
+
+       {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.io_restriction),
+        AML_OFFSET(gpio.int_flags),
+        0},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.triggering),
+        AML_OFFSET(gpio.int_flags),
+        0},
+
+       {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.polarity),
+        AML_OFFSET(gpio.int_flags),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.pin_config),
+        AML_OFFSET(gpio.pin_config),
+        1},
+
+       /*
+        * These fields are contiguous in both the source and destination:
+        * drive_strength
+        * debounce_timeout
+        */
+       {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.gpio.drive_strength),
+        AML_OFFSET(gpio.drive_strength),
+        2},
+
+       /* Pin Table */
+
+       {ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET(data.gpio.pin_table_length),
+        AML_OFFSET(gpio.pin_table_offset),
+        AML_OFFSET(gpio.res_source_offset)},
+
+       {ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET(data.gpio.pin_table),
+        AML_OFFSET(gpio.pin_table_offset),
+        0},
+
+       /* Resource Source */
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.resource_source.index),
+        AML_OFFSET(gpio.res_source_index),
+        1},
+
+       {ACPI_RSC_COUNT_GPIO_RES,
+        ACPI_RS_OFFSET(data.gpio.resource_source.string_length),
+        AML_OFFSET(gpio.res_source_offset),
+        AML_OFFSET(gpio.vendor_offset)},
+
+       {ACPI_RSC_MOVE_GPIO_RES,
+        ACPI_RS_OFFSET(data.gpio.resource_source.string_ptr),
+        AML_OFFSET(gpio.res_source_offset),
+        0},
+
+       /* Vendor Data */
+
+       {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET(data.gpio.vendor_length),
+        AML_OFFSET(gpio.vendor_length),
+        1},
+
+       {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET(data.gpio.vendor_data),
+        AML_OFFSET(gpio.vendor_offset),
+        0},
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_i2c_serial_bus
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = {
+       {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
+        ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus),
+        ACPI_RSC_TABLE_SIZE(acpi_rs_convert_i2c_serial_bus)},
+
+       {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS,
+        sizeof(struct aml_resource_i2c_serialbus),
+        0},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id),
+        AML_OFFSET(common_serial_bus.revision_id),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type),
+        AML_OFFSET(common_serial_bus.type),
+        1},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode),
+        AML_OFFSET(common_serial_bus.flags),
+        0},
+
+       {ACPI_RSC_1BITFLAG,
+        ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer),
+        AML_OFFSET(common_serial_bus.flags),
+        1},
+
+       {ACPI_RSC_MOVE8,
+        ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
+        AML_OFFSET(common_serial_bus.type_revision_id),
+        1},
+
+       {ACPI_RSC_MOVE16,
+        ACPI_RS_OFFSET(data.common_serial_bus.type_data_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        1},
+
+       /* Vendor data */
+
+       {ACPI_RSC_COUNT_SERIAL_VEN,
+        ACPI_RS_OFFSET(data.common_serial_bus.vendor_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        AML_RESOURCE_I2C_MIN_DATA_LEN},
+
+       {ACPI_RSC_MOVE_SERIAL_VEN,
+        ACPI_RS_OFFSET(data.common_serial_bus.vendor_data),
+        0,
+        sizeof(struct aml_resource_i2c_serialbus)},
+
+       /* Resource Source */
+
+       {ACPI_RSC_MOVE8,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index),
+        AML_OFFSET(common_serial_bus.res_source_index),
+        1},
+
+       {ACPI_RSC_COUNT_SERIAL_RES,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        sizeof(struct aml_resource_common_serialbus)},
+
+       {ACPI_RSC_MOVE_SERIAL_RES,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        sizeof(struct aml_resource_common_serialbus)},
+
+       /* I2C bus type specific */
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.i2c_serial_bus.access_mode),
+        AML_OFFSET(i2c_serial_bus.type_specific_flags),
+        0},
+
+       {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.i2c_serial_bus.connection_speed),
+        AML_OFFSET(i2c_serial_bus.connection_speed),
+        1},
+
+       {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.i2c_serial_bus.slave_address),
+        AML_OFFSET(i2c_serial_bus.slave_address),
+        1},
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_spi_serial_bus
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = {
+       {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
+        ACPI_RS_SIZE(struct acpi_resource_spi_serialbus),
+        ACPI_RSC_TABLE_SIZE(acpi_rs_convert_spi_serial_bus)},
+
+       {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS,
+        sizeof(struct aml_resource_spi_serialbus),
+        0},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id),
+        AML_OFFSET(common_serial_bus.revision_id),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type),
+        AML_OFFSET(common_serial_bus.type),
+        1},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode),
+        AML_OFFSET(common_serial_bus.flags),
+        0},
+
+       {ACPI_RSC_1BITFLAG,
+        ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer),
+        AML_OFFSET(common_serial_bus.flags),
+        1},
+
+       {ACPI_RSC_MOVE8,
+        ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
+        AML_OFFSET(common_serial_bus.type_revision_id),
+        1},
+
+       {ACPI_RSC_MOVE16,
+        ACPI_RS_OFFSET(data.common_serial_bus.type_data_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        1},
+
+       /* Vendor data */
+
+       {ACPI_RSC_COUNT_SERIAL_VEN,
+        ACPI_RS_OFFSET(data.common_serial_bus.vendor_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        AML_RESOURCE_SPI_MIN_DATA_LEN},
+
+       {ACPI_RSC_MOVE_SERIAL_VEN,
+        ACPI_RS_OFFSET(data.common_serial_bus.vendor_data),
+        0,
+        sizeof(struct aml_resource_spi_serialbus)},
+
+       /* Resource Source */
+
+       {ACPI_RSC_MOVE8,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index),
+        AML_OFFSET(common_serial_bus.res_source_index),
+        1},
+
+       {ACPI_RSC_COUNT_SERIAL_RES,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        sizeof(struct aml_resource_common_serialbus)},
+
+       {ACPI_RSC_MOVE_SERIAL_RES,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        sizeof(struct aml_resource_common_serialbus)},
+
+       /* Spi bus type specific  */
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.spi_serial_bus.wire_mode),
+        AML_OFFSET(spi_serial_bus.type_specific_flags),
+        0},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.spi_serial_bus.device_polarity),
+        AML_OFFSET(spi_serial_bus.type_specific_flags),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.data_bit_length),
+        AML_OFFSET(spi_serial_bus.data_bit_length),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.clock_phase),
+        AML_OFFSET(spi_serial_bus.clock_phase),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.clock_polarity),
+        AML_OFFSET(spi_serial_bus.clock_polarity),
+        1},
+
+       {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.spi_serial_bus.device_selection),
+        AML_OFFSET(spi_serial_bus.device_selection),
+        1},
+
+       {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.spi_serial_bus.connection_speed),
+        AML_OFFSET(spi_serial_bus.connection_speed),
+        1},
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_uart_serial_bus
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[22] = {
+       {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
+        ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),
+        ACPI_RSC_TABLE_SIZE(acpi_rs_convert_uart_serial_bus)},
+
+       {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS,
+        sizeof(struct aml_resource_uart_serialbus),
+        0},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id),
+        AML_OFFSET(common_serial_bus.revision_id),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type),
+        AML_OFFSET(common_serial_bus.type),
+        1},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode),
+        AML_OFFSET(common_serial_bus.flags),
+        0},
+
+       {ACPI_RSC_1BITFLAG,
+        ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer),
+        AML_OFFSET(common_serial_bus.flags),
+        1},
+
+       {ACPI_RSC_MOVE8,
+        ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
+        AML_OFFSET(common_serial_bus.type_revision_id),
+        1},
+
+       {ACPI_RSC_MOVE16,
+        ACPI_RS_OFFSET(data.common_serial_bus.type_data_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        1},
+
+       /* Vendor data */
+
+       {ACPI_RSC_COUNT_SERIAL_VEN,
+        ACPI_RS_OFFSET(data.common_serial_bus.vendor_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        AML_RESOURCE_UART_MIN_DATA_LEN},
+
+       {ACPI_RSC_MOVE_SERIAL_VEN,
+        ACPI_RS_OFFSET(data.common_serial_bus.vendor_data),
+        0,
+        sizeof(struct aml_resource_uart_serialbus)},
+
+       /* Resource Source */
+
+       {ACPI_RSC_MOVE8,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index),
+        AML_OFFSET(common_serial_bus.res_source_index),
+        1},
+
+       {ACPI_RSC_COUNT_SERIAL_RES,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        sizeof(struct aml_resource_common_serialbus)},
+
+       {ACPI_RSC_MOVE_SERIAL_RES,
+        ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr),
+        AML_OFFSET(common_serial_bus.type_data_length),
+        sizeof(struct aml_resource_common_serialbus)},
+
+       /* Uart bus type specific  */
+
+       {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.flow_control),
+        AML_OFFSET(uart_serial_bus.type_specific_flags),
+        0},
+
+       {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.stop_bits),
+        AML_OFFSET(uart_serial_bus.type_specific_flags),
+        2},
+
+       {ACPI_RSC_3BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.data_bits),
+        AML_OFFSET(uart_serial_bus.type_specific_flags),
+        4},
+
+       {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.endian),
+        AML_OFFSET(uart_serial_bus.type_specific_flags),
+        7},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.uart_serial_bus.parity),
+        AML_OFFSET(uart_serial_bus.parity),
+        1},
+
+       {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.uart_serial_bus.lines_enabled),
+        AML_OFFSET(uart_serial_bus.lines_enabled),
+        1},
+
+       {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.uart_serial_bus.rx_fifo_size),
+        AML_OFFSET(uart_serial_bus.rx_fifo_size),
+        1},
+
+       {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.uart_serial_bus.tx_fifo_size),
+        AML_OFFSET(uart_serial_bus.tx_fifo_size),
+        1},
+
+       {ACPI_RSC_MOVE32,
+        ACPI_RS_OFFSET(data.uart_serial_bus.default_baud_rate),
+        AML_OFFSET(uart_serial_bus.default_baud_rate),
+        1},
+};
index 231811e569399c5b75d2b7ba55be22bf82edbdbb..433a375deb9350e9635b103e3c593d6e7c3838da 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -144,6 +144,9 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
                         * since there are no alignment or endian issues
                         */
                case ACPI_RSC_MOVE8:
+               case ACPI_RSC_MOVE_GPIO_RES:
+               case ACPI_RSC_MOVE_SERIAL_VEN:
+               case ACPI_RSC_MOVE_SERIAL_RES:
                        ACPI_MEMCPY(destination, source, item_count);
                        return;
 
@@ -153,6 +156,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
                         * misaligned memory transfers
                         */
                case ACPI_RSC_MOVE16:
+               case ACPI_RSC_MOVE_GPIO_PIN:
                        ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
                                           &ACPI_CAST_PTR(u16, source)[i]);
                        break;
@@ -588,6 +592,56 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
 }
 #endif                         /*  ACPI_FUTURE_USAGE  */
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_get_aei_method_data
+ *
+ * PARAMETERS:  Node            - Device node
+ *              ret_buffer      - Pointer to a buffer structure for the
+ *                                results
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This function is called to get the _AEI value of an object
+ *              contained in an object specified by the handle passed in
+ *
+ *              If the function fails an appropriate status will be returned
+ *              and the contents of the callers buffer is undefined.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
+                           struct acpi_buffer *ret_buffer)
+{
+       union acpi_operand_object *obj_desc;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(rs_get_aei_method_data);
+
+       /* Parameters guaranteed valid by caller */
+
+       /* Execute the method, no parameters */
+
+       status = acpi_ut_evaluate_object(node, METHOD_NAME__AEI,
+                                        ACPI_BTYPE_BUFFER, &obj_desc);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /*
+        * Make the call to create a resource linked list from the
+        * byte stream buffer that comes back from the _CRS method
+        * execution.
+        */
+       status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
+
+       /* On exit, we must delete the object returned by evaluate_object */
+
+       acpi_ut_remove_reference(obj_desc);
+       return_ACPI_STATUS(status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_rs_get_method_data
index fe86b37b16ce657bd719b68c656ce252581a0452..f58c098c7aeb3fd5f5e35b532fbbd82da6eab42a 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -307,6 +307,46 @@ acpi_set_current_resources(acpi_handle device_handle,
 
 ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_event_resources
+ *
+ * PARAMETERS:  device_handle   - Handle to the device object for the
+ *                                device we are getting resources
+ *              in_buffer       - Pointer to a buffer containing the
+ *                                resources to be set for the device
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This function is called to get the event resources for a
+ *              specific device. The caller must first acquire a handle for
+ *              the desired device. The resource data is passed to the routine
+ *              the buffer pointed to by the in_buffer variable. Uses the
+ *              _AEI method.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_event_resources(acpi_handle device_handle,
+                        struct acpi_buffer *ret_buffer)
+{
+       acpi_status status;
+       struct acpi_namespace_node *node;
+
+       ACPI_FUNCTION_TRACE(acpi_get_event_resources);
+
+       /* Validate parameters then dispatch to internal routine */
+
+       status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       status = acpi_rs_get_aei_method_data(node, ret_buffer);
+       return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_event_resources)
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_resource_to_address64
@@ -486,8 +526,9 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
  *
  * PARAMETERS:  device_handle   - Handle to the device object for the
  *                                device we are querying
- *              Name            - Method name of the resources we want
- *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ *              Name            - Method name of the resources we want.
+ *                                (METHOD_NAME__CRS, METHOD_NAME__PRS, or
+ *                                METHOD_NAME__AEI)
  *              user_function   - Called for each resource
  *              Context         - Passed to user_function
  *
@@ -514,11 +555,12 @@ acpi_walk_resources(acpi_handle device_handle,
 
        if (!device_handle || !user_function || !name ||
            (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
-            !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) {
+            !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) &&
+            !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) {
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       /* Get the _CRS or _PRS resource list */
+       /* Get the _CRS/_PRS/_AEI resource list */
 
        buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
        status = acpi_rs_get_method_data(device_handle, name, &buffer);
index 6f5588e62c0ac24d396288f661fa3a959b52f734..c5d870406f4126adf7ce80ffa0635d175c1a772d 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,14 +63,15 @@ static void acpi_tb_setup_fadt_registers(void);
 
 typedef struct acpi_fadt_info {
        char *name;
-       u8 address64;
-       u8 address32;
-       u8 length;
+       u16 address64;
+       u16 address32;
+       u16 length;
        u8 default_length;
        u8 type;
 
 } acpi_fadt_info;
 
+#define ACPI_FADT_OPTIONAL          0
 #define ACPI_FADT_REQUIRED          1
 #define ACPI_FADT_SEPARATE_LENGTH   2
 
@@ -87,7 +88,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
         ACPI_FADT_OFFSET(pm1b_event_block),
         ACPI_FADT_OFFSET(pm1_event_length),
         ACPI_PM1_REGISTER_WIDTH * 2,   /* Enable + Status register */
-        0},
+        ACPI_FADT_OPTIONAL},
 
        {"Pm1aControlBlock",
         ACPI_FADT_OFFSET(xpm1a_control_block),
@@ -101,7 +102,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
         ACPI_FADT_OFFSET(pm1b_control_block),
         ACPI_FADT_OFFSET(pm1_control_length),
         ACPI_PM1_REGISTER_WIDTH,
-        0},
+        ACPI_FADT_OPTIONAL},
 
        {"Pm2ControlBlock",
         ACPI_FADT_OFFSET(xpm2_control_block),
@@ -139,7 +140,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
 
 typedef struct acpi_fadt_pm_info {
        struct acpi_generic_address *target;
-       u8 source;
+       u16 source;
        u8 register_num;
 
 } acpi_fadt_pm_info;
@@ -253,8 +254,13 @@ void acpi_tb_parse_fadt(u32 table_index)
        acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
                              ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
 
-       acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs,
-                             ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
+       /* If Hardware Reduced flag is set, there is no FACS */
+
+       if (!acpi_gbl_reduced_hardware) {
+               acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.
+                                     Xfacs, ACPI_SIG_FACS,
+                                     ACPI_TABLE_INDEX_FACS);
+       }
 }
 
 /*******************************************************************************
@@ -277,12 +283,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
 {
        /*
         * Check if the FADT is larger than the largest table that we expect
-        * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
+        * (the ACPI 5.0 version). If so, truncate the table, and issue
         * a warning.
         */
        if (length > sizeof(struct acpi_table_fadt)) {
                ACPI_WARNING((AE_INFO,
-                             "FADT (revision %u) is longer than ACPI 2.0 version, "
+                             "FADT (revision %u) is longer than ACPI 5.0 version, "
                              "truncating length %u to %u",
                              table->revision, length,
                              (u32)sizeof(struct acpi_table_fadt)));
@@ -297,6 +303,13 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
        ACPI_MEMCPY(&acpi_gbl_FADT, table,
                    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));
 
+       /* Take a copy of the Hardware Reduced flag */
+
+       acpi_gbl_reduced_hardware = FALSE;
+       if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) {
+               acpi_gbl_reduced_hardware = TRUE;
+       }
+
        /* Convert the local copy of the FADT to the common internal format */
 
        acpi_tb_convert_fadt();
@@ -502,6 +515,12 @@ static void acpi_tb_validate_fadt(void)
                acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
        }
 
+       /* If Hardware Reduced flag is set, we are all done */
+
+       if (acpi_gbl_reduced_hardware) {
+               return;
+       }
+
        /* Examine all of the 64-bit extended address fields (X fields) */
 
        for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
index a55cb2bb5abbfdee7b448ced5baf23bb37c68a4a..4903e36ea75a3f4f24930c43b497626b930d8f0e 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 62365f6075dda417e7204d55105707ef1a64eaf9..1aecf7baa4e0c2f2a0f35c7ebc4ecd8bbbe161c7 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 0f2d395feabadb20e8ce47d88f53ff8d786e2427..09ca39e143373c7dfeb11efc63f01540e62d3edb 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,13 @@ acpi_status acpi_tb_initialize_facs(void)
 {
        acpi_status status;
 
+       /* If Hardware Reduced flag is set, there is no FACS */
+
+       if (acpi_gbl_reduced_hardware) {
+               acpi_gbl_FACS = NULL;
+               return (AE_OK);
+       }
+
        status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
                                         ACPI_CAST_INDIRECT_PTR(struct
                                                                acpi_table_header,
index e7d13f5d3f2da0f77d7b04a71e1118cb2793f7cd..abcc6412c24492129b8bb003963a7f7e826f80fc 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 7eb6c6cc1edf76000d8842edc6a1a36bf261a43b..4258f647ca3d63cb20cf9ce2d0b01701f6d00e11 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
new file mode 100644 (file)
index 0000000..67932ae
--- /dev/null
@@ -0,0 +1,294 @@
+/******************************************************************************
+ *
+ * Module Name: utaddress - op_region address range check
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utaddress")
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_add_address_range
+ *
+ * PARAMETERS:  space_id            - Address space ID
+ *              Address             - op_region start address
+ *              Length              - op_region length
+ *              region_node         - op_region namespace node
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Add the Operation Region address range to the global list.
+ *              The only supported Space IDs are Memory and I/O. Called when
+ *              the op_region address/length operands are fully evaluated.
+ *
+ * MUTEX:       Locks the namespace
+ *
+ * NOTE: Because this interface is only called when an op_region argument
+ * list is evaluated, there cannot be any duplicate region_nodes.
+ * Duplicate Address/Length values are allowed, however, so that multiple
+ * address conflicts can be detected.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ut_add_address_range(acpi_adr_space_type space_id,
+                         acpi_physical_address address,
+                         u32 length, struct acpi_namespace_node *region_node)
+{
+       struct acpi_address_range *range_info;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(ut_add_address_range);
+
+       if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+           (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
+       /* Allocate/init a new info block, add it to the appropriate list */
+
+       range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));
+       if (!range_info) {
+               return_ACPI_STATUS(AE_NO_MEMORY);
+       }
+
+       range_info->start_address = address;
+       range_info->end_address = (address + length - 1);
+       range_info->region_node = region_node;
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               ACPI_FREE(range_info);
+               return_ACPI_STATUS(status);
+       }
+
+       range_info->next = acpi_gbl_address_range_list[space_id];
+       acpi_gbl_address_range_list[space_id] = range_info;
+
+       ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+                         "\nAdded [%4.4s] address range: 0x%p-0x%p\n",
+                         acpi_ut_get_node_name(range_info->region_node),
+                         ACPI_CAST_PTR(void, address),
+                         ACPI_CAST_PTR(void, range_info->end_address)));
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+       return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_remove_address_range
+ *
+ * PARAMETERS:  space_id            - Address space ID
+ *              region_node         - op_region namespace node
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Remove the Operation Region from the global list. The only
+ *              supported Space IDs are Memory and I/O. Called when an
+ *              op_region is deleted.
+ *
+ * MUTEX:       Assumes the namespace is locked
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_remove_address_range(acpi_adr_space_type space_id,
+                            struct acpi_namespace_node *region_node)
+{
+       struct acpi_address_range *range_info;
+       struct acpi_address_range *prev;
+
+       ACPI_FUNCTION_TRACE(ut_remove_address_range);
+
+       if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+           (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+               return_VOID;
+       }
+
+       /* Get the appropriate list head and check the list */
+
+       range_info = prev = acpi_gbl_address_range_list[space_id];
+       while (range_info) {
+               if (range_info->region_node == region_node) {
+                       if (range_info == prev) {       /* Found at list head */
+                               acpi_gbl_address_range_list[space_id] =
+                                   range_info->next;
+                       } else {
+                               prev->next = range_info->next;
+                       }
+
+                       ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+                                         "\nRemoved [%4.4s] address range: 0x%p-0x%p\n",
+                                         acpi_ut_get_node_name(range_info->
+                                                               region_node),
+                                         ACPI_CAST_PTR(void,
+                                                       range_info->
+                                                       start_address),
+                                         ACPI_CAST_PTR(void,
+                                                       range_info->
+                                                       end_address)));
+
+                       ACPI_FREE(range_info);
+                       return_VOID;
+               }
+
+               prev = range_info;
+               range_info = range_info->next;
+       }
+
+       return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_check_address_range
+ *
+ * PARAMETERS:  space_id            - Address space ID
+ *              Address             - Start address
+ *              Length              - Length of address range
+ *              Warn                - TRUE if warning on overlap desired
+ *
+ * RETURN:      Count of the number of conflicts detected. Zero is always
+ *              returned for Space IDs other than Memory or I/O.
+ *
+ * DESCRIPTION: Check if the input address range overlaps any of the
+ *              ASL operation region address ranges. The only supported
+ *              Space IDs are Memory and I/O.
+ *
+ * MUTEX:       Assumes the namespace is locked.
+ *
+ ******************************************************************************/
+
+u32
+acpi_ut_check_address_range(acpi_adr_space_type space_id,
+                           acpi_physical_address address, u32 length, u8 warn)
+{
+       struct acpi_address_range *range_info;
+       acpi_physical_address end_address;
+       char *pathname;
+       u32 overlap_count = 0;
+
+       ACPI_FUNCTION_TRACE(ut_check_address_range);
+
+       if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+           (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+               return_UINT32(0);
+       }
+
+       range_info = acpi_gbl_address_range_list[space_id];
+       end_address = address + length - 1;
+
+       /* Check entire list for all possible conflicts */
+
+       while (range_info) {
+               /*
+                * Check if the requested Address/Length overlaps this address_range.
+                * Four cases to consider:
+                *
+                * 1) Input address/length is contained completely in the address range
+                * 2) Input address/length overlaps range at the range start
+                * 3) Input address/length overlaps range at the range end
+                * 4) Input address/length completely encompasses the range
+                */
+               if ((address <= range_info->end_address) &&
+                   (end_address >= range_info->start_address)) {
+
+                       /* Found an address range overlap */
+
+                       overlap_count++;
+                       if (warn) {     /* Optional warning message */
+                               pathname =
+                                   acpi_ns_get_external_pathname(range_info->
+                                                                 region_node);
+
+                               ACPI_WARNING((AE_INFO,
+                                             "0x%p-0x%p %s conflicts with Region %s %d",
+                                             ACPI_CAST_PTR(void, address),
+                                             ACPI_CAST_PTR(void, end_address),
+                                             acpi_ut_get_region_name(space_id),
+                                             pathname, overlap_count));
+                               ACPI_FREE(pathname);
+                       }
+               }
+
+               range_info = range_info->next;
+       }
+
+       return_UINT32(overlap_count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_delete_address_lists
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Delete all global address range lists (called during
+ *              subsystem shutdown).
+ *
+ ******************************************************************************/
+
+void acpi_ut_delete_address_lists(void)
+{
+       struct acpi_address_range *next;
+       struct acpi_address_range *range_info;
+       int i;
+
+       /* Delete all elements in all address range lists */
+
+       for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
+               next = acpi_gbl_address_range_list[i];
+
+               while (next) {
+                       range_info = next;
+                       next = range_info->next;
+                       ACPI_FREE(range_info);
+               }
+
+               acpi_gbl_address_range_list[i] = NULL;
+       }
+}
index 0a697351cf6974474852370b843880ee3872ab7d..9982d2ea66fbbc382a4b6daaf64d1bdcf647b678 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index aded299a2fa842210a7ee9c616ff321573f8c5c4..3317c0a406ee539381e5f80f93983c6653f8697f 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index a1f8d7509e664f256bb03153319699915fc0bfef..a0998a886318dba8f286f93e393fc2994848d2b5 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 8b087e2d64f4d9e331be57092e3c36395b58db8c..d42ede5260c77cac6f9b947ec625c252ebe027bc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -171,7 +171,9 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
        "SMBus",
        "SystemCMOS",
        "PCIBARTarget",
-       "IPMI"
+       "IPMI",
+       "GeneralPurposeIo",
+       "GenericSerialBus"
 };
 
 char *acpi_ut_get_region_name(u8 space_id)
index 31f5a7832ef135e94659179fbec6a927098b5fa3..2a6c3e183697ac68a6c6bca589116c20f8bf4520 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -215,11 +215,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
                                  "***** Region %p\n", object));
 
-               /* Invalidate the region address/length via the host OS */
-
-               acpi_os_invalidate_address(object->region.space_id,
-                                         object->region.address,
-                                         (acpi_size) object->region.length);
+               /*
+                * Update address_range list. However, only permanent regions
+                * are installed in this list. (Not created within a method)
+                */
+               if (!(object->region.node->flags & ANOBJ_TEMPORARY)) {
+                       acpi_ut_remove_address_range(object->region.space_id,
+                                                    object->region.node);
+               }
 
                second_desc = acpi_ns_get_secondary_object(object);
                if (second_desc) {
index 18f73c9d10bce26a71a469569a868c72bc75fabd..479f32b33415722742c10c7b125cebd682b4b054 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ffba0a39c3e8598d1aeceecd1a007ddf974213cd..4153584cf526a81bb3ab99bd3f5f59a37fb19f42 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -264,6 +264,12 @@ acpi_status acpi_ut_init_globals(void)
                return_ACPI_STATUS(status);
        }
 
+       /* Address Range lists */
+
+       for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
+               acpi_gbl_address_range_list[i] = NULL;
+       }
+
        /* Mutex locked flags */
 
        for (i = 0; i < ACPI_NUM_MUTEX; i++) {
index b679ea693545db6fd16703268c9cbd6354cecfcd..c92eb1d937859d673ff1c08293ef4ad94f861328 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 191b6828cce99d300a20fd01d559b21628a0189c..8359c0c5dc9830456ec2605f2bcc9114cd4a25cc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,6 +92,7 @@ static void acpi_ut_terminate(void)
                gpe_xrupt_info = next_gpe_xrupt_info;
        }
 
+       acpi_ut_delete_address_lists();
        return_VOID;
 }
 
index f6bb75c6faf5ea4a653569e9653e3094a07b7056..155fd786d0f2a45b6174f210b621fee6b6b7436d 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ce481da9bb451858da374fdee0e5f271196ab335..2491a552b0e69eeba847364f3ab643505f5afb09 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index c33a852d4f42a5d9b9113840bcd918680a3836b8..86f19db74e0549949c9685e391166b282523b949 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 7d797e2baecd11996ae49525bc99e79f1fbbd5e9..43174df3312100f0a5e9d4b58dfde1679c9a1fd3 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -293,14 +293,10 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
 
 acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
 {
-       acpi_thread_id this_thread_id;
-
        ACPI_FUNCTION_NAME(ut_release_mutex);
 
-       this_thread_id = acpi_os_get_thread_id();
-
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
-                         (u32)this_thread_id,
+                         (u32)acpi_os_get_thread_id(),
                          acpi_ut_get_mutex_name(mutex_id)));
 
        if (mutex_id > ACPI_MAX_MUTEX) {
@@ -329,7 +325,8 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
                 * the ACPI subsystem code.
                 */
                for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
-                       if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
+                       if (acpi_gbl_mutex_info[i].thread_id ==
+                           acpi_os_get_thread_id()) {
                                if (i == mutex_id) {
                                        continue;
                                }
index 188340a017b4036422e900ccac69d44f44754780..b112744fc9ae3018dd591b5904f94b8059ea6b10 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 1fb10cb8f11dfdaa660c0bf4ee9095a79986bd55..2360cf70c18ccdcb810ccc08c2c520d3bcaf3948 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 6ffd3a8bdaa5dadbdac41ede3dd0f6c95db8c0f4..9d441ea703052545c2b9f98f122de42a6acfb26e 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
 
 #include <acpi/acpi.h>
 #include "accommon.h"
-#include "amlresrc.h"
+#include "acresrc.h"
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utresrc")
@@ -154,6 +154,138 @@ const char *acpi_gbl_typ_decode[] = {
        "TypeF"
 };
 
+const char *acpi_gbl_ppc_decode[] = {
+       "PullDefault",
+       "PullUp",
+       "PullDown",
+       "PullNone"
+};
+
+const char *acpi_gbl_ior_decode[] = {
+       "IoRestrictionNone",
+       "IoRestrictionInputOnly",
+       "IoRestrictionOutputOnly",
+       "IoRestrictionNoneAndPreserve"
+};
+
+const char *acpi_gbl_dts_decode[] = {
+       "Width8bit",
+       "Width16bit",
+       "Width32bit",
+       "Width64bit",
+       "Width128bit",
+       "Width256bit",
+};
+
+/* GPIO connection type */
+
+const char *acpi_gbl_ct_decode[] = {
+       "Interrupt",
+       "I/O"
+};
+
+/* Serial bus type */
+
+const char *acpi_gbl_sbt_decode[] = {
+       "/* UNKNOWN serial bus type */",
+       "I2C",
+       "SPI",
+       "UART"
+};
+
+/* I2C serial bus access mode */
+
+const char *acpi_gbl_am_decode[] = {
+       "AddressingMode7Bit",
+       "AddressingMode10Bit"
+};
+
+/* I2C serial bus slave mode */
+
+const char *acpi_gbl_sm_decode[] = {
+       "ControllerInitiated",
+       "DeviceInitiated"
+};
+
+/* SPI serial bus wire mode */
+
+const char *acpi_gbl_wm_decode[] = {
+       "FourWireMode",
+       "ThreeWireMode"
+};
+
+/* SPI serial clock phase */
+
+const char *acpi_gbl_cph_decode[] = {
+       "ClockPhaseFirst",
+       "ClockPhaseSecond"
+};
+
+/* SPI serial bus clock polarity */
+
+const char *acpi_gbl_cpo_decode[] = {
+       "ClockPolarityLow",
+       "ClockPolarityHigh"
+};
+
+/* SPI serial bus device polarity */
+
+const char *acpi_gbl_dp_decode[] = {
+       "PolarityLow",
+       "PolarityHigh"
+};
+
+/* UART serial bus endian */
+
+const char *acpi_gbl_ed_decode[] = {
+       "LittleEndian",
+       "BigEndian"
+};
+
+/* UART serial bus bits per byte */
+
+const char *acpi_gbl_bpb_decode[] = {
+       "DataBitsFive",
+       "DataBitsSix",
+       "DataBitsSeven",
+       "DataBitsEight",
+       "DataBitsNine",
+       "/* UNKNOWN Bits per byte */",
+       "/* UNKNOWN Bits per byte */",
+       "/* UNKNOWN Bits per byte */"
+};
+
+/* UART serial bus stop bits */
+
+const char *acpi_gbl_sb_decode[] = {
+       "StopBitsNone",
+       "StopBitsOne",
+       "StopBitsOnePlusHalf",
+       "StopBitsTwo"
+};
+
+/* UART serial bus flow control */
+
+const char *acpi_gbl_fc_decode[] = {
+       "FlowControlNone",
+       "FlowControlHardware",
+       "FlowControlXON",
+       "/* UNKNOWN flow control keyword */"
+};
+
+/* UART serial bus parity type */
+
+const char *acpi_gbl_pt_decode[] = {
+       "ParityTypeNone",
+       "ParityTypeEven",
+       "ParityTypeOdd",
+       "ParityTypeMark",
+       "ParityTypeSpace",
+       "/* UNKNOWN parity keyword */",
+       "/* UNKNOWN parity keyword */",
+       "/* UNKNOWN parity keyword */"
+};
+
 #endif
 
 /*
@@ -173,7 +305,7 @@ const u8 acpi_gbl_resource_aml_sizes[] = {
        ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
        ACPI_AML_SIZE_SMALL(struct aml_resource_io),
        ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
-       0,
+       ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
        0,
        0,
        0,
@@ -193,7 +325,17 @@ const u8 acpi_gbl_resource_aml_sizes[] = {
        ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
        ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
        ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
-       ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64)
+       ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
+       ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
+       0,
+       ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
+};
+
+const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
+       0,
+       ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
+       ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
+       ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
 };
 
 /*
@@ -209,35 +351,49 @@ static const u8 acpi_gbl_resource_types[] = {
        0,
        0,
        0,
-       ACPI_SMALL_VARIABLE_LENGTH,
-       ACPI_FIXED_LENGTH,
-       ACPI_SMALL_VARIABLE_LENGTH,
-       ACPI_FIXED_LENGTH,
-       ACPI_FIXED_LENGTH,
-       ACPI_FIXED_LENGTH,
-       0,
+       ACPI_SMALL_VARIABLE_LENGTH,     /* 04 IRQ */
+       ACPI_FIXED_LENGTH,      /* 05 DMA */
+       ACPI_SMALL_VARIABLE_LENGTH,     /* 06 start_dependent_functions */
+       ACPI_FIXED_LENGTH,      /* 07 end_dependent_functions */
+       ACPI_FIXED_LENGTH,      /* 08 IO */
+       ACPI_FIXED_LENGTH,      /* 09 fixed_iO */
+       ACPI_FIXED_LENGTH,      /* 0_a fixed_dMA */
        0,
        0,
        0,
-       ACPI_VARIABLE_LENGTH,
-       ACPI_FIXED_LENGTH,
+       ACPI_VARIABLE_LENGTH,   /* 0_e vendor_short */
+       ACPI_FIXED_LENGTH,      /* 0_f end_tag */
 
        /* Large descriptors */
 
        0,
-       ACPI_FIXED_LENGTH,
-       ACPI_FIXED_LENGTH,
+       ACPI_FIXED_LENGTH,      /* 01 Memory24 */
+       ACPI_FIXED_LENGTH,      /* 02 generic_register */
        0,
-       ACPI_VARIABLE_LENGTH,
-       ACPI_FIXED_LENGTH,
-       ACPI_FIXED_LENGTH,
-       ACPI_VARIABLE_LENGTH,
-       ACPI_VARIABLE_LENGTH,
-       ACPI_VARIABLE_LENGTH,
-       ACPI_VARIABLE_LENGTH,
-       ACPI_FIXED_LENGTH
+       ACPI_VARIABLE_LENGTH,   /* 04 vendor_long */
+       ACPI_FIXED_LENGTH,      /* 05 Memory32 */
+       ACPI_FIXED_LENGTH,      /* 06 memory32_fixed */
+       ACPI_VARIABLE_LENGTH,   /* 07 Dword* address */
+       ACPI_VARIABLE_LENGTH,   /* 08 Word* address */
+       ACPI_VARIABLE_LENGTH,   /* 09 extended_iRQ */
+       ACPI_VARIABLE_LENGTH,   /* 0_a Qword* address */
+       ACPI_FIXED_LENGTH,      /* 0_b Extended* address */
+       ACPI_VARIABLE_LENGTH,   /* 0_c Gpio* */
+       0,
+       ACPI_VARIABLE_LENGTH    /* 0_e *serial_bus */
 };
 
+/*
+ * For the i_aSL compiler/disassembler, we don't want any error messages
+ * because the disassembler uses the resource validation code to determine
+ * if Buffer objects are actually Resource Templates.
+ */
+#ifdef ACPI_ASL_COMPILER
+#define ACPI_RESOURCE_ERROR(plist)
+#else
+#define ACPI_RESOURCE_ERROR(plist)  ACPI_ERROR(plist)
+#endif
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_walk_aml_resources
@@ -265,6 +421,7 @@ acpi_ut_walk_aml_resources(u8 * aml,
        u8 resource_index;
        u32 length;
        u32 offset = 0;
+       u8 end_tag[2] = { 0x79, 0x00 };
 
        ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
 
@@ -286,6 +443,10 @@ acpi_ut_walk_aml_resources(u8 * aml,
 
                status = acpi_ut_validate_resource(aml, &resource_index);
                if (ACPI_FAILURE(status)) {
+                       /*
+                        * Exit on failure. Cannot continue because the descriptor length
+                        * may be bogus also.
+                        */
                        return_ACPI_STATUS(status);
                }
 
@@ -300,7 +461,7 @@ acpi_ut_walk_aml_resources(u8 * aml,
                            user_function(aml, length, offset, resource_index,
                                          context);
                        if (ACPI_FAILURE(status)) {
-                               return (status);
+                               return_ACPI_STATUS(status);
                        }
                }
 
@@ -333,7 +494,19 @@ acpi_ut_walk_aml_resources(u8 * aml,
 
        /* Did not find an end_tag descriptor */
 
-       return (AE_AML_NO_RESOURCE_END_TAG);
+       if (user_function) {
+
+               /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
+
+               (void)acpi_ut_validate_resource(end_tag, &resource_index);
+               status =
+                   user_function(end_tag, 2, offset, resource_index, context);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+       }
+
+       return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 }
 
 /*******************************************************************************
@@ -354,6 +527,7 @@ acpi_ut_walk_aml_resources(u8 * aml,
 
 acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
 {
+       union aml_resource *aml_resource;
        u8 resource_type;
        u8 resource_index;
        acpi_rs_length resource_length;
@@ -375,7 +549,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
                /* Verify the large resource type (name) against the max */
 
                if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
-                       return (AE_AML_INVALID_RESOURCE_TYPE);
+                       goto invalid_resource;
                }
 
                /*
@@ -392,15 +566,17 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
                    ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
        }
 
-       /* Check validity of the resource type, zero indicates name is invalid */
-
+       /*
+        * Check validity of the resource type, via acpi_gbl_resource_types. Zero
+        * indicates an invalid resource.
+        */
        if (!acpi_gbl_resource_types[resource_index]) {
-               return (AE_AML_INVALID_RESOURCE_TYPE);
+               goto invalid_resource;
        }
 
        /*
-        * 2) Validate the resource_length field. This ensures that the length
-        *    is at least reasonable, and guarantees that it is non-zero.
+        * Validate the resource_length field. This ensures that the length
+        * is at least reasonable, and guarantees that it is non-zero.
         */
        resource_length = acpi_ut_get_resource_length(aml);
        minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
@@ -413,7 +589,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
                /* Fixed length resource, length must match exactly */
 
                if (resource_length != minimum_resource_length) {
-                       return (AE_AML_BAD_RESOURCE_LENGTH);
+                       goto bad_resource_length;
                }
                break;
 
@@ -422,7 +598,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
                /* Variable length resource, length must be at least the minimum */
 
                if (resource_length < minimum_resource_length) {
-                       return (AE_AML_BAD_RESOURCE_LENGTH);
+                       goto bad_resource_length;
                }
                break;
 
@@ -432,7 +608,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
 
                if ((resource_length > minimum_resource_length) ||
                    (resource_length < (minimum_resource_length - 1))) {
-                       return (AE_AML_BAD_RESOURCE_LENGTH);
+                       goto bad_resource_length;
                }
                break;
 
@@ -440,7 +616,23 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
 
                /* Shouldn't happen (because of validation earlier), but be sure */
 
-               return (AE_AML_INVALID_RESOURCE_TYPE);
+               goto invalid_resource;
+       }
+
+       aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
+       if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
+
+               /* Validate the bus_type field */
+
+               if ((aml_resource->common_serial_bus.type == 0) ||
+                   (aml_resource->common_serial_bus.type >
+                    AML_RESOURCE_MAX_SERIALBUSTYPE)) {
+                       ACPI_RESOURCE_ERROR((AE_INFO,
+                                            "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
+                                            aml_resource->common_serial_bus.
+                                            type));
+                       return (AE_AML_INVALID_RESOURCE_TYPE);
+               }
        }
 
        /* Optionally return the resource table index */
@@ -450,6 +642,22 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
        }
 
        return (AE_OK);
+
+      invalid_resource:
+
+       ACPI_RESOURCE_ERROR((AE_INFO,
+                            "Invalid/unsupported resource descriptor: Type 0x%2.2X",
+                            resource_type));
+       return (AE_AML_INVALID_RESOURCE_TYPE);
+
+      bad_resource_length:
+
+       ACPI_RESOURCE_ERROR((AE_INFO,
+                            "Invalid resource descriptor length: Type "
+                            "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
+                            resource_type, resource_length,
+                            minimum_resource_length));
+       return (AE_AML_BAD_RESOURCE_LENGTH);
 }
 
 /*******************************************************************************
index 30c21e1a9360c79adad9516dbd12787f9e892bd8..4267477c2797b2558becff9b23683d24a3cfadd1 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 420ebfe08c7218b091e1050217524547b15284aa..644e8c8ebc4b30c6ea3ca607708e3478c806c4bc 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,7 @@
 #include "acnamesp.h"
 #include "acdebug.h"
 #include "actables.h"
+#include "acinterp.h"
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utxface")
@@ -640,4 +641,41 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
 }
 
 ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_check_address_range
+ *
+ * PARAMETERS:  space_id            - Address space ID
+ *              Address             - Start address
+ *              Length              - Length
+ *              Warn                - TRUE if warning on overlap desired
+ *
+ * RETURN:      Count of the number of conflicts detected.
+ *
+ * DESCRIPTION: Check if the input address range overlaps any of the
+ *              ASL operation region address ranges.
+ *
+ ****************************************************************************/
+u32
+acpi_check_address_range(acpi_adr_space_type space_id,
+                        acpi_physical_address address,
+                        acpi_size length, u8 warn)
+{
+       u32 overlaps;
+       acpi_status status;
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               return (0);
+       }
+
+       overlaps = acpi_ut_check_address_range(space_id, address,
+                                              (u32)length, warn);
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+       return (overlaps);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_check_address_range)
 #endif                         /* !ACPI_ASL_COMPILER */
index 8d0245ec431525bbd62a030d82e1eea2bfcdb9bd..52b568af18199570446431a81638814b3cc6c99a 100644 (file)
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c
new file mode 100644 (file)
index 0000000..1427d19
--- /dev/null
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ *
+ * Module Name: utxfmutex - external AML mutex access functions
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utxfmutex")
+
+/* Local prototypes */
+static acpi_status
+acpi_ut_get_mutex_object(acpi_handle handle,
+                        acpi_string pathname,
+                        union acpi_operand_object **ret_obj);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_mutex_object
+ *
+ * PARAMETERS:  Handle              - Mutex or prefix handle (optional)
+ *              Pathname            - Mutex pathname (optional)
+ *              ret_obj             - Where the mutex object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get an AML mutex object. The mutex node is pointed to by
+ *              Handle:Pathname. Either Handle or Pathname can be NULL, but
+ *              not both.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_get_mutex_object(acpi_handle handle,
+                        acpi_string pathname,
+                        union acpi_operand_object **ret_obj)
+{
+       struct acpi_namespace_node *mutex_node;
+       union acpi_operand_object *mutex_obj;
+       acpi_status status;
+
+       /* Parameter validation */
+
+       if (!ret_obj || (!handle && !pathname)) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       /* Get a the namespace node for the mutex */
+
+       mutex_node = handle;
+       if (pathname != NULL) {
+               status = acpi_get_handle(handle, pathname,
+                                        ACPI_CAST_PTR(acpi_handle,
+                                                      &mutex_node));
+               if (ACPI_FAILURE(status)) {
+                       return (status);
+               }
+       }
+
+       /* Ensure that we actually have a Mutex object */
+
+       if (!mutex_node || (mutex_node->type != ACPI_TYPE_MUTEX)) {
+               return (AE_TYPE);
+       }
+
+       /* Get the low-level mutex object */
+
+       mutex_obj = acpi_ns_get_attached_object(mutex_node);
+       if (!mutex_obj) {
+               return (AE_NULL_OBJECT);
+       }
+
+       *ret_obj = mutex_obj;
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_acquire_mutex
+ *
+ * PARAMETERS:  Handle              - Mutex or prefix handle (optional)
+ *              Pathname            - Mutex pathname (optional)
+ *              Timeout             - Max time to wait for the lock (millisec)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Acquire an AML mutex. This is a device driver interface to
+ *              AML mutex objects, and allows for transaction locking between
+ *              drivers and AML code. The mutex node is pointed to by
+ *              Handle:Pathname. Either Handle or Pathname can be NULL, but
+ *              not both.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout)
+{
+       acpi_status status;
+       union acpi_operand_object *mutex_obj;
+
+       /* Get the low-level mutex associated with Handle:Pathname */
+
+       status = acpi_ut_get_mutex_object(handle, pathname, &mutex_obj);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /* Acquire the OS mutex */
+
+       status = acpi_os_acquire_mutex(mutex_obj->mutex.os_mutex, timeout);
+       return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_release_mutex
+ *
+ * PARAMETERS:  Handle              - Mutex or prefix handle (optional)
+ *              Pathname            - Mutex pathname (optional)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Release an AML mutex. This is a device driver interface to
+ *              AML mutex objects, and allows for transaction locking between
+ *              drivers and AML code. The mutex node is pointed to by
+ *              Handle:Pathname. Either Handle or Pathname can be NULL, but
+ *              not both.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_release_mutex(acpi_handle handle, acpi_string pathname)
+{
+       acpi_status status;
+       union acpi_operand_object *mutex_obj;
+
+       /* Get the low-level mutex associated with Handle:Pathname */
+
+       status = acpi_ut_get_mutex_object(handle, pathname, &mutex_obj);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /* Release the OS mutex */
+
+       acpi_os_release_mutex(mutex_obj->mutex.os_mutex);
+       return (AE_OK);
+}
index 61540360d5ce815f67e67250874ad357f3e328e6..e5d53b7ddc7e0eb024f7cdc6863619bd2c3dc0a2 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/acpi_io.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/kref.h>
 #include <linux/rculist.h>
 #include <linux/interrupt.h>
 #include <linux/debugfs.h>
-#include <acpi/atomicio.h>
 
 #include "apei-internal.h"
 
@@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
 {
        int rc;
 
-       rc = acpi_atomic_read(val, &entry->register_region);
+       rc = apei_read(val, &entry->register_region);
        if (rc)
                return rc;
        *val >>= entry->register_region.bit_offset;
@@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
        val <<= entry->register_region.bit_offset;
        if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
                u64 valr = 0;
-               rc = acpi_atomic_read(&valr, &entry->register_region);
+               rc = apei_read(&valr, &entry->register_region);
                if (rc)
                        return rc;
                valr &= ~(entry->mask << entry->register_region.bit_offset);
                val |= valr;
        }
-       rc = acpi_atomic_write(val, &entry->register_region);
+       rc = apei_write(val, &entry->register_region);
 
        return rc;
 }
@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx,
        u8 ins = entry->instruction;
 
        if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
-               return acpi_pre_map_gar(&entry->register_region);
+               return acpi_os_map_generic_address(&entry->register_region);
 
        return 0;
 }
@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx,
        u8 ins = entry->instruction;
 
        if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
-               acpi_post_unmap_gar(&entry->register_region);
+               acpi_os_unmap_generic_address(&entry->register_region);
 
        return 0;
 }
@@ -421,6 +421,17 @@ static int apei_resources_merge(struct apei_resources *resources1,
        return 0;
 }
 
+int apei_resources_add(struct apei_resources *resources,
+                      unsigned long start, unsigned long size,
+                      bool iomem)
+{
+       if (iomem)
+               return apei_res_add(&resources->iomem, start, size);
+       else
+               return apei_res_add(&resources->ioport, start, size);
+}
+EXPORT_SYMBOL_GPL(apei_resources_add);
+
 /*
  * EINJ has two groups of GARs (EINJ table entry and trigger table
  * entry), so common resources are subtracted from the trigger table
@@ -438,8 +449,19 @@ int apei_resources_sub(struct apei_resources *resources1,
 }
 EXPORT_SYMBOL_GPL(apei_resources_sub);
 
+static int apei_get_nvs_callback(__u64 start, __u64 size, void *data)
+{
+       struct apei_resources *resources = data;
+       return apei_res_add(&resources->iomem, start, size);
+}
+
+static int apei_get_nvs_resources(struct apei_resources *resources)
+{
+       return acpi_nvs_for_each_region(apei_get_nvs_callback, resources);
+}
+
 /*
- * IO memory/port rersource management mechanism is used to check
+ * IO memory/port resource management mechanism is used to check
  * whether memory/port area used by GARs conflicts with normal memory
  * or IO memory/port of devices.
  */
@@ -448,21 +470,35 @@ int apei_resources_request(struct apei_resources *resources,
 {
        struct apei_res *res, *res_bak = NULL;
        struct resource *r;
+       struct apei_resources nvs_resources;
        int rc;
 
        rc = apei_resources_sub(resources, &apei_resources_all);
        if (rc)
                return rc;
 
+       /*
+        * Some firmware uses ACPI NVS region, that has been marked as
+        * busy, so exclude it from APEI resources to avoid false
+        * conflict.
+        */
+       apei_resources_init(&nvs_resources);
+       rc = apei_get_nvs_resources(&nvs_resources);
+       if (rc)
+               goto res_fini;
+       rc = apei_resources_sub(resources, &nvs_resources);
+       if (rc)
+               goto res_fini;
+
        rc = -EINVAL;
        list_for_each_entry(res, &resources->iomem, list) {
                r = request_mem_region(res->start, res->end - res->start,
                                       desc);
                if (!r) {
                        pr_err(APEI_PFX
-               "Can not request iomem region <%016llx-%016llx> for GARs.\n",
+               "Can not request [mem %#010llx-%#010llx] for %s registers\n",
                               (unsigned long long)res->start,
-                              (unsigned long long)res->end);
+                              (unsigned long long)res->end - 1, desc);
                        res_bak = res;
                        goto err_unmap_iomem;
                }
@@ -472,9 +508,9 @@ int apei_resources_request(struct apei_resources *resources,
                r = request_region(res->start, res->end - res->start, desc);
                if (!r) {
                        pr_err(APEI_PFX
-               "Can not request ioport region <%016llx-%016llx> for GARs.\n",
+               "Can not request [io  %#06llx-%#06llx] for %s registers\n",
                               (unsigned long long)res->start,
-                              (unsigned long long)res->end);
+                              (unsigned long long)res->end - 1, desc);
                        res_bak = res;
                        goto err_unmap_ioport;
                }
@@ -500,6 +536,8 @@ err_unmap_iomem:
                        break;
                release_mem_region(res->start, res->end - res->start);
        }
+res_fini:
+       apei_resources_fini(&nvs_resources);
        return rc;
 }
 EXPORT_SYMBOL_GPL(apei_resources_request);
@@ -553,6 +591,69 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
        return 0;
 }
 
+/* read GAR in interrupt (including NMI) or process context */
+int apei_read(u64 *val, struct acpi_generic_address *reg)
+{
+       int rc;
+       u64 address;
+       acpi_status status;
+
+       rc = apei_check_gar(reg, &address);
+       if (rc)
+               return rc;
+
+       *val = 0;
+       switch(reg->space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+               status = acpi_os_read_memory64((acpi_physical_address)
+                                            address, val, reg->bit_width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               break;
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(apei_read);
+
+/* write GAR in interrupt (including NMI) or process context */
+int apei_write(u64 val, struct acpi_generic_address *reg)
+{
+       int rc;
+       u64 address;
+       acpi_status status;
+
+       rc = apei_check_gar(reg, &address);
+       if (rc)
+               return rc;
+
+       switch (reg->space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+               status = acpi_os_write_memory64((acpi_physical_address)
+                                             address, val, reg->bit_width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               break;
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               status = acpi_os_write_port(address, val, reg->bit_width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(apei_write);
+
 static int collect_res_callback(struct apei_exec_context *ctx,
                                struct acpi_whea_header *entry,
                                void *data)
index f57050e7a5e756ceb1f8885ce01030d0ac593ea4..cca240a33038fe148ca5e9324214ba988c62c6c2 100644 (file)
@@ -68,6 +68,9 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio
 /* IP has been set in instruction function */
 #define APEI_EXEC_SET_IP       1
 
+int apei_read(u64 *val, struct acpi_generic_address *reg);
+int apei_write(u64 val, struct acpi_generic_address *reg);
+
 int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
 int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
 int apei_exec_read_register(struct apei_exec_context *ctx,
@@ -95,6 +98,9 @@ static inline void apei_resources_init(struct apei_resources *resources)
 }
 
 void apei_resources_fini(struct apei_resources *resources);
+int apei_resources_add(struct apei_resources *resources,
+                      unsigned long start, unsigned long size,
+                      bool iomem);
 int apei_resources_sub(struct apei_resources *resources1,
                       struct apei_resources *resources2);
 int apei_resources_request(struct apei_resources *resources,
index 589b96c38704db0bf803842aaf3c6b22b890cd06..4ca087dd5f4fceb797e1272912b06f082af7549d 100644 (file)
 /* Firmware should respond within 1 milliseconds */
 #define FIRMWARE_TIMEOUT       (1 * NSEC_PER_MSEC)
 
+/*
+ * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
+ */
+static int acpi5;
+
+struct set_error_type_with_address {
+       u32     type;
+       u32     vendor_extension;
+       u32     flags;
+       u32     apicid;
+       u64     memory_address;
+       u64     memory_address_range;
+       u32     pcie_sbdf;
+};
+enum {
+       SETWA_FLAGS_APICID = 1,
+       SETWA_FLAGS_MEM = 2,
+       SETWA_FLAGS_PCIE_SBDF = 4,
+};
+
+/*
+ * Vendor extensions for platform specific operations
+ */
+struct vendor_error_type_extension {
+       u32     length;
+       u32     pcie_sbdf;
+       u16     vendor_id;
+       u16     device_id;
+       u8      rev_id;
+       u8      reserved[3];
+};
+
+static u32 vendor_flags;
+static struct debugfs_blob_wrapper vendor_blob;
+static char vendor_dev[64];
+
 /*
  * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
  * EINJ table through an unpublished extension. Use with caution as
@@ -103,15 +139,7 @@ static struct apei_exec_ins_type einj_ins_type[] = {
  */
 static DEFINE_MUTEX(einj_mutex);
 
-static struct einj_parameter *einj_param;
-
-#ifndef writeq
-static inline void writeq(__u64 val, volatile void __iomem *addr)
-{
-       writel(val, addr);
-       writel(val >> 32, addr+4);
-}
-#endif
+static void *einj_param;
 
 static void einj_exec_ctx_init(struct apei_exec_context *ctx)
 {
@@ -158,10 +186,30 @@ static int einj_timedout(u64 *t)
        return 0;
 }
 
-static u64 einj_get_parameter_address(void)
+static void check_vendor_extension(u64 paddr,
+                                  struct set_error_type_with_address *v5param)
+{
+       int     offset = v5param->vendor_extension;
+       struct  vendor_error_type_extension *v;
+       u32     sbdf;
+
+       if (!offset)
+               return;
+       v = acpi_os_map_memory(paddr + offset, sizeof(*v));
+       if (!v)
+               return;
+       sbdf = v->pcie_sbdf;
+       sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
+               sbdf >> 24, (sbdf >> 16) & 0xff,
+               (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
+                v->vendor_id, v->device_id, v->rev_id);
+       acpi_os_unmap_memory(v, sizeof(*v));
+}
+
+static void *einj_get_parameter_address(void)
 {
        int i;
-       u64 paddr = 0;
+       u64 paddrv4 = 0, paddrv5 = 0;
        struct acpi_whea_header *entry;
 
        entry = EINJ_TAB_ENTRY(einj_tab);
@@ -170,12 +218,40 @@ static u64 einj_get_parameter_address(void)
                    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
                    entry->register_region.space_id ==
                    ACPI_ADR_SPACE_SYSTEM_MEMORY)
-                       memcpy(&paddr, &entry->register_region.address,
-                              sizeof(paddr));
+                       memcpy(&paddrv4, &entry->register_region.address,
+                              sizeof(paddrv4));
+               if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS &&
+                   entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
+                   entry->register_region.space_id ==
+                   ACPI_ADR_SPACE_SYSTEM_MEMORY)
+                       memcpy(&paddrv5, &entry->register_region.address,
+                              sizeof(paddrv5));
                entry++;
        }
+       if (paddrv5) {
+               struct set_error_type_with_address *v5param;
+
+               v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param));
+               if (v5param) {
+                       acpi5 = 1;
+                       check_vendor_extension(paddrv5, v5param);
+                       return v5param;
+               }
+       }
+       if (paddrv4) {
+               struct einj_parameter *v4param;
+
+               v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
+               if (!v4param)
+                       return NULL;
+               if (v4param->reserved1 || v4param->reserved2) {
+                       acpi_os_unmap_memory(v4param, sizeof(*v4param));
+                       return NULL;
+               }
+               return v4param;
+       }
 
-       return paddr;
+       return NULL;
 }
 
 /* do sanity check to trigger table */
@@ -184,7 +260,7 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
        if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
                return -EINVAL;
        if (trigger_tab->table_size > PAGE_SIZE ||
-           trigger_tab->table_size <= trigger_tab->header_size)
+           trigger_tab->table_size < trigger_tab->header_size)
                return -EINVAL;
        if (trigger_tab->entry_count !=
            (trigger_tab->table_size - trigger_tab->header_size) /
@@ -194,8 +270,29 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
        return 0;
 }
 
+static struct acpi_generic_address *einj_get_trigger_parameter_region(
+       struct acpi_einj_trigger *trigger_tab, u64 param1, u64 param2)
+{
+       int i;
+       struct acpi_whea_header *entry;
+
+       entry = (struct acpi_whea_header *)
+               ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
+       for (i = 0; i < trigger_tab->entry_count; i++) {
+               if (entry->action == ACPI_EINJ_TRIGGER_ERROR &&
+               entry->instruction == ACPI_EINJ_WRITE_REGISTER_VALUE &&
+               entry->register_region.space_id ==
+                       ACPI_ADR_SPACE_SYSTEM_MEMORY &&
+               (entry->register_region.address & param2) == (param1 & param2))
+                       return &entry->register_region;
+               entry++;
+       }
+
+       return NULL;
+}
 /* Execute instructions in trigger error action table */
-static int __einj_error_trigger(u64 trigger_paddr)
+static int __einj_error_trigger(u64 trigger_paddr, u32 type,
+                               u64 param1, u64 param2)
 {
        struct acpi_einj_trigger *trigger_tab = NULL;
        struct apei_exec_context trigger_ctx;
@@ -204,14 +301,16 @@ static int __einj_error_trigger(u64 trigger_paddr)
        struct resource *r;
        u32 table_size;
        int rc = -EIO;
+       struct acpi_generic_address *trigger_param_region = NULL;
 
        r = request_mem_region(trigger_paddr, sizeof(*trigger_tab),
                               "APEI EINJ Trigger Table");
        if (!r) {
                pr_err(EINJ_PFX
-       "Can not request iomem region <%016llx-%016llx> for Trigger table.\n",
+       "Can not request [mem %#010llx-%#010llx] for Trigger table\n",
                       (unsigned long long)trigger_paddr,
-                      (unsigned long long)trigger_paddr+sizeof(*trigger_tab));
+                      (unsigned long long)trigger_paddr +
+                           sizeof(*trigger_tab) - 1);
                goto out;
        }
        trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab));
@@ -225,6 +324,11 @@ static int __einj_error_trigger(u64 trigger_paddr)
                           "The trigger error action table is invalid\n");
                goto out_rel_header;
        }
+
+       /* No action structures in the TRIGGER_ERROR table, nothing to do */
+       if (!trigger_tab->entry_count)
+               goto out_rel_header;
+
        rc = -EIO;
        table_size = trigger_tab->table_size;
        r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
@@ -232,9 +336,9 @@ static int __einj_error_trigger(u64 trigger_paddr)
                               "APEI EINJ Trigger Table");
        if (!r) {
                pr_err(EINJ_PFX
-"Can not request iomem region <%016llx-%016llx> for Trigger Table Entry.\n",
-                      (unsigned long long)trigger_paddr+sizeof(*trigger_tab),
-                      (unsigned long long)trigger_paddr + table_size);
+"Can not request [mem %#010llx-%#010llx] for Trigger Table Entry\n",
+                      (unsigned long long)trigger_paddr + sizeof(*trigger_tab),
+                      (unsigned long long)trigger_paddr + table_size - 1);
                goto out_rel_header;
        }
        iounmap(trigger_tab);
@@ -255,6 +359,30 @@ static int __einj_error_trigger(u64 trigger_paddr)
        rc = apei_resources_sub(&trigger_resources, &einj_resources);
        if (rc)
                goto out_fini;
+       /*
+        * Some firmware will access target address specified in
+        * param1 to trigger the error when injecting memory error.
+        * This will cause resource conflict with regular memory.  So
+        * remove it from trigger table resources.
+        */
+       if (param_extension && (type & 0x0038) && param2) {
+               struct apei_resources addr_resources;
+               apei_resources_init(&addr_resources);
+               trigger_param_region = einj_get_trigger_parameter_region(
+                       trigger_tab, param1, param2);
+               if (trigger_param_region) {
+                       rc = apei_resources_add(&addr_resources,
+                               trigger_param_region->address,
+                               trigger_param_region->bit_width/8, true);
+                       if (rc)
+                               goto out_fini;
+                       rc = apei_resources_sub(&trigger_resources,
+                                       &addr_resources);
+               }
+               apei_resources_fini(&addr_resources);
+               if (rc)
+                       goto out_fini;
+       }
        rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
        if (rc)
                goto out_fini;
@@ -293,12 +421,56 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, type);
-       rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
-       if (rc)
-               return rc;
-       if (einj_param) {
-               writeq(param1, &einj_param->param1);
-               writeq(param2, &einj_param->param2);
+       if (acpi5) {
+               struct set_error_type_with_address *v5param = einj_param;
+
+               v5param->type = type;
+               if (type & 0x80000000) {
+                       switch (vendor_flags) {
+                       case SETWA_FLAGS_APICID:
+                               v5param->apicid = param1;
+                               break;
+                       case SETWA_FLAGS_MEM:
+                               v5param->memory_address = param1;
+                               v5param->memory_address_range = param2;
+                               break;
+                       case SETWA_FLAGS_PCIE_SBDF:
+                               v5param->pcie_sbdf = param1;
+                               break;
+                       }
+                       v5param->flags = vendor_flags;
+               } else {
+                       switch (type) {
+                       case ACPI_EINJ_PROCESSOR_CORRECTABLE:
+                       case ACPI_EINJ_PROCESSOR_UNCORRECTABLE:
+                       case ACPI_EINJ_PROCESSOR_FATAL:
+                               v5param->apicid = param1;
+                               v5param->flags = SETWA_FLAGS_APICID;
+                               break;
+                       case ACPI_EINJ_MEMORY_CORRECTABLE:
+                       case ACPI_EINJ_MEMORY_UNCORRECTABLE:
+                       case ACPI_EINJ_MEMORY_FATAL:
+                               v5param->memory_address = param1;
+                               v5param->memory_address_range = param2;
+                               v5param->flags = SETWA_FLAGS_MEM;
+                               break;
+                       case ACPI_EINJ_PCIX_CORRECTABLE:
+                       case ACPI_EINJ_PCIX_UNCORRECTABLE:
+                       case ACPI_EINJ_PCIX_FATAL:
+                               v5param->pcie_sbdf = param1;
+                               v5param->flags = SETWA_FLAGS_PCIE_SBDF;
+                               break;
+                       }
+               }
+       } else {
+               rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
+               if (rc)
+                       return rc;
+               if (einj_param) {
+                       struct einj_parameter *v4param = einj_param;
+                       v4param->param1 = param1;
+                       v4param->param2 = param2;
+               }
        }
        rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
        if (rc)
@@ -324,7 +496,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
        if (rc)
                return rc;
        trigger_paddr = apei_exec_ctx_get_output(&ctx);
-       rc = __einj_error_trigger(trigger_paddr);
+       rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
        if (rc)
                return rc;
        rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
@@ -408,15 +580,25 @@ static int error_type_set(void *data, u64 val)
 {
        int rc;
        u32 available_error_type = 0;
+       u32 tval, vendor;
+
+       /*
+        * Vendor defined types have 0x80000000 bit set, and
+        * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
+        */
+       vendor = val & 0x80000000;
+       tval = val & 0x7fffffff;
 
        /* Only one error type can be specified */
-       if (val & (val - 1))
-               return -EINVAL;
-       rc = einj_get_available_error_type(&available_error_type);
-       if (rc)
-               return rc;
-       if (!(val & available_error_type))
+       if (tval & (tval - 1))
                return -EINVAL;
+       if (!vendor) {
+               rc = einj_get_available_error_type(&available_error_type);
+               if (rc)
+                       return rc;
+               if (!(val & available_error_type))
+                       return -EINVAL;
+       }
        error_type = val;
 
        return 0;
@@ -455,7 +637,6 @@ static int einj_check_table(struct acpi_table_einj *einj_tab)
 static int __init einj_init(void)
 {
        int rc;
-       u64 param_paddr;
        acpi_status status;
        struct dentry *fentry;
        struct apei_exec_context ctx;
@@ -465,10 +646,9 @@ static int __init einj_init(void)
 
        status = acpi_get_table(ACPI_SIG_EINJ, 0,
                                (struct acpi_table_header **)&einj_tab);
-       if (status == AE_NOT_FOUND) {
-               pr_info(EINJ_PFX "Table is not found!\n");
+       if (status == AE_NOT_FOUND)
                return -ENODEV;
-       else if (ACPI_FAILURE(status)) {
+       else if (ACPI_FAILURE(status)) {
                const char *msg = acpi_format_exception(status);
                pr_err(EINJ_PFX "Failed to get table, %s\n", msg);
                return -EINVAL;
@@ -509,23 +689,30 @@ static int __init einj_init(void)
        rc = apei_exec_pre_map_gars(&ctx);
        if (rc)
                goto err_release;
-       if (param_extension) {
-               param_paddr = einj_get_parameter_address();
-               if (param_paddr) {
-                       einj_param = ioremap(param_paddr, sizeof(*einj_param));
-                       rc = -ENOMEM;
-                       if (!einj_param)
-                               goto err_unmap;
-                       fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
-                                                   einj_debug_dir, &error_param1);
-                       if (!fentry)
-                               goto err_unmap;
-                       fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
-                                                   einj_debug_dir, &error_param2);
-                       if (!fentry)
-                               goto err_unmap;
-               } else
-                       pr_warn(EINJ_PFX "Parameter extension is not supported.\n");
+
+       einj_param = einj_get_parameter_address();
+       if ((param_extension || acpi5) && einj_param) {
+               fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
+                                           einj_debug_dir, &error_param1);
+               if (!fentry)
+                       goto err_unmap;
+               fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
+                                           einj_debug_dir, &error_param2);
+               if (!fentry)
+                       goto err_unmap;
+       }
+
+       if (vendor_dev[0]) {
+               vendor_blob.data = vendor_dev;
+               vendor_blob.size = strlen(vendor_dev);
+               fentry = debugfs_create_blob("vendor", S_IRUSR,
+                                            einj_debug_dir, &vendor_blob);
+               if (!fentry)
+                       goto err_unmap;
+               fentry = debugfs_create_x32("vendor_flags", S_IRUSR | S_IWUSR,
+                                           einj_debug_dir, &vendor_flags);
+               if (!fentry)
+                       goto err_unmap;
        }
 
        pr_info(EINJ_PFX "Error INJection is initialized.\n");
@@ -533,8 +720,13 @@ static int __init einj_init(void)
        return 0;
 
 err_unmap:
-       if (einj_param)
-               iounmap(einj_param);
+       if (einj_param) {
+               acpi_size size = (acpi5) ?
+                       sizeof(struct set_error_type_with_address) :
+                       sizeof(struct einj_parameter);
+
+               acpi_os_unmap_memory(einj_param, size);
+       }
        apei_exec_post_unmap_gars(&ctx);
 err_release:
        apei_resources_release(&einj_resources);
@@ -550,8 +742,13 @@ static void __exit einj_exit(void)
 {
        struct apei_exec_context ctx;
 
-       if (einj_param)
-               iounmap(einj_param);
+       if (einj_param) {
+               acpi_size size = (acpi5) ?
+                       sizeof(struct set_error_type_with_address) :
+                       sizeof(struct einj_parameter);
+
+               acpi_os_unmap_memory(einj_param, size);
+       }
        einj_exec_ctx_init(&ctx);
        apei_exec_post_unmap_gars(&ctx);
        apei_resources_release(&einj_resources);
index 6a9e3bad13f418d93572faff72d18a4df124f8e8..eb9fab5b96e4d3dca071e11e8dbdec2405b23508 100644 (file)
@@ -1127,10 +1127,9 @@ static int __init erst_init(void)
 
        status = acpi_get_table(ACPI_SIG_ERST, 0,
                                (struct acpi_table_header **)&erst_tab);
-       if (status == AE_NOT_FOUND) {
-               pr_info(ERST_PFX "Table is not found!\n");
+       if (status == AE_NOT_FOUND)
                goto err;
-       else if (ACPI_FAILURE(status)) {
+       else if (ACPI_FAILURE(status)) {
                const char *msg = acpi_format_exception(status);
                pr_err(ERST_PFX "Failed to get table, %s\n", msg);
                rc = -EINVAL;
index ebaf037a787b5479dcc87100e883a3440b8ef25f..9b3cac0abecc33c672c884ece470dfb494d1836c 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/acpi_io.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
@@ -45,8 +46,9 @@
 #include <linux/irq_work.h>
 #include <linux/llist.h>
 #include <linux/genalloc.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
 #include <acpi/apei.h>
-#include <acpi/atomicio.h>
 #include <acpi/hed.h>
 #include <asm/mce.h>
 #include <asm/tlbflush.h>
@@ -299,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
        if (!ghes)
                return ERR_PTR(-ENOMEM);
        ghes->generic = generic;
-       rc = acpi_pre_map_gar(&generic->error_status_address);
+       rc = acpi_os_map_generic_address(&generic->error_status_address);
        if (rc)
                goto err_free;
        error_block_length = generic->error_block_length;
@@ -319,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
        return ghes;
 
 err_unmap:
-       acpi_post_unmap_gar(&generic->error_status_address);
+       acpi_os_unmap_generic_address(&generic->error_status_address);
 err_free:
        kfree(ghes);
        return ERR_PTR(rc);
@@ -328,7 +330,7 @@ err_free:
 static void ghes_fini(struct ghes *ghes)
 {
        kfree(ghes->estatus);
-       acpi_post_unmap_gar(&ghes->generic->error_status_address);
+       acpi_os_unmap_generic_address(&ghes->generic->error_status_address);
 }
 
 enum {
@@ -399,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent)
        u32 len;
        int rc;
 
-       rc = acpi_atomic_read(&buf_paddr, &g->error_status_address);
+       rc = apei_read(&buf_paddr, &g->error_status_address);
        if (rc) {
                if (!silent && printk_ratelimit())
                        pr_warning(FW_WARN GHES_PFX
@@ -476,6 +478,27 @@ static void ghes_do_proc(const struct acpi_hest_generic_status *estatus)
                        }
 #endif
                }
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+               else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
+                                     CPER_SEC_PCIE)) {
+                       struct cper_sec_pcie *pcie_err;
+                       pcie_err = (struct cper_sec_pcie *)(gdata+1);
+                       if (sev == GHES_SEV_RECOVERABLE &&
+                           sec_sev == GHES_SEV_RECOVERABLE &&
+                           pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
+                           pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
+                               unsigned int devfn;
+                               int aer_severity;
+                               devfn = PCI_DEVFN(pcie_err->device_id.device,
+                                                 pcie_err->device_id.function);
+                               aer_severity = cper_severity_to_aer(sev);
+                               aer_recover_queue(pcie_err->device_id.segment,
+                                                 pcie_err->device_id.bus,
+                                                 devfn, aer_severity);
+                       }
+
+               }
+#endif
        }
 }
 
@@ -483,16 +506,22 @@ static void __ghes_print_estatus(const char *pfx,
                                 const struct acpi_hest_generic *generic,
                                 const struct acpi_hest_generic_status *estatus)
 {
+       static atomic_t seqno;
+       unsigned int curr_seqno;
+       char pfx_seq[64];
+
        if (pfx == NULL) {
                if (ghes_severity(estatus->error_severity) <=
                    GHES_SEV_CORRECTED)
-                       pfx = KERN_WARNING HW_ERR;
+                       pfx = KERN_WARNING;
                else
-                       pfx = KERN_ERR HW_ERR;
+                       pfx = KERN_ERR;
        }
+       curr_seqno = atomic_inc_return(&seqno);
+       snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}" HW_ERR, pfx, curr_seqno);
        printk("%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
-              pfx, generic->header.source_id);
-       apei_estatus_print(pfx, estatus);
+              pfx_seq, generic->header.source_id);
+       apei_estatus_print(pfx_seq, estatus);
 }
 
 static int ghes_print_estatus(const char *pfx,
@@ -711,26 +740,34 @@ static int ghes_notify_sci(struct notifier_block *this,
        return ret;
 }
 
+static struct llist_node *llist_nodes_reverse(struct llist_node *llnode)
+{
+       struct llist_node *next, *tail = NULL;
+
+       while (llnode) {
+               next = llnode->next;
+               llnode->next = tail;
+               tail = llnode;
+               llnode = next;
+       }
+
+       return tail;
+}
+
 static void ghes_proc_in_irq(struct irq_work *irq_work)
 {
-       struct llist_node *llnode, *next, *tail = NULL;
+       struct llist_node *llnode, *next;
        struct ghes_estatus_node *estatus_node;
        struct acpi_hest_generic *generic;
        struct acpi_hest_generic_status *estatus;
        u32 len, node_len;
 
+       llnode = llist_del_all(&ghes_estatus_llist);
        /*
         * Because the time order of estatus in list is reversed,
         * revert it back to proper order.
         */
-       llnode = llist_del_all(&ghes_estatus_llist);
-       while (llnode) {
-               next = llnode->next;
-               llnode->next = tail;
-               tail = llnode;
-               llnode = next;
-       }
-       llnode = tail;
+       llnode = llist_nodes_reverse(llnode);
        while (llnode) {
                next = llnode->next;
                estatus_node = llist_entry(llnode, struct ghes_estatus_node,
@@ -750,6 +787,32 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
        }
 }
 
+static void ghes_print_queued_estatus(void)
+{
+       struct llist_node *llnode;
+       struct ghes_estatus_node *estatus_node;
+       struct acpi_hest_generic *generic;
+       struct acpi_hest_generic_status *estatus;
+       u32 len, node_len;
+
+       llnode = llist_del_all(&ghes_estatus_llist);
+       /*
+        * Because the time order of estatus in list is reversed,
+        * revert it back to proper order.
+        */
+       llnode = llist_nodes_reverse(llnode);
+       while (llnode) {
+               estatus_node = llist_entry(llnode, struct ghes_estatus_node,
+                                          llnode);
+               estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
+               len = apei_estatus_len(estatus);
+               node_len = GHES_ESTATUS_NODE_LEN(len);
+               generic = estatus_node->generic;
+               ghes_print_estatus(NULL, generic, estatus);
+               llnode = llnode->next;
+       }
+}
+
 static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
 {
        struct ghes *ghes, *ghes_global = NULL;
@@ -775,7 +838,8 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
 
        if (sev_global >= GHES_SEV_PANIC) {
                oops_begin();
-               __ghes_print_estatus(KERN_EMERG HW_ERR, ghes_global->generic,
+               ghes_print_queued_estatus();
+               __ghes_print_estatus(KERN_EMERG, ghes_global->generic,
                                     ghes_global->estatus);
                /* reboot to log the error! */
                if (panic_timeout == 0)
index ee7fddc4665c9788d1502f0f28304493cede903b..7f00cf38098f21bdbe0d6a69ba624d18b00f7cb3 100644 (file)
@@ -221,10 +221,9 @@ void __init acpi_hest_init(void)
 
        status = acpi_get_table(ACPI_SIG_HEST, 0,
                                (struct acpi_table_header **)&hest_tab);
-       if (status == AE_NOT_FOUND) {
-               pr_info(HEST_PFX "Table not found.\n");
+       if (status == AE_NOT_FOUND)
                goto err;
-       else if (ACPI_FAILURE(status)) {
+       else if (ACPI_FAILURE(status)) {
                const char *msg = acpi_format_exception(status);
                pr_err(HEST_PFX "Failed to get table, %s\n", msg);
                rc = -EINVAL;
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
deleted file mode 100644 (file)
index cfc0cc1..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * atomicio.c - ACPI IO memory pre-mapping/post-unmapping, then
- * accessing in atomic context.
- *
- * This is used for NMI handler to access IO memory area, because
- * ioremap/iounmap can not be used in NMI handler. The IO memory area
- * is pre-mapped in process context and accessed in NMI handler.
- *
- * Copyright (C) 2009-2010, Intel Corp.
- *     Author: Huang Ying <ying.huang@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/io.h>
-#include <linux/kref.h>
-#include <linux/rculist.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <acpi/atomicio.h>
-
-#define ACPI_PFX "ACPI: "
-
-static LIST_HEAD(acpi_iomaps);
-/*
- * Used for mutual exclusion between writers of acpi_iomaps list, for
- * synchronization between readers and writer, RCU is used.
- */
-static DEFINE_SPINLOCK(acpi_iomaps_lock);
-
-struct acpi_iomap {
-       struct list_head list;
-       void __iomem *vaddr;
-       unsigned long size;
-       phys_addr_t paddr;
-       struct kref ref;
-};
-
-/* acpi_iomaps_lock or RCU read lock must be held before calling */
-static struct acpi_iomap *__acpi_find_iomap(phys_addr_t paddr,
-                                           unsigned long size)
-{
-       struct acpi_iomap *map;
-
-       list_for_each_entry_rcu(map, &acpi_iomaps, list) {
-               if (map->paddr + map->size >= paddr + size &&
-                   map->paddr <= paddr)
-                       return map;
-       }
-       return NULL;
-}
-
-/*
- * Atomic "ioremap" used by NMI handler, if the specified IO memory
- * area is not pre-mapped, NULL will be returned.
- *
- * acpi_iomaps_lock or RCU read lock must be held before calling
- */
-static void __iomem *__acpi_ioremap_fast(phys_addr_t paddr,
-                                        unsigned long size)
-{
-       struct acpi_iomap *map;
-
-       map = __acpi_find_iomap(paddr, size/8);
-       if (map)
-               return map->vaddr + (paddr - map->paddr);
-       else
-               return NULL;
-}
-
-/* acpi_iomaps_lock must be held before calling */
-static void __iomem *__acpi_try_ioremap(phys_addr_t paddr,
-                                       unsigned long size)
-{
-       struct acpi_iomap *map;
-
-       map = __acpi_find_iomap(paddr, size);
-       if (map) {
-               kref_get(&map->ref);
-               return map->vaddr + (paddr - map->paddr);
-       } else
-               return NULL;
-}
-
-/*
- * Used to pre-map the specified IO memory area. First try to find
- * whether the area is already pre-mapped, if it is, increase the
- * reference count (in __acpi_try_ioremap) and return; otherwise, do
- * the real ioremap, and add the mapping into acpi_iomaps list.
- */
-static void __iomem *acpi_pre_map(phys_addr_t paddr,
-                                 unsigned long size)
-{
-       void __iomem *vaddr;
-       struct acpi_iomap *map;
-       unsigned long pg_sz, flags;
-       phys_addr_t pg_off;
-
-       spin_lock_irqsave(&acpi_iomaps_lock, flags);
-       vaddr = __acpi_try_ioremap(paddr, size);
-       spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-       if (vaddr)
-               return vaddr;
-
-       pg_off = paddr & PAGE_MASK;
-       pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off;
-       vaddr = ioremap(pg_off, pg_sz);
-       if (!vaddr)
-               return NULL;
-       map = kmalloc(sizeof(*map), GFP_KERNEL);
-       if (!map)
-               goto err_unmap;
-       INIT_LIST_HEAD(&map->list);
-       map->paddr = pg_off;
-       map->size = pg_sz;
-       map->vaddr = vaddr;
-       kref_init(&map->ref);
-
-       spin_lock_irqsave(&acpi_iomaps_lock, flags);
-       vaddr = __acpi_try_ioremap(paddr, size);
-       if (vaddr) {
-               spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-               iounmap(map->vaddr);
-               kfree(map);
-               return vaddr;
-       }
-       list_add_tail_rcu(&map->list, &acpi_iomaps);
-       spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-
-       return map->vaddr + (paddr - map->paddr);
-err_unmap:
-       iounmap(vaddr);
-       return NULL;
-}
-
-/* acpi_iomaps_lock must be held before calling */
-static void __acpi_kref_del_iomap(struct kref *ref)
-{
-       struct acpi_iomap *map;
-
-       map = container_of(ref, struct acpi_iomap, ref);
-       list_del_rcu(&map->list);
-}
-
-/*
- * Used to post-unmap the specified IO memory area. The iounmap is
- * done only if the reference count goes zero.
- */
-static void acpi_post_unmap(phys_addr_t paddr, unsigned long size)
-{
-       struct acpi_iomap *map;
-       unsigned long flags;
-       int del;
-
-       spin_lock_irqsave(&acpi_iomaps_lock, flags);
-       map = __acpi_find_iomap(paddr, size);
-       BUG_ON(!map);
-       del = kref_put(&map->ref, __acpi_kref_del_iomap);
-       spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-
-       if (!del)
-               return;
-
-       synchronize_rcu();
-       iounmap(map->vaddr);
-       kfree(map);
-}
-
-/* In NMI handler, should set silent = 1 */
-static int acpi_check_gar(struct acpi_generic_address *reg,
-                         u64 *paddr, int silent)
-{
-       u32 width, space_id;
-
-       width = reg->bit_width;
-       space_id = reg->space_id;
-       /* Handle possible alignment issues */
-       memcpy(paddr, &reg->address, sizeof(*paddr));
-       if (!*paddr) {
-               if (!silent)
-                       pr_warning(FW_BUG ACPI_PFX
-                       "Invalid physical address in GAR [0x%llx/%u/%u]\n",
-                                  *paddr, width, space_id);
-               return -EINVAL;
-       }
-
-       if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
-               if (!silent)
-                       pr_warning(FW_BUG ACPI_PFX
-                                  "Invalid bit width in GAR [0x%llx/%u/%u]\n",
-                                  *paddr, width, space_id);
-               return -EINVAL;
-       }
-
-       if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
-           space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
-               if (!silent)
-                       pr_warning(FW_BUG ACPI_PFX
-                       "Invalid address space type in GAR [0x%llx/%u/%u]\n",
-                                  *paddr, width, space_id);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* Pre-map, working on GAR */
-int acpi_pre_map_gar(struct acpi_generic_address *reg)
-{
-       u64 paddr;
-       void __iomem *vaddr;
-       int rc;
-
-       if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
-               return 0;
-
-       rc = acpi_check_gar(reg, &paddr, 0);
-       if (rc)
-               return rc;
-
-       vaddr = acpi_pre_map(paddr, reg->bit_width / 8);
-       if (!vaddr)
-               return -EIO;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(acpi_pre_map_gar);
-
-/* Post-unmap, working on GAR */
-int acpi_post_unmap_gar(struct acpi_generic_address *reg)
-{
-       u64 paddr;
-       int rc;
-
-       if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
-               return 0;
-
-       rc = acpi_check_gar(reg, &paddr, 0);
-       if (rc)
-               return rc;
-
-       acpi_post_unmap(paddr, reg->bit_width / 8);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(acpi_post_unmap_gar);
-
-/*
- * Can be used in atomic (including NMI) or process context. RCU read
- * lock can only be released after the IO memory area accessing.
- */
-static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width)
-{
-       void __iomem *addr;
-
-       rcu_read_lock();
-       addr = __acpi_ioremap_fast(paddr, width);
-       switch (width) {
-       case 8:
-               *val = readb(addr);
-               break;
-       case 16:
-               *val = readw(addr);
-               break;
-       case 32:
-               *val = readl(addr);
-               break;
-#ifdef readq
-       case 64:
-               *val = readq(addr);
-               break;
-#endif
-       default:
-               return -EINVAL;
-       }
-       rcu_read_unlock();
-
-       return 0;
-}
-
-static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width)
-{
-       void __iomem *addr;
-
-       rcu_read_lock();
-       addr = __acpi_ioremap_fast(paddr, width);
-       switch (width) {
-       case 8:
-               writeb(val, addr);
-               break;
-       case 16:
-               writew(val, addr);
-               break;
-       case 32:
-               writel(val, addr);
-               break;
-#ifdef writeq
-       case 64:
-               writeq(val, addr);
-               break;
-#endif
-       default:
-               return -EINVAL;
-       }
-       rcu_read_unlock();
-
-       return 0;
-}
-
-/* GAR accessing in atomic (including NMI) or process context */
-int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg)
-{
-       u64 paddr;
-       int rc;
-
-       rc = acpi_check_gar(reg, &paddr, 1);
-       if (rc)
-               return rc;
-
-       *val = 0;
-       switch (reg->space_id) {
-       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-               return acpi_atomic_read_mem(paddr, val, reg->bit_width);
-       case ACPI_ADR_SPACE_SYSTEM_IO:
-               return acpi_os_read_port(paddr, (u32 *)val, reg->bit_width);
-       default:
-               return -EINVAL;
-       }
-}
-EXPORT_SYMBOL_GPL(acpi_atomic_read);
-
-int acpi_atomic_write(u64 val, struct acpi_generic_address *reg)
-{
-       u64 paddr;
-       int rc;
-
-       rc = acpi_check_gar(reg, &paddr, 1);
-       if (rc)
-               return rc;
-
-       switch (reg->space_id) {
-       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-               return acpi_atomic_write_mem(paddr, val, reg->bit_width);
-       case ACPI_ADR_SPACE_SYSTEM_IO:
-               return acpi_os_write_port(paddr, val, reg->bit_width);
-       default:
-               return -EINVAL;
-       }
-}
-EXPORT_SYMBOL_GPL(acpi_atomic_write);
index 3b5c3189fd995e4cc200c532b2d05ba6b274fac7..e56f3be7b07d36fceb32dce25ede0fa35308f0e7 100644 (file)
@@ -45,6 +45,8 @@ static int pxm_to_node_map[MAX_PXM_DOMAINS]
 static int node_to_pxm_map[MAX_NUMNODES]
                        = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
+unsigned char acpi_srat_revision __initdata;
+
 int pxm_to_node(int pxm)
 {
        if (pxm < 0)
@@ -255,9 +257,13 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header,
 
 static int __init acpi_parse_srat(struct acpi_table_header *table)
 {
+       struct acpi_table_srat *srat;
        if (!table)
                return -EINVAL;
 
+       srat = (struct acpi_table_srat *)table;
+       acpi_srat_revision = srat->header.revision;
+
        /* Real work done in acpi_table_parse_srat below. */
 
        return 0;
index 096787b43c960a71afd971ed8f312ba39e7787a9..7a2035fa8c713d660a697d0d49e0a430476ed9fa 100644 (file)
 #include <linux/acpi_io.h>
 #include <acpi/acpiosxf.h>
 
+/* ACPI NVS regions, APEI may use it */
+
+struct nvs_region {
+       __u64 phys_start;
+       __u64 size;
+       struct list_head node;
+};
+
+static LIST_HEAD(nvs_region_list);
+
+#ifdef CONFIG_ACPI_SLEEP
+static int suspend_nvs_register(unsigned long start, unsigned long size);
+#else
+static inline int suspend_nvs_register(unsigned long a, unsigned long b)
+{
+       return 0;
+}
+#endif
+
+int acpi_nvs_register(__u64 start, __u64 size)
+{
+       struct nvs_region *region;
+
+       region = kmalloc(sizeof(*region), GFP_KERNEL);
+       if (!region)
+               return -ENOMEM;
+       region->phys_start = start;
+       region->size = size;
+       list_add_tail(&region->node, &nvs_region_list);
+
+       return suspend_nvs_register(start, size);
+}
+
+int acpi_nvs_for_each_region(int (*func)(__u64 start, __u64 size, void *data),
+                            void *data)
+{
+       int rc;
+       struct nvs_region *region;
+
+       list_for_each_entry(region, &nvs_region_list, node) {
+               rc = func(region->phys_start, region->size, data);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+
+#ifdef CONFIG_ACPI_SLEEP
 /*
  * Platforms, like ACPI, may want us to save some memory used by them during
  * suspend and to restore the contents of this memory during the subsequent
@@ -41,7 +91,7 @@ static LIST_HEAD(nvs_list);
  *     things so that the data from page-aligned addresses in this region will
  *     be copied into separate RAM pages.
  */
-int suspend_nvs_register(unsigned long start, unsigned long size)
+static int suspend_nvs_register(unsigned long start, unsigned long size)
 {
        struct nvs_page *entry, *next;
 
@@ -159,3 +209,4 @@ void suspend_nvs_restore(void)
                if (entry->data)
                        memcpy(entry->kaddr, entry->data, entry->size);
 }
+#endif
index f31c5c5f1b7e083351e013649f1e1d73fdd74fa6..412a1e04a9226a84970654c433597455cb53f0ca 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
@@ -83,19 +84,6 @@ static struct workqueue_struct *kacpi_notify_wq;
 struct workqueue_struct *kacpi_hotplug_wq;
 EXPORT_SYMBOL(kacpi_hotplug_wq);
 
-struct acpi_res_list {
-       resource_size_t start;
-       resource_size_t end;
-       acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
-       char name[5];   /* only can have a length of 4 chars, make use of this
-                          one instead of res->name, no need to kalloc then */
-       struct list_head resource_list;
-       int count;
-};
-
-static LIST_HEAD(resource_list_head);
-static DEFINE_SPINLOCK(acpi_res_lock);
-
 /*
  * This list of permanent mappings is for memory that may be accessed from
  * interrupt context, where we can't do the ioremap().
@@ -166,17 +154,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
        return supported;
 }
 
-static void __init acpi_request_region (struct acpi_generic_address *addr,
+static void __init acpi_request_region (struct acpi_generic_address *gas,
        unsigned int length, char *desc)
 {
-       if (!addr->address || !length)
+       u64 addr;
+
+       /* Handle possible alignment issues */
+       memcpy(&addr, &gas->address, sizeof(addr));
+       if (!addr || !length)
                return;
 
        /* Resources are never freed */
-       if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
-               request_region(addr->address, length, desc);
-       else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
-               request_mem_region(addr->address, length, desc);
+       if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
+               request_region(addr, length, desc);
+       else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+               request_mem_region(addr, length, desc);
 }
 
 static int __init acpi_reserve_resources(void)
@@ -330,6 +322,37 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
        return NULL;
 }
 
+#ifndef CONFIG_IA64
+#define should_use_kmap(pfn)   page_is_ram(pfn)
+#else
+/* ioremap will take care of cache attributes */
+#define should_use_kmap(pfn)   0
+#endif
+
+static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
+{
+       unsigned long pfn;
+
+       pfn = pg_off >> PAGE_SHIFT;
+       if (should_use_kmap(pfn)) {
+               if (pg_sz > PAGE_SIZE)
+                       return NULL;
+               return (void __iomem __force *)kmap(pfn_to_page(pfn));
+       } else
+               return acpi_os_ioremap(pg_off, pg_sz);
+}
+
+static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
+{
+       unsigned long pfn;
+
+       pfn = pg_off >> PAGE_SHIFT;
+       if (page_is_ram(pfn))
+               kunmap(pfn_to_page(pfn));
+       else
+               iounmap(vaddr);
+}
+
 void __iomem *__init_refok
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
@@ -362,7 +385,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 
        pg_off = round_down(phys, PAGE_SIZE);
        pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
-       virt = acpi_os_ioremap(pg_off, pg_sz);
+       virt = acpi_map(pg_off, pg_sz);
        if (!virt) {
                mutex_unlock(&acpi_ioremap_lock);
                kfree(map);
@@ -393,7 +416,7 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map)
 {
        if (!map->refcount) {
                synchronize_rcu();
-               iounmap(map->virt);
+               acpi_unmap(map->phys, map->virt);
                kfree(map);
        }
 }
@@ -427,35 +450,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
                __acpi_unmap_table(virt, size);
 }
 
-static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+int acpi_os_map_generic_address(struct acpi_generic_address *gas)
 {
+       u64 addr;
        void __iomem *virt;
 
-       if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+       if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
                return 0;
 
-       if (!addr->address || !addr->bit_width)
+       /* Handle possible alignment issues */
+       memcpy(&addr, &gas->address, sizeof(addr));
+       if (!addr || !gas->bit_width)
                return -EINVAL;
 
-       virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
+       virt = acpi_os_map_memory(addr, gas->bit_width / 8);
        if (!virt)
                return -EIO;
 
        return 0;
 }
+EXPORT_SYMBOL(acpi_os_map_generic_address);
 
-static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+void acpi_os_unmap_generic_address(struct acpi_generic_address *gas)
 {
+       u64 addr;
        struct acpi_ioremap *map;
 
-       if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+       if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
                return;
 
-       if (!addr->address || !addr->bit_width)
+       /* Handle possible alignment issues */
+       memcpy(&addr, &gas->address, sizeof(addr));
+       if (!addr || !gas->bit_width)
                return;
 
        mutex_lock(&acpi_ioremap_lock);
-       map = acpi_map_lookup(addr->address, addr->bit_width / 8);
+       map = acpi_map_lookup(addr, gas->bit_width / 8);
        if (!map) {
                mutex_unlock(&acpi_ioremap_lock);
                return;
@@ -465,6 +495,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 
        acpi_os_map_cleanup(map);
 }
+EXPORT_SYMBOL(acpi_os_unmap_generic_address);
 
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
@@ -711,6 +742,67 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
        return AE_OK;
 }
 
+#ifdef readq
+static inline u64 read64(const volatile void __iomem *addr)
+{
+       return readq(addr);
+}
+#else
+static inline u64 read64(const volatile void __iomem *addr)
+{
+       u64 l, h;
+       l = readl(addr);
+       h = readl(addr+4);
+       return l | (h << 32);
+}
+#endif
+
+acpi_status
+acpi_os_read_memory64(acpi_physical_address phys_addr, u64 *value, u32 width)
+{
+       void __iomem *virt_addr;
+       unsigned int size = width / 8;
+       bool unmap = false;
+       u64 dummy;
+
+       rcu_read_lock();
+       virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+       if (!virt_addr) {
+               rcu_read_unlock();
+               virt_addr = acpi_os_ioremap(phys_addr, size);
+               if (!virt_addr)
+                       return AE_BAD_ADDRESS;
+               unmap = true;
+       }
+
+       if (!value)
+               value = &dummy;
+
+       switch (width) {
+       case 8:
+               *(u8 *) value = readb(virt_addr);
+               break;
+       case 16:
+               *(u16 *) value = readw(virt_addr);
+               break;
+       case 32:
+               *(u32 *) value = readl(virt_addr);
+               break;
+       case 64:
+               *(u64 *) value = read64(virt_addr);
+               break;
+       default:
+               BUG();
+       }
+
+       if (unmap)
+               iounmap(virt_addr);
+       else
+               rcu_read_unlock();
+
+       return AE_OK;
+}
+
 acpi_status
 acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
 {
@@ -750,6 +842,61 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
        return AE_OK;
 }
 
+#ifdef writeq
+static inline void write64(u64 val, volatile void __iomem *addr)
+{
+       writeq(val, addr);
+}
+#else
+static inline void write64(u64 val, volatile void __iomem *addr)
+{
+       writel(val, addr);
+       writel(val>>32, addr+4);
+}
+#endif
+
+acpi_status
+acpi_os_write_memory64(acpi_physical_address phys_addr, u64 value, u32 width)
+{
+       void __iomem *virt_addr;
+       unsigned int size = width / 8;
+       bool unmap = false;
+
+       rcu_read_lock();
+       virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+       if (!virt_addr) {
+               rcu_read_unlock();
+               virt_addr = acpi_os_ioremap(phys_addr, size);
+               if (!virt_addr)
+                       return AE_BAD_ADDRESS;
+               unmap = true;
+       }
+
+       switch (width) {
+       case 8:
+               writeb(value, virt_addr);
+               break;
+       case 16:
+               writew(value, virt_addr);
+               break;
+       case 32:
+               writel(value, virt_addr);
+               break;
+       case 64:
+               write64(value, virt_addr);
+               break;
+       default:
+               BUG();
+       }
+
+       if (unmap)
+               iounmap(virt_addr);
+       else
+               rcu_read_unlock();
+
+       return AE_OK;
+}
+
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
                               u64 *value, u32 width)
@@ -1278,44 +1425,28 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
  * drivers */
 int acpi_check_resource_conflict(const struct resource *res)
 {
-       struct acpi_res_list *res_list_elem;
-       int ioport = 0, clash = 0;
+       acpi_adr_space_type space_id;
+       acpi_size length;
+       u8 warn = 0;
+       int clash = 0;
 
        if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
                return 0;
        if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
                return 0;
 
-       ioport = res->flags & IORESOURCE_IO;
-
-       spin_lock(&acpi_res_lock);
-       list_for_each_entry(res_list_elem, &resource_list_head,
-                           resource_list) {
-               if (ioport && (res_list_elem->resource_type
-                              != ACPI_ADR_SPACE_SYSTEM_IO))
-                       continue;
-               if (!ioport && (res_list_elem->resource_type
-                               != ACPI_ADR_SPACE_SYSTEM_MEMORY))
-                       continue;
+       if (res->flags & IORESOURCE_IO)
+               space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+       else
+               space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
 
-               if (res->end < res_list_elem->start
-                   || res_list_elem->end < res->start)
-                       continue;
-               clash = 1;
-               break;
-       }
-       spin_unlock(&acpi_res_lock);
+       length = res->end - res->start + 1;
+       if (acpi_enforce_resources != ENFORCE_RESOURCES_NO)
+               warn = 1;
+       clash = acpi_check_address_range(space_id, res->start, length, warn);
 
        if (clash) {
                if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
-                       printk(KERN_WARNING "ACPI: resource %s %pR"
-                              " conflicts with ACPI region %s "
-                              "[%s 0x%zx-0x%zx]\n",
-                              res->name, res, res_list_elem->name,
-                              (res_list_elem->resource_type ==
-                               ACPI_ADR_SPACE_SYSTEM_IO) ? "io" : "mem",
-                              (size_t) res_list_elem->start,
-                              (size_t) res_list_elem->end);
                        if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
                                printk(KERN_NOTICE "ACPI: This conflict may"
                                       " cause random problems and system"
@@ -1467,155 +1598,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
        kmem_cache_free(cache, object);
        return (AE_OK);
 }
-
-static inline int acpi_res_list_add(struct acpi_res_list *res)
-{
-       struct acpi_res_list *res_list_elem;
-
-       list_for_each_entry(res_list_elem, &resource_list_head,
-                           resource_list) {
-
-               if (res->resource_type == res_list_elem->resource_type &&
-                   res->start == res_list_elem->start &&
-                   res->end == res_list_elem->end) {
-
-                       /*
-                        * The Region(addr,len) already exist in the list,
-                        * just increase the count
-                        */
-
-                       res_list_elem->count++;
-                       return 0;
-               }
-       }
-
-       res->count = 1;
-       list_add(&res->resource_list, &resource_list_head);
-       return 1;
-}
-
-static inline void acpi_res_list_del(struct acpi_res_list *res)
-{
-       struct acpi_res_list *res_list_elem;
-
-       list_for_each_entry(res_list_elem, &resource_list_head,
-                           resource_list) {
-
-               if (res->resource_type == res_list_elem->resource_type &&
-                   res->start == res_list_elem->start &&
-                   res->end == res_list_elem->end) {
-
-                       /*
-                        * If the res count is decreased to 0,
-                        * remove and free it
-                        */
-
-                       if (--res_list_elem->count == 0) {
-                               list_del(&res_list_elem->resource_list);
-                               kfree(res_list_elem);
-                       }
-                       return;
-               }
-       }
-}
-
-acpi_status
-acpi_os_invalidate_address(
-    u8                   space_id,
-    acpi_physical_address   address,
-    acpi_size               length)
-{
-       struct acpi_res_list res;
-
-       switch (space_id) {
-       case ACPI_ADR_SPACE_SYSTEM_IO:
-       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-               /* Only interference checks against SystemIO and SystemMemory
-                  are needed */
-               res.start = address;
-               res.end = address + length - 1;
-               res.resource_type = space_id;
-               spin_lock(&acpi_res_lock);
-               acpi_res_list_del(&res);
-               spin_unlock(&acpi_res_lock);
-               break;
-       case ACPI_ADR_SPACE_PCI_CONFIG:
-       case ACPI_ADR_SPACE_EC:
-       case ACPI_ADR_SPACE_SMBUS:
-       case ACPI_ADR_SPACE_CMOS:
-       case ACPI_ADR_SPACE_PCI_BAR_TARGET:
-       case ACPI_ADR_SPACE_DATA_TABLE:
-       case ACPI_ADR_SPACE_FIXED_HARDWARE:
-               break;
-       }
-       return AE_OK;
-}
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_os_validate_address
- *
- * PARAMETERS:  space_id             - ACPI space ID
- *              address             - Physical address
- *              length              - Address length
- *
- * RETURN:      AE_OK if address/length is valid for the space_id. Otherwise,
- *              should return AE_AML_ILLEGAL_ADDRESS.
- *
- * DESCRIPTION: Validate a system address via the host OS. Used to validate
- *              the addresses accessed by AML operation regions.
- *
- *****************************************************************************/
-
-acpi_status
-acpi_os_validate_address (
-    u8                   space_id,
-    acpi_physical_address   address,
-    acpi_size               length,
-    char *name)
-{
-       struct acpi_res_list *res;
-       int added;
-       if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
-               return AE_OK;
-
-       switch (space_id) {
-       case ACPI_ADR_SPACE_SYSTEM_IO:
-       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-               /* Only interference checks against SystemIO and SystemMemory
-                  are needed */
-               res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
-               if (!res)
-                       return AE_OK;
-               /* ACPI names are fixed to 4 bytes, still better use strlcpy */
-               strlcpy(res->name, name, 5);
-               res->start = address;
-               res->end = address + length - 1;
-               res->resource_type = space_id;
-               spin_lock(&acpi_res_lock);
-               added = acpi_res_list_add(res);
-               spin_unlock(&acpi_res_lock);
-               pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
-                        "name: %s\n", added ? "Added" : "Already exist",
-                        (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
-                        ? "SystemIO" : "System Memory",
-                        (unsigned long long)res->start,
-                        (unsigned long long)res->end,
-                        res->name);
-               if (!added)
-                       kfree(res);
-               break;
-       case ACPI_ADR_SPACE_PCI_CONFIG:
-       case ACPI_ADR_SPACE_EC:
-       case ACPI_ADR_SPACE_SMBUS:
-       case ACPI_ADR_SPACE_CMOS:
-       case ACPI_ADR_SPACE_PCI_BAR_TARGET:
-       case ACPI_ADR_SPACE_DATA_TABLE:
-       case ACPI_ADR_SPACE_FIXED_HARDWARE:
-               break;
-       }
-       return AE_OK;
-}
 #endif
 
 acpi_status __init acpi_os_initialize(void)
index 3a0428e8435c0fcb0221540ded7f20d731d764ae..c850de4c9a146883a7d91f16c8cd8ddc3b694940 100644 (file)
@@ -173,8 +173,30 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
        apic_id = map_mat_entry(handle, type, acpi_id);
        if (apic_id == -1)
                apic_id = map_madt_entry(type, acpi_id);
-       if (apic_id == -1)
-               return apic_id;
+       if (apic_id == -1) {
+               /*
+                * On UP processor, there is no _MAT or MADT table.
+                * So above apic_id is always set to -1.
+                *
+                * BIOS may define multiple CPU handles even for UP processor.
+                * For example,
+                *
+                * Scope (_PR)
+                 * {
+                *     Processor (CPU0, 0x00, 0x00000410, 0x06) {}
+                *     Processor (CPU1, 0x01, 0x00000410, 0x06) {}
+                *     Processor (CPU2, 0x02, 0x00000410, 0x06) {}
+                *     Processor (CPU3, 0x03, 0x00000410, 0x06) {}
+                * }
+                *
+                * Ignores apic_id and always return 0 for CPU0's handle.
+                * Return -1 for other CPU's handle.
+                */
+               if (acpi_id == 0)
+                       return acpi_id;
+               else
+                       return apic_id;
+       }
 
 #ifdef CONFIG_SMP
        for_each_possible_cpu(i) {
index 20a68ca386de033dac092e74541f66f78cb21466..8ae05ce18500092baadd8938f56ef5822d6603c8 100644 (file)
@@ -82,9 +82,9 @@ MODULE_LICENSE("GPL");
 static int acpi_processor_add(struct acpi_device *device);
 static int acpi_processor_remove(struct acpi_device *device, int type);
 static void acpi_processor_notify(struct acpi_device *device, u32 event);
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
+static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr);
 static int acpi_processor_handle_eject(struct acpi_processor *pr);
-
+static int acpi_processor_start(struct acpi_processor *pr);
 
 static const struct acpi_device_id processor_device_ids[] = {
        {ACPI_PROCESSOR_OBJECT_HID, 0},
@@ -324,10 +324,8 @@ static int acpi_processor_get_info(struct acpi_device *device)
         *  they are physically not present.
         */
        if (pr->id == -1) {
-               if (ACPI_FAILURE
-                   (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+               if (ACPI_FAILURE(acpi_processor_hotadd_init(pr)))
                        return -ENODEV;
-               }
        }
        /*
         * On some boxes several processors use the same processor bus id.
@@ -425,10 +423,29 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
        struct acpi_processor *pr = per_cpu(processors, cpu);
 
        if (action == CPU_ONLINE && pr) {
-               acpi_processor_ppc_has_changed(pr, 0);
-               acpi_processor_hotplug(pr);
-               acpi_processor_reevaluate_tstate(pr, action);
-               acpi_processor_tstate_has_changed(pr);
+               /* CPU got physically hotplugged and onlined the first time:
+                * Initialize missing things
+                */
+               if (pr->flags.need_hotplug_init) {
+                       struct cpuidle_driver *idle_driver =
+                               cpuidle_get_driver();
+
+                       printk(KERN_INFO "Will online and init hotplugged "
+                              "CPU: %d\n", pr->id);
+                       WARN(acpi_processor_start(pr), "Failed to start CPU:"
+                               " %d\n", pr->id);
+                       pr->flags.need_hotplug_init = 0;
+                       if (idle_driver && !strcmp(idle_driver->name,
+                                                  "intel_idle")) {
+                               intel_idle_cpu_init(pr->id);
+                       }
+               /* Normal CPU soft online event */
+               } else {
+                       acpi_processor_ppc_has_changed(pr, 0);
+                       acpi_processor_cst_has_changed(pr);
+                       acpi_processor_reevaluate_tstate(pr, action);
+                       acpi_processor_tstate_has_changed(pr);
+               }
        }
        if (action == CPU_DEAD && pr) {
                /* invalidate the flag.throttling after one CPU is offline */
@@ -442,6 +459,71 @@ static struct notifier_block acpi_cpu_notifier =
            .notifier_call = acpi_cpu_soft_notify,
 };
 
+/*
+ * acpi_processor_start() is called by the cpu_hotplug_notifier func:
+ * acpi_cpu_soft_notify(). Getting it __cpuinit{data} is difficult, the
+ * root cause seem to be that acpi_processor_uninstall_hotplug_notify()
+ * is in the module_exit (__exit) func. Allowing acpi_processor_start()
+ * to not be in __cpuinit section, but being called from __cpuinit funcs
+ * via __ref looks like the right thing to do here.
+ */
+static __ref int acpi_processor_start(struct acpi_processor *pr)
+{
+       struct acpi_device *device = per_cpu(processor_device_array, pr->id);
+       int result = 0;
+
+#ifdef CONFIG_CPU_FREQ
+       acpi_processor_ppc_has_changed(pr, 0);
+#endif
+       acpi_processor_get_throttling_info(pr);
+       acpi_processor_get_limit_info(pr);
+
+       if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
+               acpi_processor_power_init(pr, device);
+
+       pr->cdev = thermal_cooling_device_register("Processor", device,
+                                                  &processor_cooling_ops);
+       if (IS_ERR(pr->cdev)) {
+               result = PTR_ERR(pr->cdev);
+               goto err_power_exit;
+       }
+
+       dev_dbg(&device->dev, "registered as cooling_device%d\n",
+               pr->cdev->id);
+
+       result = sysfs_create_link(&device->dev.kobj,
+                                  &pr->cdev->device.kobj,
+                                  "thermal_cooling");
+       if (result) {
+               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               goto err_thermal_unregister;
+       }
+       result = sysfs_create_link(&pr->cdev->device.kobj,
+                                  &device->dev.kobj,
+                                  "device");
+       if (result) {
+               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               goto err_remove_sysfs_thermal;
+       }
+
+       return 0;
+
+err_remove_sysfs_thermal:
+       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+       thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+       acpi_processor_power_exit(pr, device);
+
+       return result;
+}
+
+/*
+ * Do not put anything in here which needs the core to be online.
+ * For example MSR access or setting up things which check for cpuinfo_x86
+ * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
+ * Such things have to be put in and set up above in acpi_processor_start()
+ */
 static int __cpuinit acpi_processor_add(struct acpi_device *device)
 {
        struct acpi_processor *pr = NULL;
@@ -497,48 +579,21 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
                goto err_free_cpumask;
        }
 
-#ifdef CONFIG_CPU_FREQ
-       acpi_processor_ppc_has_changed(pr, 0);
-#endif
-       acpi_processor_get_throttling_info(pr);
-       acpi_processor_get_limit_info(pr);
-
-       if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
-               acpi_processor_power_init(pr, device);
-
-       pr->cdev = thermal_cooling_device_register("Processor", device,
-                                               &processor_cooling_ops);
-       if (IS_ERR(pr->cdev)) {
-               result = PTR_ERR(pr->cdev);
-               goto err_power_exit;
-       }
-
-       dev_dbg(&device->dev, "registered as cooling_device%d\n",
-                pr->cdev->id);
+       /*
+        * Do not start hotplugged CPUs now, but when they
+        * are onlined the first time
+        */
+       if (pr->flags.need_hotplug_init)
+               return 0;
 
-       result = sysfs_create_link(&device->dev.kobj,
-                                  &pr->cdev->device.kobj,
-                                  "thermal_cooling");
-       if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
-               goto err_thermal_unregister;
-       }
-       result = sysfs_create_link(&pr->cdev->device.kobj,
-                                  &device->dev.kobj,
-                                  "device");
-       if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
+       result = acpi_processor_start(pr);
+       if (result)
                goto err_remove_sysfs;
-       }
 
        return 0;
 
 err_remove_sysfs:
-       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-err_thermal_unregister:
-       thermal_cooling_device_unregister(pr->cdev);
-err_power_exit:
-       acpi_processor_power_exit(pr, device);
+       sysfs_remove_link(&device->dev.kobj, "sysdev");
 err_free_cpumask:
        free_cpumask_var(pr->throttling.shared_cpu_map);
 
@@ -720,21 +775,33 @@ processor_walk_namespace_cb(acpi_handle handle,
        return (AE_OK);
 }
 
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
 {
+       acpi_handle handle = pr->handle;
 
        if (!is_processor_present(handle)) {
                return AE_ERROR;
        }
 
-       if (acpi_map_lsapic(handle, p_cpu))
+       if (acpi_map_lsapic(handle, &pr->id))
                return AE_ERROR;
 
-       if (arch_register_cpu(*p_cpu)) {
-               acpi_unmap_lsapic(*p_cpu);
+       if (arch_register_cpu(pr->id)) {
+               acpi_unmap_lsapic(pr->id);
                return AE_ERROR;
        }
 
+       /* CPU got hot-plugged, but cpu_data is not initialized yet
+        * Set flag to delay cpu_idle/throttling initialization
+        * in:
+        * acpi_processor_add()
+        *   acpi_processor_get_info()
+        * and do it when the CPU gets online the first time
+        * TBD: Cleanup above functions and try to do this more elegant.
+        */
+       printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
+       pr->flags.need_hotplug_init = 1;
+
        return AE_OK;
 }
 
@@ -748,7 +815,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
        return (0);
 }
 #else
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
 {
        return AE_ERROR;
 }
@@ -827,8 +894,6 @@ static void __exit acpi_processor_exit(void)
 
        acpi_bus_unregister_driver(&acpi_processor_driver);
 
-       cpuidle_unregister_driver(&acpi_idle_driver);
-
        return;
 }
 
index 0a7ed69546ba47db0c322542864c168068baa7f4..ca191ff978444c2fedf09aa950f8b26d327befbd 100644 (file)
@@ -438,6 +438,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
        },
        {
        .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCCW29FX",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
        .ident = "Averatec AV1020-ED2",
        .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
index 69ac373c72abfc41e53304c0a8e2c7bb4fbf4e5c..fdf27b9fce43a882b706bf5148cd51a6a67f4f83 100644 (file)
@@ -1116,6 +1116,13 @@ static int piix_broken_suspend(void)
                                DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"),
                        },
                },
+               {
+                       .ident = "Satellite Pro A120",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "Satellite Pro A120"),
+                       },
+               },
                {
                        .ident = "Portege M500",
                        .matches = {
index 11c9aea4f4f7ea93a50fdc4b3547323d3728738d..c06e0ec11556d7696b620fa0b32e5af508863052 100644 (file)
@@ -4125,6 +4125,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
         * device and controller are SATA.
         */
        { "PIONEER DVD-RW  DVRTD08",    NULL,   ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVRTD08A",   NULL,   ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVR-215",    NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
index 9a7f0ea565df6c6066d7e64465c8385b81014a01..74aaee30e264ce1959c3807cb6a9e4c8bad27c95 100644 (file)
@@ -291,6 +291,7 @@ int ata_tport_add(struct device *parent,
                goto tport_err;
        }
 
+       device_enable_async_suspend(dev);
        pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
 
index a7d91a72ee352b45ca71cf1bd2ccb738890f1075..53d3770a0b1b8b3e101a10d221fef1d202ddf4d4 100644 (file)
@@ -207,11 +207,11 @@ static void set_smc_timing(struct device *dev, struct ata_device *adev,
 {
        int ret = 0;
        int use_iordy;
+       struct sam9_smc_config smc;
        unsigned int t6z;         /* data tristate time in ns */
        unsigned int cycle;       /* SMC Cycle width in MCK ticks */
        unsigned int setup;       /* SMC Setup width in MCK ticks */
        unsigned int pulse;       /* CFIOR and CFIOW pulse width in MCK ticks */
-       unsigned int cs_setup = 0;/* CS4 or CS5 setup width in MCK ticks */
        unsigned int cs_pulse;    /* CS4 or CS5 pulse width in MCK ticks*/
        unsigned int tdf_cycles;  /* SMC TDF MCK ticks */
        unsigned long mck_hz;     /* MCK frequency in Hz */
@@ -244,26 +244,20 @@ static void set_smc_timing(struct device *dev, struct ata_device *adev,
        }
 
        dev_dbg(dev, "Use IORDY=%u, TDF Cycles=%u\n", use_iordy, tdf_cycles);
-       info->mode |= AT91_SMC_TDF_(tdf_cycles);
-
-       /* write SMC Setup Register */
-       at91_sys_write(AT91_SMC_SETUP(info->cs),
-                       AT91_SMC_NWESETUP_(setup) |
-                       AT91_SMC_NRDSETUP_(setup) |
-                       AT91_SMC_NCS_WRSETUP_(cs_setup) |
-                       AT91_SMC_NCS_RDSETUP_(cs_setup));
-       /* write SMC Pulse Register */
-       at91_sys_write(AT91_SMC_PULSE(info->cs),
-                       AT91_SMC_NWEPULSE_(pulse) |
-                       AT91_SMC_NRDPULSE_(pulse) |
-                       AT91_SMC_NCS_WRPULSE_(cs_pulse) |
-                       AT91_SMC_NCS_RDPULSE_(cs_pulse));
-       /* write SMC Cycle Register */
-       at91_sys_write(AT91_SMC_CYCLE(info->cs),
-                       AT91_SMC_NWECYCLE_(cycle) |
-                       AT91_SMC_NRDCYCLE_(cycle));
-       /* write SMC Mode Register*/
-       at91_sys_write(AT91_SMC_MODE(info->cs), info->mode);
+
+       /* SMC Setup Register */
+       smc.nwe_setup = smc.nrd_setup = setup;
+       smc.ncs_write_setup = smc.ncs_read_setup = 0;
+       /* SMC Pulse Register */
+       smc.nwe_pulse = smc.nrd_pulse = pulse;
+       smc.ncs_write_pulse = smc.ncs_read_pulse = cs_pulse;
+       /* SMC Cycle Register */
+       smc.write_cycle = smc.read_cycle = cycle;
+       /* SMC Mode Register*/
+       smc.tdf_cycles = tdf_cycles;
+       smc.mode = info->mode;
+
+       sam9_smc_configure(0, info->cs, &smc);
 }
 
 static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev)
@@ -288,20 +282,20 @@ static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev,
        struct at91_ide_info *info = dev->link->ap->host->private_data;
        unsigned int consumed;
        unsigned long flags;
-       unsigned int mode;
+       struct sam9_smc_config smc;
 
        local_irq_save(flags);
-       mode = at91_sys_read(AT91_SMC_MODE(info->cs));
+       sam9_smc_read_mode(0, info->cs, &smc);
 
        /* set 16bit mode before writing data */
-       at91_sys_write(AT91_SMC_MODE(info->cs),
-                       (mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16);
+       smc.mode = (smc.mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16;
+       sam9_smc_write_mode(0, info->cs, &smc);
 
        consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
 
        /* restore 8bit mode after data is written */
-       at91_sys_write(AT91_SMC_MODE(info->cs),
-                       (mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8);
+       smc.mode = (smc.mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8;
+       sam9_smc_write_mode(0, info->cs, &smc);
 
        local_irq_restore(flags);
        return consumed;
index d6a4677fdf711801e4d09e74d6cc122db9a50904..1e65842e2ca719a0916bc371c676e68f27c096e2 100644 (file)
@@ -251,6 +251,8 @@ static const u32 udma_tenvmin = 20;
 static const u32 udma_tackmin = 20;
 static const u32 udma_tssmin = 50;
 
+#define BFIN_MAX_SG_SEGMENTS 4
+
 /**
  *
  *     Function:       num_clocks_min
@@ -829,79 +831,61 @@ static void bfin_set_devctl(struct ata_port *ap, u8 ctl)
 
 static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
 {
-       unsigned short config = WDSIZE_16;
+       struct ata_port *ap = qc->ap;
+       struct dma_desc_array *dma_desc_cpu = (struct dma_desc_array *)ap->bmdma_prd;
+       void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+       unsigned short config = DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_16 | DMAEN;
        struct scatterlist *sg;
        unsigned int si;
+       unsigned int channel;
+       unsigned int dir;
+       unsigned int size = 0;
 
        dev_dbg(qc->ap->dev, "in atapi dma setup\n");
        /* Program the ATA_CTRL register with dir */
        if (qc->tf.flags & ATA_TFLAG_WRITE) {
-               /* fill the ATAPI DMA controller */
-               set_dma_config(CH_ATAPI_TX, config);
-               set_dma_x_modify(CH_ATAPI_TX, 2);
-               for_each_sg(qc->sg, sg, qc->n_elem, si) {
-                       set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
-                       set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
-               }
+               channel = CH_ATAPI_TX;
+               dir = DMA_TO_DEVICE;
        } else {
+               channel = CH_ATAPI_RX;
+               dir = DMA_FROM_DEVICE;
                config |= WNR;
-               /* fill the ATAPI DMA controller */
-               set_dma_config(CH_ATAPI_RX, config);
-               set_dma_x_modify(CH_ATAPI_RX, 2);
-               for_each_sg(qc->sg, sg, qc->n_elem, si) {
-                       set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
-                       set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
-               }
        }
-}
 
-/**
- *     bfin_bmdma_start - Start an IDE DMA transaction
- *     @qc: Info associated with this ATA transaction.
- *
- *     Note: Original code is ata_bmdma_start().
- */
+       dma_map_sg(ap->dev, qc->sg, qc->n_elem, dir);
 
-static void bfin_bmdma_start(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-       struct scatterlist *sg;
-       unsigned int si;
+       /* fill the ATAPI DMA controller */
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
+               dma_desc_cpu[si].start_addr = sg_dma_address(sg);
+               dma_desc_cpu[si].cfg = config;
+               dma_desc_cpu[si].x_count = sg_dma_len(sg) >> 1;
+               dma_desc_cpu[si].x_modify = 2;
+               size += sg_dma_len(sg);
+       }
 
-       dev_dbg(qc->ap->dev, "in atapi dma start\n");
-       if (!(ap->udma_mask || ap->mwdma_mask))
-               return;
+       /* Set the last descriptor to stop mode */
+       dma_desc_cpu[qc->n_elem - 1].cfg &= ~(DMAFLOW | NDSIZE);
 
-       /* start ATAPI DMA controller*/
-       if (qc->tf.flags & ATA_TFLAG_WRITE) {
-               /*
-                * On blackfin arch, uncacheable memory is not
-                * allocated with flag GFP_DMA. DMA buffer from
-                * common kenel code should be flushed if WB
-                * data cache is enabled. Otherwise, this loop
-                * is an empty loop and optimized out.
-                */
-               for_each_sg(qc->sg, sg, qc->n_elem, si) {
-                       flush_dcache_range(sg_dma_address(sg),
-                               sg_dma_address(sg) + sg_dma_len(sg));
-               }
-               enable_dma(CH_ATAPI_TX);
-               dev_dbg(qc->ap->dev, "enable udma write\n");
+       flush_dcache_range((unsigned int)dma_desc_cpu,
+               (unsigned int)dma_desc_cpu +
+                       qc->n_elem * sizeof(struct dma_desc_array));
 
-               /* Send ATA DMA write command */
-               bfin_exec_command(ap, &qc->tf);
+       /* Enable ATA DMA operation*/
+       set_dma_curr_desc_addr(channel, (unsigned long *)ap->bmdma_prd_dma);
+       set_dma_x_count(channel, 0);
+       set_dma_x_modify(channel, 0);
+       set_dma_config(channel, config);
+
+       SSYNC();
+
+       /* Send ATA DMA command */
+       bfin_exec_command(ap, &qc->tf);
 
+       if (qc->tf.flags & ATA_TFLAG_WRITE) {
                /* set ATA DMA write direction */
                ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
                        | XFER_DIR));
        } else {
-               enable_dma(CH_ATAPI_RX);
-               dev_dbg(qc->ap->dev, "enable udma read\n");
-
-               /* Send ATA DMA read command */
-               bfin_exec_command(ap, &qc->tf);
-
                /* set ATA DMA read direction */
                ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
                        & ~XFER_DIR));
@@ -913,12 +897,28 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
        /* Set ATAPI state machine contorl in terminate sequence */
        ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM);
 
-       /* Set transfer length to buffer len */
-       for_each_sg(qc->sg, sg, qc->n_elem, si) {
-               ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
-       }
+       /* Set transfer length to the total size of sg buffers */
+       ATAPI_SET_XFER_LEN(base, size >> 1);
+}
 
-       /* Enable ATA DMA operation*/
+/**
+ *     bfin_bmdma_start - Start an IDE DMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Note: Original code is ata_bmdma_start().
+ */
+
+static void bfin_bmdma_start(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+
+       dev_dbg(qc->ap->dev, "in atapi dma start\n");
+
+       if (!(ap->udma_mask || ap->mwdma_mask))
+               return;
+
+       /* start ATAPI transfer*/
        if (ap->udma_mask)
                ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base)
                        | ULTRA_START);
@@ -935,34 +935,23 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
 static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       struct scatterlist *sg;
-       unsigned int si;
+       unsigned int dir;
 
        dev_dbg(qc->ap->dev, "in atapi dma stop\n");
+
        if (!(ap->udma_mask || ap->mwdma_mask))
                return;
 
        /* stop ATAPI DMA controller*/
-       if (qc->tf.flags & ATA_TFLAG_WRITE)
+       if (qc->tf.flags & ATA_TFLAG_WRITE) {
+               dir = DMA_TO_DEVICE;
                disable_dma(CH_ATAPI_TX);
-       else {
+       } else {
+               dir = DMA_FROM_DEVICE;
                disable_dma(CH_ATAPI_RX);
-               if (ap->hsm_task_state & HSM_ST_LAST) {
-                       /*
-                        * On blackfin arch, uncacheable memory is not
-                        * allocated with flag GFP_DMA. DMA buffer from
-                        * common kenel code should be invalidated if
-                        * data cache is enabled. Otherwise, this loop
-                        * is an empty loop and optimized out.
-                        */
-                       for_each_sg(qc->sg, sg, qc->n_elem, si) {
-                               invalidate_dcache_range(
-                                       sg_dma_address(sg),
-                                       sg_dma_address(sg)
-                                       + sg_dma_len(sg));
-                       }
-               }
        }
+
+       dma_unmap_sg(ap->dev, qc->sg, qc->n_elem, dir);
 }
 
 /**
@@ -1260,6 +1249,11 @@ static void bfin_port_stop(struct ata_port *ap)
 {
        dev_dbg(ap->dev, "in atapi port stop\n");
        if (ap->udma_mask != 0 || ap->mwdma_mask != 0) {
+               dma_free_coherent(ap->dev,
+                       BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
+                       ap->bmdma_prd,
+                       ap->bmdma_prd_dma);
+
                free_dma(CH_ATAPI_RX);
                free_dma(CH_ATAPI_TX);
        }
@@ -1271,14 +1265,29 @@ static int bfin_port_start(struct ata_port *ap)
        if (!(ap->udma_mask || ap->mwdma_mask))
                return 0;
 
+       ap->bmdma_prd = dma_alloc_coherent(ap->dev,
+                               BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
+                               &ap->bmdma_prd_dma,
+                               GFP_KERNEL);
+
+       if (ap->bmdma_prd == NULL) {
+               dev_info(ap->dev, "Unable to allocate DMA descriptor array.\n");
+               goto out;
+       }
+
        if (request_dma(CH_ATAPI_RX, "BFIN ATAPI RX DMA") >= 0) {
                if (request_dma(CH_ATAPI_TX,
                        "BFIN ATAPI TX DMA") >= 0)
                        return 0;
 
                free_dma(CH_ATAPI_RX);
+               dma_free_coherent(ap->dev,
+                       BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
+                       ap->bmdma_prd,
+                       ap->bmdma_prd_dma);
        }
 
+out:
        ap->udma_mask = 0;
        ap->mwdma_mask = 0;
        dev_err(ap->dev, "Unable to request ATAPI DMA!"
@@ -1400,7 +1409,7 @@ static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
 
 static struct scsi_host_template bfin_sht = {
        ATA_BASE_SHT(DRV_NAME),
-       .sg_tablesize           = SG_NONE,
+       .sg_tablesize           = BFIN_MAX_SG_SEGMENTS,
        .dma_boundary           = ATA_DMA_BOUNDARY,
 };
 
index 5a2c95ba050a28caacbb4e3a799a0cdd176fcf47..0120b0d1e9a5aa838cee9a7347992377012d6c8c 100644 (file)
@@ -140,6 +140,7 @@ enum {
         */
        HCONTROL_ONLINE_PHY_RST = (1 << 31),
        HCONTROL_FORCE_OFFLINE = (1 << 30),
+       HCONTROL_LEGACY = (1 << 28),
        HCONTROL_PARITY_PROT_MOD = (1 << 14),
        HCONTROL_DPATH_PARITY = (1 << 12),
        HCONTROL_SNOOP_ENABLE = (1 << 10),
@@ -1223,6 +1224,10 @@ static int sata_fsl_init_controller(struct ata_host *host)
         * part of the port_start() callback
         */
 
+       /* sata controller to operate in enterprise mode */
+       temp = ioread32(hcr_base + HCONTROL);
+       iowrite32(temp & ~HCONTROL_LEGACY, hcr_base + HCONTROL);
+
        /* ack. any pending IRQs for this controller/port */
        temp = ioread32(hcr_base + HSTATUS);
        if (temp & 0x3F)
@@ -1421,6 +1426,12 @@ static int sata_fsl_resume(struct platform_device *op)
        /* Recovery the CHBA register in host controller cmd register set */
        iowrite32(pp->cmdslot_paddr & 0xffffffff, hcr_base + CHBA);
 
+       iowrite32((ioread32(hcr_base + HCONTROL)
+                               | HCONTROL_ONLINE_PHY_RST
+                               | HCONTROL_SNOOP_ENABLE
+                               | HCONTROL_PMP_ATTACHED),
+                       hcr_base + HCONTROL);
+
        ata_host_resume(host);
        return 0;
 }
index 2c8272dd93c4690229e3ea2442488e99a6de22e9..610f9997a4039c6df17d33d1931624c410120053 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for the Linux device tree
 
-obj-y                  := core.o sys.o bus.o dd.o syscore.o \
+obj-y                  := core.o bus.o dd.o syscore.o \
                           driver.o class.o platform.o \
                           cpu.o firmware.o init.o map.o devres.o \
                           attribute_container.o transport_class.o \
index 99dc5921e1dd28be8e6a910964dde8ca14900238..40fb12288ce258263cd4a995273f0bcc882df2ab 100644 (file)
@@ -915,9 +915,10 @@ static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
 
 /**
  * __bus_register - register a driver-core subsystem
- * @bus: bus.
+ * @bus: bus to register
+ * @key: lockdep class key
  *
- * Once we have that, we registered the bus with the kobject
+ * Once we have that, we register the bus with the kobject
  * infrastructure, then register the children subsystems it has:
  * the devices and drivers that belong to the subsystem.
  */
@@ -1220,8 +1221,8 @@ static void system_root_device_release(struct device *dev)
 }
 /**
  * subsys_system_register - register a subsystem at /sys/devices/system/
- * @subsys - system subsystem
- * @groups - default attributes for the root device
+ * @subsys: system subsystem
+ * @groups: default attributes for the root device
  *
  * All 'system' subsystems have a /sys/devices/system/<name> root device
  * with the name of the subsystem. The root device can carry subsystem-
index 4a67cc0c8b37aaeeec97e27eef04752a52504d1a..74dda4f697f92d772355f37c0a82553e7827119d 100644 (file)
@@ -632,6 +632,11 @@ static void klist_children_put(struct klist_node *n)
  * may be used for reference counting of @dev after calling this
  * function.
  *
+ * All fields in @dev must be initialized by the caller to 0, except
+ * for those explicitly set to some other value.  The simplest
+ * approach is to use kzalloc() to allocate the structure containing
+ * @dev.
+ *
  * NOTE: Use put_device() to give up your reference instead of freeing
  * @dev directly once you have called this function.
  */
@@ -930,6 +935,13 @@ int device_private_init(struct device *dev)
  * to the global and sibling lists for the device, then
  * adds it to the other relevant subsystems of the driver model.
  *
+ * Do not call this routine or device_register() more than once for
+ * any device structure.  The driver model core is not designed to work
+ * with devices that get unregistered and then spring back to life.
+ * (Among other things, it's very hard to guarantee that all references
+ * to the previous incarnation of @dev have been dropped.)  Allocate
+ * and register a fresh new struct device instead.
+ *
  * NOTE: _Never_ directly free @dev after calling this function, even
  * if it returned an error! Always use put_device() to give up your
  * reference instead.
@@ -1022,7 +1034,7 @@ int device_add(struct device *dev)
        device_pm_add(dev);
 
        /* Notify clients of device addition.  This call must come
-        * after dpm_sysf_add() and before kobject_uevent().
+        * after dpm_sysfs_add() and before kobject_uevent().
         */
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
@@ -1090,6 +1102,9 @@ name_error:
  * have a clearly defined need to use and refcount the device
  * before it is added to the hierarchy.
  *
+ * For more information, see the kerneldoc for device_initialize()
+ * and device_add().
+ *
  * NOTE: _Never_ directly free @dev after calling this function, even
  * if it returned an error! Always use put_device() to give up the
  * reference initialized in this function instead.
index db87e78d745940a3ba19332799930057edfd0615..4dabf5077c48575b06a4a25041fca33a8a8fb344 100644 (file)
@@ -208,6 +208,25 @@ static ssize_t print_cpus_offline(struct device *dev,
 }
 static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
 
+static void cpu_device_release(struct device *dev)
+{
+       /*
+        * This is an empty function to prevent the driver core from spitting a
+        * warning at us.  Yes, I know this is directly opposite of what the
+        * documentation for the driver core and kobjects say, and the author
+        * of this code has already been publically ridiculed for doing
+        * something as foolish as this.  However, at this point in time, it is
+        * the only way to handle the issue of statically allocated cpu
+        * devices.  The different architectures will have their cpu device
+        * code reworked to properly handle this in the near future, so this
+        * function will then be changed to correctly free up the memory held
+        * by the cpu device.
+        *
+        * Never copy this way of doing things, or you too will be made fun of
+        * on the linux-kerenl list, you have been warned.
+        */
+}
+
 /*
  * register_cpu - Setup a sysfs device for a CPU.
  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -221,8 +240,10 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
        int error;
 
        cpu->node_id = cpu_to_node(num);
+       memset(&cpu->dev, 0x00, sizeof(struct device));
        cpu->dev.id = num;
        cpu->dev.bus = &cpu_subsys;
+       cpu->dev.release = cpu_device_release;
        error = device_register(&cpu->dev);
        if (!error && cpu->hotpluggable)
                register_cpu_control(cpu);
index 26ab358dac62daf5cac1531eeb0cf24546c42efd..6c9387d646ecccc0d9c8fa62f6f8ce54593894a9 100644 (file)
@@ -525,8 +525,7 @@ static int _request_firmware(const struct firmware **firmware_p,
        if (!firmware) {
                dev_err(device, "%s: kmalloc(struct firmware) failed\n",
                        __func__);
-               retval = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
        if (fw_get_builtin_firmware(firmware, name)) {
index ed5de58c340f25e7c20b6db4189b279dd3110a2f..9e60dbe9fd94884cb5850f10af74567a9bc6300f 100644 (file)
@@ -572,19 +572,36 @@ static int init_memory_block(struct memory_block **memory,
 }
 
 static int add_memory_section(int nid, struct mem_section *section,
+                       struct memory_block **mem_p,
                        unsigned long state, enum mem_add_context context)
 {
-       struct memory_block *mem;
+       struct memory_block *mem = NULL;
+       int scn_nr = __section_nr(section);
        int ret = 0;
 
        mutex_lock(&mem_sysfs_mutex);
 
-       mem = find_memory_block(section);
+       if (context == BOOT) {
+               /* same memory block ? */
+               if (mem_p && *mem_p)
+                       if (scn_nr >= (*mem_p)->start_section_nr &&
+                           scn_nr <= (*mem_p)->end_section_nr) {
+                               mem = *mem_p;
+                               kobject_get(&mem->dev.kobj);
+                       }
+       } else
+               mem = find_memory_block(section);
+
        if (mem) {
                mem->section_count++;
                kobject_put(&mem->dev.kobj);
-       } else
+       } else {
                ret = init_memory_block(&mem, section, state);
+               /* store memory_block pointer for next loop */
+               if (!ret && context == BOOT)
+                       if (mem_p)
+                               *mem_p = mem;
+       }
 
        if (!ret) {
                if (context == HOTPLUG &&
@@ -627,7 +644,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
  */
 int register_new_memory(int nid, struct mem_section *section)
 {
-       return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
+       return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -647,6 +664,7 @@ int __init memory_dev_init(void)
        int ret;
        int err;
        unsigned long block_sz;
+       struct memory_block *mem = NULL;
 
        ret = subsys_system_register(&memory_subsys, NULL);
        if (ret)
@@ -662,7 +680,10 @@ int __init memory_dev_init(void)
        for (i = 0; i < NR_MEM_SECTIONS; i++) {
                if (!present_section_nr(i))
                        continue;
-               err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
+               /* don't need to reuse memory_block if only one per block */
+               err = add_memory_section(0, __nr_to_section(i),
+                                (sections_per_block == 1) ? NULL : &mem,
+                                        MEM_ONLINE,
                                         BOOT);
                if (!ret)
                        ret = err;
index 44f427a6611724e710efc0591e8ba9777cf5dcbd..90aa2a11a933b448a536a353c5d932668c3f8e11 100644 (file)
@@ -456,7 +456,15 @@ static int link_mem_sections(int nid)
                if (!present_section_nr(section_nr))
                        continue;
                mem_sect = __nr_to_section(section_nr);
+
+               /* same memblock ? */
+               if (mem_blk)
+                       if ((section_nr >= mem_blk->start_section_nr) &&
+                           (section_nr <= mem_blk->end_section_nr))
+                               continue;
+
                mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
+
                ret = register_mem_sect_under_node(mem_blk, nid);
                if (!err)
                        err = ret;
index 1ead66186b7c0a90586f223b0b9bc23d3770a3ed..d1daa5e9fadf322b4a6e4d9e7f5d60e71eea0e40 100644 (file)
@@ -53,7 +53,7 @@ static int regcache_hw_init(struct regmap *map)
        for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
                val = regcache_get_val(map->reg_defaults_raw,
                                       i, map->cache_word_size);
-               if (!val)
+               if (regmap_volatile(map, i))
                        continue;
                count++;
        }
@@ -70,7 +70,7 @@ static int regcache_hw_init(struct regmap *map)
        for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
                val = regcache_get_val(map->reg_defaults_raw,
                                       i, map->cache_word_size);
-               if (!val)
+               if (regmap_volatile(map, i))
                        continue;
                map->reg_defaults[j].reg = i;
                map->reg_defaults[j].def = val;
index be10a4ff660915625454375ce9fb30a97d5b7ef9..65558034318f3f295abde2fe7a599c4971e7d7ec 100644 (file)
@@ -284,6 +284,9 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
        map->precious_reg = config->precious_reg;
        map->cache_type = config->cache_type;
 
+       map->cache_bypass = false;
+       map->cache_only = false;
+
        ret = regcache_init(map, config);
 
        mutex_unlock(&map->lock);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
deleted file mode 100644 (file)
index 409f5ce..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc)
- *
- * Copyright (c) 2002-3 Patrick Mochel
- *               2002-3 Open Source Development Lab
- *
- * This file is released under the GPLv2
- *
- * This exports a 'system' bus type.
- * By default, a 'sys' bus gets added to the root of the system. There will
- * always be core system devices. Devices can use sysdev_register() to
- * add themselves as children of the system bus.
- */
-
-#include <linux/sysdev.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-
-#include "base.h"
-
-#define to_sysdev(k) container_of(k, struct sys_device, kobj)
-#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
-
-
-static ssize_t
-sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
-{
-       struct sys_device *sysdev = to_sysdev(kobj);
-       struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
-
-       if (sysdev_attr->show)
-               return sysdev_attr->show(sysdev, sysdev_attr, buffer);
-       return -EIO;
-}
-
-
-static ssize_t
-sysdev_store(struct kobject *kobj, struct attribute *attr,
-            const char *buffer, size_t count)
-{
-       struct sys_device *sysdev = to_sysdev(kobj);
-       struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
-
-       if (sysdev_attr->store)
-               return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
-       return -EIO;
-}
-
-static const struct sysfs_ops sysfs_ops = {
-       .show   = sysdev_show,
-       .store  = sysdev_store,
-};
-
-static struct kobj_type ktype_sysdev = {
-       .sysfs_ops      = &sysfs_ops,
-};
-
-
-int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a)
-{
-       return sysfs_create_file(&s->kobj, &a->attr);
-}
-
-
-void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a)
-{
-       sysfs_remove_file(&s->kobj, &a->attr);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_create_file);
-EXPORT_SYMBOL_GPL(sysdev_remove_file);
-
-#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj)
-#define to_sysdev_class_attr(a) container_of(a, \
-       struct sysdev_class_attribute, attr)
-
-static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
-                                char *buffer)
-{
-       struct sysdev_class *class = to_sysdev_class(kobj);
-       struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
-
-       if (class_attr->show)
-               return class_attr->show(class, class_attr, buffer);
-       return -EIO;
-}
-
-static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
-                                 const char *buffer, size_t count)
-{
-       struct sysdev_class *class = to_sysdev_class(kobj);
-       struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
-
-       if (class_attr->store)
-               return class_attr->store(class, class_attr, buffer, count);
-       return -EIO;
-}
-
-static const struct sysfs_ops sysfs_class_ops = {
-       .show   = sysdev_class_show,
-       .store  = sysdev_class_store,
-};
-
-static struct kobj_type ktype_sysdev_class = {
-       .sysfs_ops      = &sysfs_class_ops,
-};
-
-int sysdev_class_create_file(struct sysdev_class *c,
-                            struct sysdev_class_attribute *a)
-{
-       return sysfs_create_file(&c->kset.kobj, &a->attr);
-}
-EXPORT_SYMBOL_GPL(sysdev_class_create_file);
-
-void sysdev_class_remove_file(struct sysdev_class *c,
-                             struct sysdev_class_attribute *a)
-{
-       sysfs_remove_file(&c->kset.kobj, &a->attr);
-}
-EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
-
-extern struct kset *system_kset;
-
-int sysdev_class_register(struct sysdev_class *cls)
-{
-       int retval;
-
-       pr_debug("Registering sysdev class '%s'\n", cls->name);
-
-       INIT_LIST_HEAD(&cls->drivers);
-       memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
-       cls->kset.kobj.parent = &system_kset->kobj;
-       cls->kset.kobj.ktype = &ktype_sysdev_class;
-       cls->kset.kobj.kset = system_kset;
-
-       retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
-       if (retval)
-               return retval;
-
-       retval = kset_register(&cls->kset);
-       if (!retval && cls->attrs)
-               retval = sysfs_create_files(&cls->kset.kobj,
-                                           (const struct attribute **)cls->attrs);
-       return retval;
-}
-
-void sysdev_class_unregister(struct sysdev_class *cls)
-{
-       pr_debug("Unregistering sysdev class '%s'\n",
-                kobject_name(&cls->kset.kobj));
-       if (cls->attrs)
-               sysfs_remove_files(&cls->kset.kobj,
-                                  (const struct attribute **)cls->attrs);
-       kset_unregister(&cls->kset);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_class_register);
-EXPORT_SYMBOL_GPL(sysdev_class_unregister);
-
-static DEFINE_MUTEX(sysdev_drivers_lock);
-
-/*
- * @dev != NULL means that we're unwinding because some drv->add()
- * failed for some reason. You need to grab sysdev_drivers_lock before
- * calling this.
- */
-static void __sysdev_driver_remove(struct sysdev_class *cls,
-                                  struct sysdev_driver *drv,
-                                  struct sys_device *from_dev)
-{
-       struct sys_device *dev = from_dev;
-
-       list_del_init(&drv->entry);
-       if (!cls)
-               return;
-
-       if (!drv->remove)
-               goto kset_put;
-
-       if (dev)
-               list_for_each_entry_continue_reverse(dev, &cls->kset.list,
-                                                    kobj.entry)
-                       drv->remove(dev);
-       else
-               list_for_each_entry(dev, &cls->kset.list, kobj.entry)
-                       drv->remove(dev);
-
-kset_put:
-       kset_put(&cls->kset);
-}
-
-/**
- *     sysdev_driver_register - Register auxiliary driver
- *     @cls:   Device class driver belongs to.
- *     @drv:   Driver.
- *
- *     @drv is inserted into @cls->drivers to be
- *     called on each operation on devices of that class. The refcount
- *     of @cls is incremented.
- */
-int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
-{
-       struct sys_device *dev = NULL;
-       int err = 0;
-
-       if (!cls) {
-               WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
-                       __func__);
-               return -EINVAL;
-       }
-
-       /* Check whether this driver has already been added to a class. */
-       if (drv->entry.next && !list_empty(&drv->entry))
-               WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already"
-                       " been registered to a class, something is wrong, but "
-                       "will forge on!\n", cls->name, drv);
-
-       mutex_lock(&sysdev_drivers_lock);
-       if (cls && kset_get(&cls->kset)) {
-               list_add_tail(&drv->entry, &cls->drivers);
-
-               /* If devices of this class already exist, tell the driver */
-               if (drv->add) {
-                       list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
-                               err = drv->add(dev);
-                               if (err)
-                                       goto unwind;
-                       }
-               }
-       } else {
-               err = -EINVAL;
-               WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
-       }
-
-       goto unlock;
-
-unwind:
-       __sysdev_driver_remove(cls, drv, dev);
-
-unlock:
-       mutex_unlock(&sysdev_drivers_lock);
-       return err;
-}
-
-/**
- *     sysdev_driver_unregister - Remove an auxiliary driver.
- *     @cls:   Class driver belongs to.
- *     @drv:   Driver.
- */
-void sysdev_driver_unregister(struct sysdev_class *cls,
-                             struct sysdev_driver *drv)
-{
-       mutex_lock(&sysdev_drivers_lock);
-       __sysdev_driver_remove(cls, drv, NULL);
-       mutex_unlock(&sysdev_drivers_lock);
-}
-EXPORT_SYMBOL_GPL(sysdev_driver_register);
-EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
-
-/**
- *     sysdev_register - add a system device to the tree
- *     @sysdev:        device in question
- *
- */
-int sysdev_register(struct sys_device *sysdev)
-{
-       int error;
-       struct sysdev_class *cls = sysdev->cls;
-
-       if (!cls)
-               return -EINVAL;
-
-       pr_debug("Registering sys device of class '%s'\n",
-                kobject_name(&cls->kset.kobj));
-
-       /* initialize the kobject to 0, in case it had previously been used */
-       memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
-
-       /* Make sure the kset is set */
-       sysdev->kobj.kset = &cls->kset;
-
-       /* Register the object */
-       error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL,
-                                    "%s%d", kobject_name(&cls->kset.kobj),
-                                    sysdev->id);
-
-       if (!error) {
-               struct sysdev_driver *drv;
-
-               pr_debug("Registering sys device '%s'\n",
-                        kobject_name(&sysdev->kobj));
-
-               mutex_lock(&sysdev_drivers_lock);
-               /* Generic notification is implicit, because it's that
-                * code that should have called us.
-                */
-
-               /* Notify class auxiliary drivers */
-               list_for_each_entry(drv, &cls->drivers, entry) {
-                       if (drv->add)
-                               drv->add(sysdev);
-               }
-               mutex_unlock(&sysdev_drivers_lock);
-               kobject_uevent(&sysdev->kobj, KOBJ_ADD);
-       }
-
-       return error;
-}
-
-void sysdev_unregister(struct sys_device *sysdev)
-{
-       struct sysdev_driver *drv;
-
-       mutex_lock(&sysdev_drivers_lock);
-       list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
-               if (drv->remove)
-                       drv->remove(sysdev);
-       }
-       mutex_unlock(&sysdev_drivers_lock);
-
-       kobject_put(&sysdev->kobj);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_register);
-EXPORT_SYMBOL_GPL(sysdev_unregister);
-
-#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
-
-ssize_t sysdev_store_ulong(struct sys_device *sysdev,
-                          struct sysdev_attribute *attr,
-                          const char *buf, size_t size)
-{
-       struct sysdev_ext_attribute *ea = to_ext_attr(attr);
-       char *end;
-       unsigned long new = simple_strtoul(buf, &end, 0);
-       if (end == buf)
-               return -EINVAL;
-       *(unsigned long *)(ea->var) = new;
-       /* Always return full write size even if we didn't consume all */
-       return size;
-}
-EXPORT_SYMBOL_GPL(sysdev_store_ulong);
-
-ssize_t sysdev_show_ulong(struct sys_device *sysdev,
-                         struct sysdev_attribute *attr,
-                         char *buf)
-{
-       struct sysdev_ext_attribute *ea = to_ext_attr(attr);
-       return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
-}
-EXPORT_SYMBOL_GPL(sysdev_show_ulong);
-
-ssize_t sysdev_store_int(struct sys_device *sysdev,
-                          struct sysdev_attribute *attr,
-                          const char *buf, size_t size)
-{
-       struct sysdev_ext_attribute *ea = to_ext_attr(attr);
-       char *end;
-       long new = simple_strtol(buf, &end, 0);
-       if (end == buf || new > INT_MAX || new < INT_MIN)
-               return -EINVAL;
-       *(int *)(ea->var) = new;
-       /* Always return full write size even if we didn't consume all */
-       return size;
-}
-EXPORT_SYMBOL_GPL(sysdev_store_int);
-
-ssize_t sysdev_show_int(struct sys_device *sysdev,
-                         struct sysdev_attribute *attr,
-                         char *buf)
-{
-       struct sysdev_ext_attribute *ea = to_ext_attr(attr);
-       return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
-}
-EXPORT_SYMBOL_GPL(sysdev_show_int);
-
index fda56bde36b836cc7fa4a8bee2c1bc92b0e5a43d..0def898a1d159c12d2543df6ffd6264932a7affc 100644 (file)
@@ -19,6 +19,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
                                   struct bcma_device *core_cc,
                                   struct bcma_device *core_mips);
 #ifdef CONFIG_PM
+int bcma_bus_suspend(struct bcma_bus *bus);
 int bcma_bus_resume(struct bcma_bus *bus);
 #endif
 
index 443b83a2fd7aa012c1c6835137e2642a79499b41..f59244e3397137ca9b6a6d311612dd53db721646 100644 (file)
@@ -235,38 +235,32 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
 }
 
 #ifdef CONFIG_PM
-static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
+static int bcma_host_pci_suspend(struct device *dev)
 {
-       /* Host specific */
-       pci_save_state(dev);
-       pci_disable_device(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct bcma_bus *bus = pci_get_drvdata(pdev);
 
-       return 0;
+       bus->mapped_core = NULL;
+
+       return bcma_bus_suspend(bus);
 }
 
-static int bcma_host_pci_resume(struct pci_dev *dev)
+static int bcma_host_pci_resume(struct device *dev)
 {
-       struct bcma_bus *bus = pci_get_drvdata(dev);
-       int err;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct bcma_bus *bus = pci_get_drvdata(pdev);
 
-       /* Host specific */
-       pci_set_power_state(dev, 0);
-       err = pci_enable_device(dev);
-       if (err)
-               return err;
-       pci_restore_state(dev);
+       return bcma_bus_resume(bus);
+}
 
-       /* Bus specific */
-       err = bcma_bus_resume(bus);
-       if (err)
-               return err;
+static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
+                        bcma_host_pci_resume);
+#define BCMA_PM_OPS    (&bcma_pm_ops)
 
-       return 0;
-}
 #else /* CONFIG_PM */
-# define bcma_host_pci_suspend NULL
-# define bcma_host_pci_resume  NULL
+
+#define BCMA_PM_OPS     NULL
+
 #endif /* CONFIG_PM */
 
 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
@@ -284,8 +278,7 @@ static struct pci_driver bcma_pci_bridge_driver = {
        .id_table = bcma_pci_bridge_tbl,
        .probe = bcma_host_pci_probe,
        .remove = bcma_host_pci_remove,
-       .suspend = bcma_host_pci_suspend,
-       .resume = bcma_host_pci_resume,
+       .driver.pm = BCMA_PM_OPS,
 };
 
 int __init bcma_host_pci_init(void)
index 10f92b371e582bf6d371f425b17dd1dfe5629afd..ec31f7dd55491aeaea79b071c8aebc7065a8452a 100644 (file)
@@ -169,10 +169,8 @@ int bcma_bus_register(struct bcma_bus *bus)
        err = bcma_sprom_get(bus);
        if (err == -ENOENT) {
                pr_err("No SPROM available\n");
-       } else if (err) {
+       } else if (err)
                pr_err("Failed to get SPROM: %d\n", err);
-               return -ENOENT;
-       }
 
        /* Register found cores */
        bcma_register_cores(bus);
@@ -241,6 +239,21 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
 }
 
 #ifdef CONFIG_PM
+int bcma_bus_suspend(struct bcma_bus *bus)
+{
+       struct bcma_device *core;
+
+       list_for_each_entry(core, &bus->cores, list) {
+               struct device_driver *drv = core->dev.driver;
+               if (drv) {
+                       struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
+                       if (adrv->suspend)
+                               adrv->suspend(core);
+               }
+       }
+       return 0;
+}
+
 int bcma_bus_resume(struct bcma_bus *bus)
 {
        struct bcma_device *core;
@@ -252,6 +265,15 @@ int bcma_bus_resume(struct bcma_bus *bus)
                bcma_core_chipcommon_init(&bus->drv_cc);
        }
 
+       list_for_each_entry(core, &bus->cores, list) {
+               struct device_driver *drv = core->dev.driver;
+               if (drv) {
+                       struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
+                       if (adrv->resume)
+                               adrv->resume(core);
+               }
+       }
+
        return 0;
 }
 #endif
index cad9948576837a53373791179b388d59276c7596..3a2f672db9ad217c264cf7a2203e4d96aa0910d7 100644 (file)
@@ -399,15 +399,18 @@ int bcma_bus_scan(struct bcma_bus *bus)
                core->bus = bus;
 
                err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
-               if (err == -ENODEV) {
-                       core_num++;
-                       continue;
-               } else if (err == -ENXIO)
-                       continue;
-               else if (err == -ESPIPE)
-                       break;
-               else if (err < 0)
+               if (err < 0) {
+                       kfree(core);
+                       if (err == -ENODEV) {
+                               core_num++;
+                               continue;
+                       } else if (err == -ENXIO) {
+                               continue;
+                       } else if (err == -ESPIPE) {
+                               break;
+                       }
                        return err;
+               }
 
                core->core_index = core_num++;
                bus->nr_cores++;
index a30aa103f95b33a4567b519250331725dc5f9539..4e4c8a4a5fd3fb4412a19fdbd3f62647b285fd6a 100644 (file)
@@ -317,6 +317,17 @@ config BLK_DEV_NBD
 
          If unsure, say N.
 
+config BLK_DEV_NVME
+       tristate "NVM Express block device"
+       depends on PCI
+       ---help---
+         The NVM Express driver is for solid state drives directly
+         connected to the PCI or PCI Express bus.  If you know you
+         don't have one of these, it is safe to answer N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called nvme.
+
 config BLK_DEV_OSD
        tristate "OSD object-as-blkdev support"
        depends on SCSI_OSD_ULD
index ad7b74a44ef3dd3e1e1c39f7e44855e45e0bfd56..5b795059f8fb76107b5f2950dd88c5c9696ad4ee 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE)   += xsysace.o
 obj-$(CONFIG_CDROM_PKTCDVD)    += pktcdvd.o
 obj-$(CONFIG_MG_DISK)          += mg_disk.o
 obj-$(CONFIG_SUNVDC)           += sunvdc.o
+obj-$(CONFIG_BLK_DEV_NVME)     += nvme.o
 obj-$(CONFIG_BLK_DEV_OSD)      += osdblk.o
 
 obj-$(CONFIG_BLK_DEV_UMEM)     += umem.o
index 510fb10ec45a9fc532820b5a9cb3158c2abd66d9..9baf11e8636205c413bd5c00498baab628657b44 100644 (file)
@@ -4368,8 +4368,14 @@ out_unreg_blkdev:
 out_put_disk:
        while (dr--) {
                del_timer_sync(&motor_off_timer[dr]);
-               if (disks[dr]->queue)
+               if (disks[dr]->queue) {
                        blk_cleanup_queue(disks[dr]->queue);
+                       /*
+                        * put_disk() is not paired with add_disk() and
+                        * will put queue reference one extra time. fix it.
+                        */
+                       disks[dr]->queue = NULL;
+               }
                put_disk(disks[dr]);
        }
        return err;
@@ -4579,6 +4585,15 @@ static void __exit floppy_module_exit(void)
                        platform_device_unregister(&floppy_device[drive]);
                }
                blk_cleanup_queue(disks[drive]->queue);
+
+               /*
+                * These disks have not called add_disk().  Don't put down
+                * queue reference in put_disk().
+                */
+               if (!(allowed_drive_mask & (1 << drive)) ||
+                   fdc_state[FDC(drive)].version == FDC_NONE)
+                       disks[drive]->queue = NULL;
+
                put_disk(disks[drive]);
        }
 
index f00257782fccd34af45fc233ecb26255828e7a0a..cd504353b2785fcaeebb5a58ccc6effe8568c43b 100644 (file)
@@ -356,14 +356,14 @@ lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
        return __splice_from_pipe(pipe, sd, lo_splice_actor);
 }
 
-static int
+static ssize_t
 do_lo_receive(struct loop_device *lo,
              struct bio_vec *bvec, int bsize, loff_t pos)
 {
        struct lo_read_data cookie;
        struct splice_desc sd;
        struct file *file;
-       long retval;
+       ssize_t retval;
 
        cookie.lo = lo;
        cookie.page = bvec->bv_page;
@@ -379,26 +379,28 @@ do_lo_receive(struct loop_device *lo,
        file = lo->lo_backing_file;
        retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
 
-       if (retval < 0)
-               return retval;
-       if (retval != bvec->bv_len)
-               return -EIO;
-       return 0;
+       return retval;
 }
 
 static int
 lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
 {
        struct bio_vec *bvec;
-       int i, ret = 0;
+       ssize_t s;
+       int i;
 
        bio_for_each_segment(bvec, bio, i) {
-               ret = do_lo_receive(lo, bvec, bsize, pos);
-               if (ret < 0)
+               s = do_lo_receive(lo, bvec, bsize, pos);
+               if (s < 0)
+                       return s;
+
+               if (s != bvec->bv_len) {
+                       zero_fill_bio(bio);
                        break;
+               }
                pos += bvec->bv_len;
        }
-       return ret;
+       return 0;
 }
 
 static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
index b74eab70c3d0aa0f386655e02fab6dc45bd0c508..8eb81c96608fbc47aadc382015a0e44db2b4599a 100644 (file)
@@ -2068,8 +2068,6 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  *          when the read completes.
  * @data     Callback data passed to the callback function
  *          when the read completes.
- * @barrier  If non-zero, this command must be completed before
- *          issuing any other commands.
  * @dir      Direction (read or write)
  *
  * return value
@@ -2077,7 +2075,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  */
 static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
                              int nsect, int nents, int tag, void *callback,
-                             void *data, int barrier, int dir)
+                             void *data, int dir)
 {
        struct host_to_dev_fis  *fis;
        struct mtip_port *port = dd->port;
@@ -2108,8 +2106,6 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
        *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
        fis->device      = 1 << 6;
-       if (barrier)
-               fis->device |= FUA_BIT;
        fis->features    = nsect & 0xFF;
        fis->features_ex = (nsect >> 8) & 0xFF;
        fis->sect_count  = ((tag << 3) | (tag >> 5));
@@ -3087,7 +3083,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
                                tag,
                                bio_endio,
                                bio,
-                               bio->bi_rw & REQ_FUA,
                                bio_data_dir(bio));
        } else
                bio_io_error(bio);
@@ -3187,6 +3182,10 @@ skip_create_disk:
        blk_queue_max_segments(dd->queue, MTIP_MAX_SG);
        blk_queue_physical_block_size(dd->queue, 4096);
        blk_queue_io_min(dd->queue, 4096);
+       /*
+        * write back cache is not supported in the device. FUA depends on
+        * write back cache support, hence setting flush support to zero.
+        */
        blk_queue_flush(dd->queue, 0);
 
        /* Set the capacity of the device in 512 byte sectors. */
index 723d7c4946dcb1419cacac22194915a058040856..e0554a8f2233faf85c8f98409fdf83c9cdd5cae7 100644 (file)
 /* BAR number used to access the HBA registers. */
 #define MTIP_ABAR              5
 
-/* Forced Unit Access Bit */
-#define FUA_BIT                        0x80
-
 #ifdef DEBUG
  #define dbg_printk(format, arg...)    \
        printk(pr_fmt(format), ##arg);
@@ -415,8 +412,6 @@ struct driver_data {
 
        atomic_t resumeflag; /* Atomic variable to track suspend/resume */
 
-       atomic_t eh_active; /* Flag for error handling tracking */
-
        struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
 };
 
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
new file mode 100644 (file)
index 0000000..1f3c1a7
--- /dev/null
@@ -0,0 +1,1741 @@
+/*
+ * NVM Express device driver
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/nvme.h>
+#include <linux/bio.h>
+#include <linux/bitops.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kdev_t.h>
+#include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/poison.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
+#define NVME_Q_DEPTH 1024
+#define SQ_SIZE(depth)         (depth * sizeof(struct nvme_command))
+#define CQ_SIZE(depth)         (depth * sizeof(struct nvme_completion))
+#define NVME_MINORS 64
+#define NVME_IO_TIMEOUT        (5 * HZ)
+#define ADMIN_TIMEOUT  (60 * HZ)
+
+static int nvme_major;
+module_param(nvme_major, int, 0);
+
+static int use_threaded_interrupts;
+module_param(use_threaded_interrupts, int, 0);
+
+static DEFINE_SPINLOCK(dev_list_lock);
+static LIST_HEAD(dev_list);
+static struct task_struct *nvme_thread;
+
+/*
+ * Represents an NVM Express device.  Each nvme_dev is a PCI function.
+ */
+struct nvme_dev {
+       struct list_head node;
+       struct nvme_queue **queues;
+       u32 __iomem *dbs;
+       struct pci_dev *pci_dev;
+       struct dma_pool *prp_page_pool;
+       struct dma_pool *prp_small_pool;
+       int instance;
+       int queue_count;
+       int db_stride;
+       u32 ctrl_config;
+       struct msix_entry *entry;
+       struct nvme_bar __iomem *bar;
+       struct list_head namespaces;
+       char serial[20];
+       char model[40];
+       char firmware_rev[8];
+};
+
+/*
+ * An NVM Express namespace is equivalent to a SCSI LUN
+ */
+struct nvme_ns {
+       struct list_head list;
+
+       struct nvme_dev *dev;
+       struct request_queue *queue;
+       struct gendisk *disk;
+
+       int ns_id;
+       int lba_shift;
+};
+
+/*
+ * An NVM Express queue.  Each device has at least two (one for admin
+ * commands and one for I/O commands).
+ */
+struct nvme_queue {
+       struct device *q_dmadev;
+       struct nvme_dev *dev;
+       spinlock_t q_lock;
+       struct nvme_command *sq_cmds;
+       volatile struct nvme_completion *cqes;
+       dma_addr_t sq_dma_addr;
+       dma_addr_t cq_dma_addr;
+       wait_queue_head_t sq_full;
+       wait_queue_t sq_cong_wait;
+       struct bio_list sq_cong;
+       u32 __iomem *q_db;
+       u16 q_depth;
+       u16 cq_vector;
+       u16 sq_head;
+       u16 sq_tail;
+       u16 cq_head;
+       u16 cq_phase;
+       unsigned long cmdid_data[];
+};
+
+/*
+ * Check we didin't inadvertently grow the command struct
+ */
+static inline void _nvme_check_size(void)
+{
+       BUILD_BUG_ON(sizeof(struct nvme_rw_command) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_create_cq) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_features) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_command) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096);
+       BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096);
+       BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64);
+}
+
+typedef void (*nvme_completion_fn)(struct nvme_dev *, void *,
+                                               struct nvme_completion *);
+
+struct nvme_cmd_info {
+       nvme_completion_fn fn;
+       void *ctx;
+       unsigned long timeout;
+};
+
+static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq)
+{
+       return (void *)&nvmeq->cmdid_data[BITS_TO_LONGS(nvmeq->q_depth)];
+}
+
+/**
+ * alloc_cmdid() - Allocate a Command ID
+ * @nvmeq: The queue that will be used for this command
+ * @ctx: A pointer that will be passed to the handler
+ * @handler: The function to call on completion
+ *
+ * Allocate a Command ID for a queue.  The data passed in will
+ * be passed to the completion handler.  This is implemented by using
+ * the bottom two bits of the ctx pointer to store the handler ID.
+ * Passing in a pointer that's not 4-byte aligned will cause a BUG.
+ * We can change this if it becomes a problem.
+ *
+ * May be called with local interrupts disabled and the q_lock held,
+ * or with interrupts enabled and no locks held.
+ */
+static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx,
+                               nvme_completion_fn handler, unsigned timeout)
+{
+       int depth = nvmeq->q_depth - 1;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+       int cmdid;
+
+       do {
+               cmdid = find_first_zero_bit(nvmeq->cmdid_data, depth);
+               if (cmdid >= depth)
+                       return -EBUSY;
+       } while (test_and_set_bit(cmdid, nvmeq->cmdid_data));
+
+       info[cmdid].fn = handler;
+       info[cmdid].ctx = ctx;
+       info[cmdid].timeout = jiffies + timeout;
+       return cmdid;
+}
+
+static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx,
+                               nvme_completion_fn handler, unsigned timeout)
+{
+       int cmdid;
+       wait_event_killable(nvmeq->sq_full,
+               (cmdid = alloc_cmdid(nvmeq, ctx, handler, timeout)) >= 0);
+       return (cmdid < 0) ? -EINTR : cmdid;
+}
+
+/* Special values must be less than 0x1000 */
+#define CMD_CTX_BASE           ((void *)POISON_POINTER_DELTA)
+#define CMD_CTX_CANCELLED      (0x30C + CMD_CTX_BASE)
+#define CMD_CTX_COMPLETED      (0x310 + CMD_CTX_BASE)
+#define CMD_CTX_INVALID                (0x314 + CMD_CTX_BASE)
+#define CMD_CTX_FLUSH          (0x318 + CMD_CTX_BASE)
+
+static void special_completion(struct nvme_dev *dev, void *ctx,
+                                               struct nvme_completion *cqe)
+{
+       if (ctx == CMD_CTX_CANCELLED)
+               return;
+       if (ctx == CMD_CTX_FLUSH)
+               return;
+       if (ctx == CMD_CTX_COMPLETED) {
+               dev_warn(&dev->pci_dev->dev,
+                               "completed id %d twice on queue %d\n",
+                               cqe->command_id, le16_to_cpup(&cqe->sq_id));
+               return;
+       }
+       if (ctx == CMD_CTX_INVALID) {
+               dev_warn(&dev->pci_dev->dev,
+                               "invalid id %d completed on queue %d\n",
+                               cqe->command_id, le16_to_cpup(&cqe->sq_id));
+               return;
+       }
+
+       dev_warn(&dev->pci_dev->dev, "Unknown special completion %p\n", ctx);
+}
+
+/*
+ * Called with local interrupts disabled and the q_lock held.  May not sleep.
+ */
+static void *free_cmdid(struct nvme_queue *nvmeq, int cmdid,
+                                               nvme_completion_fn *fn)
+{
+       void *ctx;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+
+       if (cmdid >= nvmeq->q_depth) {
+               *fn = special_completion;
+               return CMD_CTX_INVALID;
+       }
+       *fn = info[cmdid].fn;
+       ctx = info[cmdid].ctx;
+       info[cmdid].fn = special_completion;
+       info[cmdid].ctx = CMD_CTX_COMPLETED;
+       clear_bit(cmdid, nvmeq->cmdid_data);
+       wake_up(&nvmeq->sq_full);
+       return ctx;
+}
+
+static void *cancel_cmdid(struct nvme_queue *nvmeq, int cmdid,
+                                               nvme_completion_fn *fn)
+{
+       void *ctx;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+       if (fn)
+               *fn = info[cmdid].fn;
+       ctx = info[cmdid].ctx;
+       info[cmdid].fn = special_completion;
+       info[cmdid].ctx = CMD_CTX_CANCELLED;
+       return ctx;
+}
+
+static struct nvme_queue *get_nvmeq(struct nvme_dev *dev)
+{
+       return dev->queues[get_cpu() + 1];
+}
+
+static void put_nvmeq(struct nvme_queue *nvmeq)
+{
+       put_cpu();
+}
+
+/**
+ * nvme_submit_cmd() - Copy a command into a queue and ring the doorbell
+ * @nvmeq: The queue to use
+ * @cmd: The command to send
+ *
+ * Safe to use from interrupt context
+ */
+static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd)
+{
+       unsigned long flags;
+       u16 tail;
+       spin_lock_irqsave(&nvmeq->q_lock, flags);
+       tail = nvmeq->sq_tail;
+       memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
+       if (++tail == nvmeq->q_depth)
+               tail = 0;
+       writel(tail, nvmeq->q_db);
+       nvmeq->sq_tail = tail;
+       spin_unlock_irqrestore(&nvmeq->q_lock, flags);
+
+       return 0;
+}
+
+/*
+ * The nvme_iod describes the data in an I/O, including the list of PRP
+ * entries.  You can't see it in this data structure because C doesn't let
+ * me express that.  Use nvme_alloc_iod to ensure there's enough space
+ * allocated to store the PRP list.
+ */
+struct nvme_iod {
+       void *private;          /* For the use of the submitter of the I/O */
+       int npages;             /* In the PRP list. 0 means small pool in use */
+       int offset;             /* Of PRP list */
+       int nents;              /* Used in scatterlist */
+       int length;             /* Of data, in bytes */
+       dma_addr_t first_dma;
+       struct scatterlist sg[0];
+};
+
+static __le64 **iod_list(struct nvme_iod *iod)
+{
+       return ((void *)iod) + iod->offset;
+}
+
+/*
+ * Will slightly overestimate the number of pages needed.  This is OK
+ * as it only leads to a small amount of wasted memory for the lifetime of
+ * the I/O.
+ */
+static int nvme_npages(unsigned size)
+{
+       unsigned nprps = DIV_ROUND_UP(size + PAGE_SIZE, PAGE_SIZE);
+       return DIV_ROUND_UP(8 * nprps, PAGE_SIZE - 8);
+}
+
+static struct nvme_iod *
+nvme_alloc_iod(unsigned nseg, unsigned nbytes, gfp_t gfp)
+{
+       struct nvme_iod *iod = kmalloc(sizeof(struct nvme_iod) +
+                               sizeof(__le64 *) * nvme_npages(nbytes) +
+                               sizeof(struct scatterlist) * nseg, gfp);
+
+       if (iod) {
+               iod->offset = offsetof(struct nvme_iod, sg[nseg]);
+               iod->npages = -1;
+               iod->length = nbytes;
+       }
+
+       return iod;
+}
+
+static void nvme_free_iod(struct nvme_dev *dev, struct nvme_iod *iod)
+{
+       const int last_prp = PAGE_SIZE / 8 - 1;
+       int i;
+       __le64 **list = iod_list(iod);
+       dma_addr_t prp_dma = iod->first_dma;
+
+       if (iod->npages == 0)
+               dma_pool_free(dev->prp_small_pool, list[0], prp_dma);
+       for (i = 0; i < iod->npages; i++) {
+               __le64 *prp_list = list[i];
+               dma_addr_t next_prp_dma = le64_to_cpu(prp_list[last_prp]);
+               dma_pool_free(dev->prp_page_pool, prp_list, prp_dma);
+               prp_dma = next_prp_dma;
+       }
+       kfree(iod);
+}
+
+static void requeue_bio(struct nvme_dev *dev, struct bio *bio)
+{
+       struct nvme_queue *nvmeq = get_nvmeq(dev);
+       if (bio_list_empty(&nvmeq->sq_cong))
+               add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait);
+       bio_list_add(&nvmeq->sq_cong, bio);
+       put_nvmeq(nvmeq);
+       wake_up_process(nvme_thread);
+}
+
+static void bio_completion(struct nvme_dev *dev, void *ctx,
+                                               struct nvme_completion *cqe)
+{
+       struct nvme_iod *iod = ctx;
+       struct bio *bio = iod->private;
+       u16 status = le16_to_cpup(&cqe->status) >> 1;
+
+       dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents,
+                       bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       nvme_free_iod(dev, iod);
+       if (status) {
+               bio_endio(bio, -EIO);
+       } else if (bio->bi_vcnt > bio->bi_idx) {
+               requeue_bio(dev, bio);
+       } else {
+               bio_endio(bio, 0);
+       }
+}
+
+/* length is in bytes.  gfp flags indicates whether we may sleep. */
+static int nvme_setup_prps(struct nvme_dev *dev,
+                       struct nvme_common_command *cmd, struct nvme_iod *iod,
+                       int total_len, gfp_t gfp)
+{
+       struct dma_pool *pool;
+       int length = total_len;
+       struct scatterlist *sg = iod->sg;
+       int dma_len = sg_dma_len(sg);
+       u64 dma_addr = sg_dma_address(sg);
+       int offset = offset_in_page(dma_addr);
+       __le64 *prp_list;
+       __le64 **list = iod_list(iod);
+       dma_addr_t prp_dma;
+       int nprps, i;
+
+       cmd->prp1 = cpu_to_le64(dma_addr);
+       length -= (PAGE_SIZE - offset);
+       if (length <= 0)
+               return total_len;
+
+       dma_len -= (PAGE_SIZE - offset);
+       if (dma_len) {
+               dma_addr += (PAGE_SIZE - offset);
+       } else {
+               sg = sg_next(sg);
+               dma_addr = sg_dma_address(sg);
+               dma_len = sg_dma_len(sg);
+       }
+
+       if (length <= PAGE_SIZE) {
+               cmd->prp2 = cpu_to_le64(dma_addr);
+               return total_len;
+       }
+
+       nprps = DIV_ROUND_UP(length, PAGE_SIZE);
+       if (nprps <= (256 / 8)) {
+               pool = dev->prp_small_pool;
+               iod->npages = 0;
+       } else {
+               pool = dev->prp_page_pool;
+               iod->npages = 1;
+       }
+
+       prp_list = dma_pool_alloc(pool, gfp, &prp_dma);
+       if (!prp_list) {
+               cmd->prp2 = cpu_to_le64(dma_addr);
+               iod->npages = -1;
+               return (total_len - length) + PAGE_SIZE;
+       }
+       list[0] = prp_list;
+       iod->first_dma = prp_dma;
+       cmd->prp2 = cpu_to_le64(prp_dma);
+       i = 0;
+       for (;;) {
+               if (i == PAGE_SIZE / 8) {
+                       __le64 *old_prp_list = prp_list;
+                       prp_list = dma_pool_alloc(pool, gfp, &prp_dma);
+                       if (!prp_list)
+                               return total_len - length;
+                       list[iod->npages++] = prp_list;
+                       prp_list[0] = old_prp_list[i - 1];
+                       old_prp_list[i - 1] = cpu_to_le64(prp_dma);
+                       i = 1;
+               }
+               prp_list[i++] = cpu_to_le64(dma_addr);
+               dma_len -= PAGE_SIZE;
+               dma_addr += PAGE_SIZE;
+               length -= PAGE_SIZE;
+               if (length <= 0)
+                       break;
+               if (dma_len > 0)
+                       continue;
+               BUG_ON(dma_len < 0);
+               sg = sg_next(sg);
+               dma_addr = sg_dma_address(sg);
+               dma_len = sg_dma_len(sg);
+       }
+
+       return total_len;
+}
+
+/* NVMe scatterlists require no holes in the virtual address */
+#define BIOVEC_NOT_VIRT_MERGEABLE(vec1, vec2)  ((vec2)->bv_offset || \
+                       (((vec1)->bv_offset + (vec1)->bv_len) % PAGE_SIZE))
+
+static int nvme_map_bio(struct device *dev, struct nvme_iod *iod,
+               struct bio *bio, enum dma_data_direction dma_dir, int psegs)
+{
+       struct bio_vec *bvec, *bvprv = NULL;
+       struct scatterlist *sg = NULL;
+       int i, old_idx, length = 0, nsegs = 0;
+
+       sg_init_table(iod->sg, psegs);
+       old_idx = bio->bi_idx;
+       bio_for_each_segment(bvec, bio, i) {
+               if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) {
+                       sg->length += bvec->bv_len;
+               } else {
+                       if (bvprv && BIOVEC_NOT_VIRT_MERGEABLE(bvprv, bvec))
+                               break;
+                       sg = sg ? sg + 1 : iod->sg;
+                       sg_set_page(sg, bvec->bv_page, bvec->bv_len,
+                                                       bvec->bv_offset);
+                       nsegs++;
+               }
+               length += bvec->bv_len;
+               bvprv = bvec;
+       }
+       bio->bi_idx = i;
+       iod->nents = nsegs;
+       sg_mark_end(sg);
+       if (dma_map_sg(dev, iod->sg, iod->nents, dma_dir) == 0) {
+               bio->bi_idx = old_idx;
+               return -ENOMEM;
+       }
+       return length;
+}
+
+static int nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns,
+                                                               int cmdid)
+{
+       struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+
+       memset(cmnd, 0, sizeof(*cmnd));
+       cmnd->common.opcode = nvme_cmd_flush;
+       cmnd->common.command_id = cmdid;
+       cmnd->common.nsid = cpu_to_le32(ns->ns_id);
+
+       if (++nvmeq->sq_tail == nvmeq->q_depth)
+               nvmeq->sq_tail = 0;
+       writel(nvmeq->sq_tail, nvmeq->q_db);
+
+       return 0;
+}
+
+static int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns)
+{
+       int cmdid = alloc_cmdid(nvmeq, (void *)CMD_CTX_FLUSH,
+                                       special_completion, NVME_IO_TIMEOUT);
+       if (unlikely(cmdid < 0))
+               return cmdid;
+
+       return nvme_submit_flush(nvmeq, ns, cmdid);
+}
+
+/*
+ * Called with local interrupts disabled and the q_lock held.  May not sleep.
+ */
+static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
+                                                               struct bio *bio)
+{
+       struct nvme_command *cmnd;
+       struct nvme_iod *iod;
+       enum dma_data_direction dma_dir;
+       int cmdid, length, result = -ENOMEM;
+       u16 control;
+       u32 dsmgmt;
+       int psegs = bio_phys_segments(ns->queue, bio);
+
+       if ((bio->bi_rw & REQ_FLUSH) && psegs) {
+               result = nvme_submit_flush_data(nvmeq, ns);
+               if (result)
+                       return result;
+       }
+
+       iod = nvme_alloc_iod(psegs, bio->bi_size, GFP_ATOMIC);
+       if (!iod)
+               goto nomem;
+       iod->private = bio;
+
+       result = -EBUSY;
+       cmdid = alloc_cmdid(nvmeq, iod, bio_completion, NVME_IO_TIMEOUT);
+       if (unlikely(cmdid < 0))
+               goto free_iod;
+
+       if ((bio->bi_rw & REQ_FLUSH) && !psegs)
+               return nvme_submit_flush(nvmeq, ns, cmdid);
+
+       control = 0;
+       if (bio->bi_rw & REQ_FUA)
+               control |= NVME_RW_FUA;
+       if (bio->bi_rw & (REQ_FAILFAST_DEV | REQ_RAHEAD))
+               control |= NVME_RW_LR;
+
+       dsmgmt = 0;
+       if (bio->bi_rw & REQ_RAHEAD)
+               dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH;
+
+       cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+
+       memset(cmnd, 0, sizeof(*cmnd));
+       if (bio_data_dir(bio)) {
+               cmnd->rw.opcode = nvme_cmd_write;
+               dma_dir = DMA_TO_DEVICE;
+       } else {
+               cmnd->rw.opcode = nvme_cmd_read;
+               dma_dir = DMA_FROM_DEVICE;
+       }
+
+       result = nvme_map_bio(nvmeq->q_dmadev, iod, bio, dma_dir, psegs);
+       if (result < 0)
+               goto free_iod;
+       length = result;
+
+       cmnd->rw.command_id = cmdid;
+       cmnd->rw.nsid = cpu_to_le32(ns->ns_id);
+       length = nvme_setup_prps(nvmeq->dev, &cmnd->common, iod, length,
+                                                               GFP_ATOMIC);
+       cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9));
+       cmnd->rw.length = cpu_to_le16((length >> ns->lba_shift) - 1);
+       cmnd->rw.control = cpu_to_le16(control);
+       cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
+
+       bio->bi_sector += length >> 9;
+
+       if (++nvmeq->sq_tail == nvmeq->q_depth)
+               nvmeq->sq_tail = 0;
+       writel(nvmeq->sq_tail, nvmeq->q_db);
+
+       return 0;
+
+ free_iod:
+       nvme_free_iod(nvmeq->dev, iod);
+ nomem:
+       return result;
+}
+
+static void nvme_make_request(struct request_queue *q, struct bio *bio)
+{
+       struct nvme_ns *ns = q->queuedata;
+       struct nvme_queue *nvmeq = get_nvmeq(ns->dev);
+       int result = -EBUSY;
+
+       spin_lock_irq(&nvmeq->q_lock);
+       if (bio_list_empty(&nvmeq->sq_cong))
+               result = nvme_submit_bio_queue(nvmeq, ns, bio);
+       if (unlikely(result)) {
+               if (bio_list_empty(&nvmeq->sq_cong))
+                       add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait);
+               bio_list_add(&nvmeq->sq_cong, bio);
+       }
+
+       spin_unlock_irq(&nvmeq->q_lock);
+       put_nvmeq(nvmeq);
+}
+
+static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq)
+{
+       u16 head, phase;
+
+       head = nvmeq->cq_head;
+       phase = nvmeq->cq_phase;
+
+       for (;;) {
+               void *ctx;
+               nvme_completion_fn fn;
+               struct nvme_completion cqe = nvmeq->cqes[head];
+               if ((le16_to_cpu(cqe.status) & 1) != phase)
+                       break;
+               nvmeq->sq_head = le16_to_cpu(cqe.sq_head);
+               if (++head == nvmeq->q_depth) {
+                       head = 0;
+                       phase = !phase;
+               }
+
+               ctx = free_cmdid(nvmeq, cqe.command_id, &fn);
+               fn(nvmeq->dev, ctx, &cqe);
+       }
+
+       /* If the controller ignores the cq head doorbell and continuously
+        * writes to the queue, it is theoretically possible to wrap around
+        * the queue twice and mistakenly return IRQ_NONE.  Linux only
+        * requires that 0.1% of your interrupts are handled, so this isn't
+        * a big problem.
+        */
+       if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
+               return IRQ_NONE;
+
+       writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride));
+       nvmeq->cq_head = head;
+       nvmeq->cq_phase = phase;
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t nvme_irq(int irq, void *data)
+{
+       irqreturn_t result;
+       struct nvme_queue *nvmeq = data;
+       spin_lock(&nvmeq->q_lock);
+       result = nvme_process_cq(nvmeq);
+       spin_unlock(&nvmeq->q_lock);
+       return result;
+}
+
+static irqreturn_t nvme_irq_check(int irq, void *data)
+{
+       struct nvme_queue *nvmeq = data;
+       struct nvme_completion cqe = nvmeq->cqes[nvmeq->cq_head];
+       if ((le16_to_cpu(cqe.status) & 1) != nvmeq->cq_phase)
+               return IRQ_NONE;
+       return IRQ_WAKE_THREAD;
+}
+
+static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid)
+{
+       spin_lock_irq(&nvmeq->q_lock);
+       cancel_cmdid(nvmeq, cmdid, NULL);
+       spin_unlock_irq(&nvmeq->q_lock);
+}
+
+struct sync_cmd_info {
+       struct task_struct *task;
+       u32 result;
+       int status;
+};
+
+static void sync_completion(struct nvme_dev *dev, void *ctx,
+                                               struct nvme_completion *cqe)
+{
+       struct sync_cmd_info *cmdinfo = ctx;
+       cmdinfo->result = le32_to_cpup(&cqe->result);
+       cmdinfo->status = le16_to_cpup(&cqe->status) >> 1;
+       wake_up_process(cmdinfo->task);
+}
+
+/*
+ * Returns 0 on success.  If the result is negative, it's a Linux error code;
+ * if the result is positive, it's an NVM Express status code
+ */
+static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq,
+                       struct nvme_command *cmd, u32 *result, unsigned timeout)
+{
+       int cmdid;
+       struct sync_cmd_info cmdinfo;
+
+       cmdinfo.task = current;
+       cmdinfo.status = -EINTR;
+
+       cmdid = alloc_cmdid_killable(nvmeq, &cmdinfo, sync_completion,
+                                                               timeout);
+       if (cmdid < 0)
+               return cmdid;
+       cmd->common.command_id = cmdid;
+
+       set_current_state(TASK_KILLABLE);
+       nvme_submit_cmd(nvmeq, cmd);
+       schedule();
+
+       if (cmdinfo.status == -EINTR) {
+               nvme_abort_command(nvmeq, cmdid);
+               return -EINTR;
+       }
+
+       if (result)
+               *result = cmdinfo.result;
+
+       return cmdinfo.status;
+}
+
+static int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd,
+                                                               u32 *result)
+{
+       return nvme_submit_sync_cmd(dev->queues[0], cmd, result, ADMIN_TIMEOUT);
+}
+
+static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
+{
+       int status;
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.delete_queue.opcode = opcode;
+       c.delete_queue.qid = cpu_to_le16(id);
+
+       status = nvme_submit_admin_cmd(dev, &c, NULL);
+       if (status)
+               return -EIO;
+       return 0;
+}
+
+static int adapter_alloc_cq(struct nvme_dev *dev, u16 qid,
+                                               struct nvme_queue *nvmeq)
+{
+       int status;
+       struct nvme_command c;
+       int flags = NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED;
+
+       memset(&c, 0, sizeof(c));
+       c.create_cq.opcode = nvme_admin_create_cq;
+       c.create_cq.prp1 = cpu_to_le64(nvmeq->cq_dma_addr);
+       c.create_cq.cqid = cpu_to_le16(qid);
+       c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
+       c.create_cq.cq_flags = cpu_to_le16(flags);
+       c.create_cq.irq_vector = cpu_to_le16(nvmeq->cq_vector);
+
+       status = nvme_submit_admin_cmd(dev, &c, NULL);
+       if (status)
+               return -EIO;
+       return 0;
+}
+
+static int adapter_alloc_sq(struct nvme_dev *dev, u16 qid,
+                                               struct nvme_queue *nvmeq)
+{
+       int status;
+       struct nvme_command c;
+       int flags = NVME_QUEUE_PHYS_CONTIG | NVME_SQ_PRIO_MEDIUM;
+
+       memset(&c, 0, sizeof(c));
+       c.create_sq.opcode = nvme_admin_create_sq;
+       c.create_sq.prp1 = cpu_to_le64(nvmeq->sq_dma_addr);
+       c.create_sq.sqid = cpu_to_le16(qid);
+       c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
+       c.create_sq.sq_flags = cpu_to_le16(flags);
+       c.create_sq.cqid = cpu_to_le16(qid);
+
+       status = nvme_submit_admin_cmd(dev, &c, NULL);
+       if (status)
+               return -EIO;
+       return 0;
+}
+
+static int adapter_delete_cq(struct nvme_dev *dev, u16 cqid)
+{
+       return adapter_delete_queue(dev, nvme_admin_delete_cq, cqid);
+}
+
+static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid)
+{
+       return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid);
+}
+
+static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns,
+                                                       dma_addr_t dma_addr)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.identify.opcode = nvme_admin_identify;
+       c.identify.nsid = cpu_to_le32(nsid);
+       c.identify.prp1 = cpu_to_le64(dma_addr);
+       c.identify.cns = cpu_to_le32(cns);
+
+       return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
+                               unsigned dword11, dma_addr_t dma_addr)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.features.opcode = nvme_admin_get_features;
+       c.features.prp1 = cpu_to_le64(dma_addr);
+       c.features.fid = cpu_to_le32(fid);
+       c.features.dword11 = cpu_to_le32(dword11);
+
+       return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+static int nvme_set_features(struct nvme_dev *dev, unsigned fid,
+                       unsigned dword11, dma_addr_t dma_addr, u32 *result)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.features.opcode = nvme_admin_set_features;
+       c.features.prp1 = cpu_to_le64(dma_addr);
+       c.features.fid = cpu_to_le32(fid);
+       c.features.dword11 = cpu_to_le32(dword11);
+
+       return nvme_submit_admin_cmd(dev, &c, result);
+}
+
+static void nvme_free_queue(struct nvme_dev *dev, int qid)
+{
+       struct nvme_queue *nvmeq = dev->queues[qid];
+       int vector = dev->entry[nvmeq->cq_vector].vector;
+
+       irq_set_affinity_hint(vector, NULL);
+       free_irq(vector, nvmeq);
+
+       /* Don't tell the adapter to delete the admin queue */
+       if (qid) {
+               adapter_delete_sq(dev, qid);
+               adapter_delete_cq(dev, qid);
+       }
+
+       dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
+                               (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+       dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+                                       nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+       kfree(nvmeq);
+}
+
+static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
+                                                       int depth, int vector)
+{
+       struct device *dmadev = &dev->pci_dev->dev;
+       unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info));
+       struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL);
+       if (!nvmeq)
+               return NULL;
+
+       nvmeq->cqes = dma_alloc_coherent(dmadev, CQ_SIZE(depth),
+                                       &nvmeq->cq_dma_addr, GFP_KERNEL);
+       if (!nvmeq->cqes)
+               goto free_nvmeq;
+       memset((void *)nvmeq->cqes, 0, CQ_SIZE(depth));
+
+       nvmeq->sq_cmds = dma_alloc_coherent(dmadev, SQ_SIZE(depth),
+                                       &nvmeq->sq_dma_addr, GFP_KERNEL);
+       if (!nvmeq->sq_cmds)
+               goto free_cqdma;
+
+       nvmeq->q_dmadev = dmadev;
+       nvmeq->dev = dev;
+       spin_lock_init(&nvmeq->q_lock);
+       nvmeq->cq_head = 0;
+       nvmeq->cq_phase = 1;
+       init_waitqueue_head(&nvmeq->sq_full);
+       init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread);
+       bio_list_init(&nvmeq->sq_cong);
+       nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
+       nvmeq->q_depth = depth;
+       nvmeq->cq_vector = vector;
+
+       return nvmeq;
+
+ free_cqdma:
+       dma_free_coherent(dmadev, CQ_SIZE(nvmeq->q_depth), (void *)nvmeq->cqes,
+                                                       nvmeq->cq_dma_addr);
+ free_nvmeq:
+       kfree(nvmeq);
+       return NULL;
+}
+
+static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq,
+                                                       const char *name)
+{
+       if (use_threaded_interrupts)
+               return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector,
+                                       nvme_irq_check, nvme_irq,
+                                       IRQF_DISABLED | IRQF_SHARED,
+                                       name, nvmeq);
+       return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq,
+                               IRQF_DISABLED | IRQF_SHARED, name, nvmeq);
+}
+
+static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
+                                       int qid, int cq_size, int vector)
+{
+       int result;
+       struct nvme_queue *nvmeq = nvme_alloc_queue(dev, qid, cq_size, vector);
+
+       if (!nvmeq)
+               return ERR_PTR(-ENOMEM);
+
+       result = adapter_alloc_cq(dev, qid, nvmeq);
+       if (result < 0)
+               goto free_nvmeq;
+
+       result = adapter_alloc_sq(dev, qid, nvmeq);
+       if (result < 0)
+               goto release_cq;
+
+       result = queue_request_irq(dev, nvmeq, "nvme");
+       if (result < 0)
+               goto release_sq;
+
+       return nvmeq;
+
+ release_sq:
+       adapter_delete_sq(dev, qid);
+ release_cq:
+       adapter_delete_cq(dev, qid);
+ free_nvmeq:
+       dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
+                               (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+       dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+                                       nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+       kfree(nvmeq);
+       return ERR_PTR(result);
+}
+
+static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
+{
+       int result;
+       u32 aqa;
+       u64 cap;
+       unsigned long timeout;
+       struct nvme_queue *nvmeq;
+
+       dev->dbs = ((void __iomem *)dev->bar) + 4096;
+
+       nvmeq = nvme_alloc_queue(dev, 0, 64, 0);
+       if (!nvmeq)
+               return -ENOMEM;
+
+       aqa = nvmeq->q_depth - 1;
+       aqa |= aqa << 16;
+
+       dev->ctrl_config = NVME_CC_ENABLE | NVME_CC_CSS_NVM;
+       dev->ctrl_config |= (PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT;
+       dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE;
+       dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
+
+       writel(0, &dev->bar->cc);
+       writel(aqa, &dev->bar->aqa);
+       writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
+       writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
+       writel(dev->ctrl_config, &dev->bar->cc);
+
+       cap = readq(&dev->bar->cap);
+       timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
+       dev->db_stride = NVME_CAP_STRIDE(cap);
+
+       while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
+               msleep(100);
+               if (fatal_signal_pending(current))
+                       return -EINTR;
+               if (time_after(jiffies, timeout)) {
+                       dev_err(&dev->pci_dev->dev,
+                               "Device not ready; aborting initialisation\n");
+                       return -ENODEV;
+               }
+       }
+
+       result = queue_request_irq(dev, nvmeq, "nvme admin");
+       dev->queues[0] = nvmeq;
+       return result;
+}
+
+static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
+                               unsigned long addr, unsigned length)
+{
+       int i, err, count, nents, offset;
+       struct scatterlist *sg;
+       struct page **pages;
+       struct nvme_iod *iod;
+
+       if (addr & 3)
+               return ERR_PTR(-EINVAL);
+       if (!length)
+               return ERR_PTR(-EINVAL);
+
+       offset = offset_in_page(addr);
+       count = DIV_ROUND_UP(offset + length, PAGE_SIZE);
+       pages = kcalloc(count, sizeof(*pages), GFP_KERNEL);
+
+       err = get_user_pages_fast(addr, count, 1, pages);
+       if (err < count) {
+               count = err;
+               err = -EFAULT;
+               goto put_pages;
+       }
+
+       iod = nvme_alloc_iod(count, length, GFP_KERNEL);
+       sg = iod->sg;
+       sg_init_table(sg, count);
+       for (i = 0; i < count; i++) {
+               sg_set_page(&sg[i], pages[i],
+                               min_t(int, length, PAGE_SIZE - offset), offset);
+               length -= (PAGE_SIZE - offset);
+               offset = 0;
+       }
+       sg_mark_end(&sg[i - 1]);
+       iod->nents = count;
+
+       err = -ENOMEM;
+       nents = dma_map_sg(&dev->pci_dev->dev, sg, count,
+                               write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       if (!nents)
+               goto free_iod;
+
+       kfree(pages);
+       return iod;
+
+ free_iod:
+       kfree(iod);
+ put_pages:
+       for (i = 0; i < count; i++)
+               put_page(pages[i]);
+       kfree(pages);
+       return ERR_PTR(err);
+}
+
+static void nvme_unmap_user_pages(struct nvme_dev *dev, int write,
+                       struct nvme_iod *iod)
+{
+       int i;
+
+       dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents,
+                               write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+       for (i = 0; i < iod->nents; i++)
+               put_page(sg_page(&iod->sg[i]));
+}
+
+static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
+{
+       struct nvme_dev *dev = ns->dev;
+       struct nvme_queue *nvmeq;
+       struct nvme_user_io io;
+       struct nvme_command c;
+       unsigned length;
+       int status;
+       struct nvme_iod *iod;
+
+       if (copy_from_user(&io, uio, sizeof(io)))
+               return -EFAULT;
+       length = (io.nblocks + 1) << ns->lba_shift;
+
+       switch (io.opcode) {
+       case nvme_cmd_write:
+       case nvme_cmd_read:
+       case nvme_cmd_compare:
+               iod = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (IS_ERR(iod))
+               return PTR_ERR(iod);
+
+       memset(&c, 0, sizeof(c));
+       c.rw.opcode = io.opcode;
+       c.rw.flags = io.flags;
+       c.rw.nsid = cpu_to_le32(ns->ns_id);
+       c.rw.slba = cpu_to_le64(io.slba);
+       c.rw.length = cpu_to_le16(io.nblocks);
+       c.rw.control = cpu_to_le16(io.control);
+       c.rw.dsmgmt = cpu_to_le16(io.dsmgmt);
+       c.rw.reftag = io.reftag;
+       c.rw.apptag = io.apptag;
+       c.rw.appmask = io.appmask;
+       /* XXX: metadata */
+       length = nvme_setup_prps(dev, &c.common, iod, length, GFP_KERNEL);
+
+       nvmeq = get_nvmeq(dev);
+       /*
+        * Since nvme_submit_sync_cmd sleeps, we can't keep preemption
+        * disabled.  We may be preempted at any point, and be rescheduled
+        * to a different CPU.  That will cause cacheline bouncing, but no
+        * additional races since q_lock already protects against other CPUs.
+        */
+       put_nvmeq(nvmeq);
+       if (length != (io.nblocks + 1) << ns->lba_shift)
+               status = -ENOMEM;
+       else
+               status = nvme_submit_sync_cmd(nvmeq, &c, NULL, NVME_IO_TIMEOUT);
+
+       nvme_unmap_user_pages(dev, io.opcode & 1, iod);
+       nvme_free_iod(dev, iod);
+       return status;
+}
+
+static int nvme_user_admin_cmd(struct nvme_ns *ns,
+                                       struct nvme_admin_cmd __user *ucmd)
+{
+       struct nvme_dev *dev = ns->dev;
+       struct nvme_admin_cmd cmd;
+       struct nvme_command c;
+       int status, length;
+       struct nvme_iod *iod;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+       if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
+               return -EFAULT;
+
+       memset(&c, 0, sizeof(c));
+       c.common.opcode = cmd.opcode;
+       c.common.flags = cmd.flags;
+       c.common.nsid = cpu_to_le32(cmd.nsid);
+       c.common.cdw2[0] = cpu_to_le32(cmd.cdw2);
+       c.common.cdw2[1] = cpu_to_le32(cmd.cdw3);
+       c.common.cdw10[0] = cpu_to_le32(cmd.cdw10);
+       c.common.cdw10[1] = cpu_to_le32(cmd.cdw11);
+       c.common.cdw10[2] = cpu_to_le32(cmd.cdw12);
+       c.common.cdw10[3] = cpu_to_le32(cmd.cdw13);
+       c.common.cdw10[4] = cpu_to_le32(cmd.cdw14);
+       c.common.cdw10[5] = cpu_to_le32(cmd.cdw15);
+
+       length = cmd.data_len;
+       if (cmd.data_len) {
+               iod = nvme_map_user_pages(dev, cmd.opcode & 1, cmd.addr,
+                                                               length);
+               if (IS_ERR(iod))
+                       return PTR_ERR(iod);
+               length = nvme_setup_prps(dev, &c.common, iod, length,
+                                                               GFP_KERNEL);
+       }
+
+       if (length != cmd.data_len)
+               status = -ENOMEM;
+       else
+               status = nvme_submit_admin_cmd(dev, &c, NULL);
+
+       if (cmd.data_len) {
+               nvme_unmap_user_pages(dev, cmd.opcode & 1, iod);
+               nvme_free_iod(dev, iod);
+       }
+       return status;
+}
+
+static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
+                                                       unsigned long arg)
+{
+       struct nvme_ns *ns = bdev->bd_disk->private_data;
+
+       switch (cmd) {
+       case NVME_IOCTL_ID:
+               return ns->ns_id;
+       case NVME_IOCTL_ADMIN_CMD:
+               return nvme_user_admin_cmd(ns, (void __user *)arg);
+       case NVME_IOCTL_SUBMIT_IO:
+               return nvme_submit_io(ns, (void __user *)arg);
+       default:
+               return -ENOTTY;
+       }
+}
+
+static const struct block_device_operations nvme_fops = {
+       .owner          = THIS_MODULE,
+       .ioctl          = nvme_ioctl,
+       .compat_ioctl   = nvme_ioctl,
+};
+
+static void nvme_timeout_ios(struct nvme_queue *nvmeq)
+{
+       int depth = nvmeq->q_depth - 1;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+       unsigned long now = jiffies;
+       int cmdid;
+
+       for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
+               void *ctx;
+               nvme_completion_fn fn;
+               static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, };
+
+               if (!time_after(now, info[cmdid].timeout))
+                       continue;
+               dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid);
+               ctx = cancel_cmdid(nvmeq, cmdid, &fn);
+               fn(nvmeq->dev, ctx, &cqe);
+       }
+}
+
+static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
+{
+       while (bio_list_peek(&nvmeq->sq_cong)) {
+               struct bio *bio = bio_list_pop(&nvmeq->sq_cong);
+               struct nvme_ns *ns = bio->bi_bdev->bd_disk->private_data;
+               if (nvme_submit_bio_queue(nvmeq, ns, bio)) {
+                       bio_list_add_head(&nvmeq->sq_cong, bio);
+                       break;
+               }
+               if (bio_list_empty(&nvmeq->sq_cong))
+                       remove_wait_queue(&nvmeq->sq_full,
+                                                       &nvmeq->sq_cong_wait);
+       }
+}
+
+static int nvme_kthread(void *data)
+{
+       struct nvme_dev *dev;
+
+       while (!kthread_should_stop()) {
+               __set_current_state(TASK_RUNNING);
+               spin_lock(&dev_list_lock);
+               list_for_each_entry(dev, &dev_list, node) {
+                       int i;
+                       for (i = 0; i < dev->queue_count; i++) {
+                               struct nvme_queue *nvmeq = dev->queues[i];
+                               if (!nvmeq)
+                                       continue;
+                               spin_lock_irq(&nvmeq->q_lock);
+                               if (nvme_process_cq(nvmeq))
+                                       printk("process_cq did something\n");
+                               nvme_timeout_ios(nvmeq);
+                               nvme_resubmit_bios(nvmeq);
+                               spin_unlock_irq(&nvmeq->q_lock);
+                       }
+               }
+               spin_unlock(&dev_list_lock);
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(HZ);
+       }
+       return 0;
+}
+
+static DEFINE_IDA(nvme_index_ida);
+
+static int nvme_get_ns_idx(void)
+{
+       int index, error;
+
+       do {
+               if (!ida_pre_get(&nvme_index_ida, GFP_KERNEL))
+                       return -1;
+
+               spin_lock(&dev_list_lock);
+               error = ida_get_new(&nvme_index_ida, &index);
+               spin_unlock(&dev_list_lock);
+       } while (error == -EAGAIN);
+
+       if (error)
+               index = -1;
+       return index;
+}
+
+static void nvme_put_ns_idx(int index)
+{
+       spin_lock(&dev_list_lock);
+       ida_remove(&nvme_index_ida, index);
+       spin_unlock(&dev_list_lock);
+}
+
+static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid,
+                       struct nvme_id_ns *id, struct nvme_lba_range_type *rt)
+{
+       struct nvme_ns *ns;
+       struct gendisk *disk;
+       int lbaf;
+
+       if (rt->attributes & NVME_LBART_ATTRIB_HIDE)
+               return NULL;
+
+       ns = kzalloc(sizeof(*ns), GFP_KERNEL);
+       if (!ns)
+               return NULL;
+       ns->queue = blk_alloc_queue(GFP_KERNEL);
+       if (!ns->queue)
+               goto out_free_ns;
+       ns->queue->queue_flags = QUEUE_FLAG_DEFAULT;
+       queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, ns->queue);
+       queue_flag_set_unlocked(QUEUE_FLAG_NONROT, ns->queue);
+/*     queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, ns->queue); */
+       blk_queue_make_request(ns->queue, nvme_make_request);
+       ns->dev = dev;
+       ns->queue->queuedata = ns;
+
+       disk = alloc_disk(NVME_MINORS);
+       if (!disk)
+               goto out_free_queue;
+       ns->ns_id = nsid;
+       ns->disk = disk;
+       lbaf = id->flbas & 0xf;
+       ns->lba_shift = id->lbaf[lbaf].ds;
+
+       disk->major = nvme_major;
+       disk->minors = NVME_MINORS;
+       disk->first_minor = NVME_MINORS * nvme_get_ns_idx();
+       disk->fops = &nvme_fops;
+       disk->private_data = ns;
+       disk->queue = ns->queue;
+       disk->driverfs_dev = &dev->pci_dev->dev;
+       sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
+       set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
+
+       return ns;
+
+ out_free_queue:
+       blk_cleanup_queue(ns->queue);
+ out_free_ns:
+       kfree(ns);
+       return NULL;
+}
+
+static void nvme_ns_free(struct nvme_ns *ns)
+{
+       int index = ns->disk->first_minor / NVME_MINORS;
+       put_disk(ns->disk);
+       nvme_put_ns_idx(index);
+       blk_cleanup_queue(ns->queue);
+       kfree(ns);
+}
+
+static int set_queue_count(struct nvme_dev *dev, int count)
+{
+       int status;
+       u32 result;
+       u32 q_count = (count - 1) | ((count - 1) << 16);
+
+       status = nvme_set_features(dev, NVME_FEAT_NUM_QUEUES, q_count, 0,
+                                                               &result);
+       if (status)
+               return -EIO;
+       return min(result & 0xffff, result >> 16) + 1;
+}
+
+static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
+{
+       int result, cpu, i, nr_io_queues, db_bar_size;
+
+       nr_io_queues = num_online_cpus();
+       result = set_queue_count(dev, nr_io_queues);
+       if (result < 0)
+               return result;
+       if (result < nr_io_queues)
+               nr_io_queues = result;
+
+       /* Deregister the admin queue's interrupt */
+       free_irq(dev->entry[0].vector, dev->queues[0]);
+
+       db_bar_size = 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3));
+       if (db_bar_size > 8192) {
+               iounmap(dev->bar);
+               dev->bar = ioremap(pci_resource_start(dev->pci_dev, 0),
+                                                               db_bar_size);
+               dev->dbs = ((void __iomem *)dev->bar) + 4096;
+               dev->queues[0]->q_db = dev->dbs;
+       }
+
+       for (i = 0; i < nr_io_queues; i++)
+               dev->entry[i].entry = i;
+       for (;;) {
+               result = pci_enable_msix(dev->pci_dev, dev->entry,
+                                                               nr_io_queues);
+               if (result == 0) {
+                       break;
+               } else if (result > 0) {
+                       nr_io_queues = result;
+                       continue;
+               } else {
+                       nr_io_queues = 1;
+                       break;
+               }
+       }
+
+       result = queue_request_irq(dev, dev->queues[0], "nvme admin");
+       /* XXX: handle failure here */
+
+       cpu = cpumask_first(cpu_online_mask);
+       for (i = 0; i < nr_io_queues; i++) {
+               irq_set_affinity_hint(dev->entry[i].vector, get_cpu_mask(cpu));
+               cpu = cpumask_next(cpu, cpu_online_mask);
+       }
+
+       for (i = 0; i < nr_io_queues; i++) {
+               dev->queues[i + 1] = nvme_create_queue(dev, i + 1,
+                                                       NVME_Q_DEPTH, i);
+               if (IS_ERR(dev->queues[i + 1]))
+                       return PTR_ERR(dev->queues[i + 1]);
+               dev->queue_count++;
+       }
+
+       for (; i < num_possible_cpus(); i++) {
+               int target = i % rounddown_pow_of_two(dev->queue_count - 1);
+               dev->queues[i + 1] = dev->queues[target + 1];
+       }
+
+       return 0;
+}
+
+static void nvme_free_queues(struct nvme_dev *dev)
+{
+       int i;
+
+       for (i = dev->queue_count - 1; i >= 0; i--)
+               nvme_free_queue(dev, i);
+}
+
+static int __devinit nvme_dev_add(struct nvme_dev *dev)
+{
+       int res, nn, i;
+       struct nvme_ns *ns, *next;
+       struct nvme_id_ctrl *ctrl;
+       struct nvme_id_ns *id_ns;
+       void *mem;
+       dma_addr_t dma_addr;
+
+       res = nvme_setup_io_queues(dev);
+       if (res)
+               return res;
+
+       mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr,
+                                                               GFP_KERNEL);
+
+       res = nvme_identify(dev, 0, 1, dma_addr);
+       if (res) {
+               res = -EIO;
+               goto out_free;
+       }
+
+       ctrl = mem;
+       nn = le32_to_cpup(&ctrl->nn);
+       memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
+       memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
+       memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
+
+       id_ns = mem;
+       for (i = 1; i <= nn; i++) {
+               res = nvme_identify(dev, i, 0, dma_addr);
+               if (res)
+                       continue;
+
+               if (id_ns->ncap == 0)
+                       continue;
+
+               res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i,
+                                                       dma_addr + 4096);
+               if (res)
+                       continue;
+
+               ns = nvme_alloc_ns(dev, i, mem, mem + 4096);
+               if (ns)
+                       list_add_tail(&ns->list, &dev->namespaces);
+       }
+       list_for_each_entry(ns, &dev->namespaces, list)
+               add_disk(ns->disk);
+
+       goto out;
+
+ out_free:
+       list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
+               list_del(&ns->list);
+               nvme_ns_free(ns);
+       }
+
+ out:
+       dma_free_coherent(&dev->pci_dev->dev, 8192, mem, dma_addr);
+       return res;
+}
+
+static int nvme_dev_remove(struct nvme_dev *dev)
+{
+       struct nvme_ns *ns, *next;
+
+       spin_lock(&dev_list_lock);
+       list_del(&dev->node);
+       spin_unlock(&dev_list_lock);
+
+       /* TODO: wait all I/O finished or cancel them */
+
+       list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
+               list_del(&ns->list);
+               del_gendisk(ns->disk);
+               nvme_ns_free(ns);
+       }
+
+       nvme_free_queues(dev);
+
+       return 0;
+}
+
+static int nvme_setup_prp_pools(struct nvme_dev *dev)
+{
+       struct device *dmadev = &dev->pci_dev->dev;
+       dev->prp_page_pool = dma_pool_create("prp list page", dmadev,
+                                               PAGE_SIZE, PAGE_SIZE, 0);
+       if (!dev->prp_page_pool)
+               return -ENOMEM;
+
+       /* Optimisation for I/Os between 4k and 128k */
+       dev->prp_small_pool = dma_pool_create("prp list 256", dmadev,
+                                               256, 256, 0);
+       if (!dev->prp_small_pool) {
+               dma_pool_destroy(dev->prp_page_pool);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void nvme_release_prp_pools(struct nvme_dev *dev)
+{
+       dma_pool_destroy(dev->prp_page_pool);
+       dma_pool_destroy(dev->prp_small_pool);
+}
+
+/* XXX: Use an ida or something to let remove / add work correctly */
+static void nvme_set_instance(struct nvme_dev *dev)
+{
+       static int instance;
+       dev->instance = instance++;
+}
+
+static void nvme_release_instance(struct nvme_dev *dev)
+{
+}
+
+static int __devinit nvme_probe(struct pci_dev *pdev,
+                                               const struct pci_device_id *id)
+{
+       int bars, result = -ENOMEM;
+       struct nvme_dev *dev;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+       dev->entry = kcalloc(num_possible_cpus(), sizeof(*dev->entry),
+                                                               GFP_KERNEL);
+       if (!dev->entry)
+               goto free;
+       dev->queues = kcalloc(num_possible_cpus() + 1, sizeof(void *),
+                                                               GFP_KERNEL);
+       if (!dev->queues)
+               goto free;
+
+       if (pci_enable_device_mem(pdev))
+               goto free;
+       pci_set_master(pdev);
+       bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       if (pci_request_selected_regions(pdev, bars, "nvme"))
+               goto disable;
+
+       INIT_LIST_HEAD(&dev->namespaces);
+       dev->pci_dev = pdev;
+       pci_set_drvdata(pdev, dev);
+       dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+       nvme_set_instance(dev);
+       dev->entry[0].vector = pdev->irq;
+
+       result = nvme_setup_prp_pools(dev);
+       if (result)
+               goto disable_msix;
+
+       dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
+       if (!dev->bar) {
+               result = -ENOMEM;
+               goto disable_msix;
+       }
+
+       result = nvme_configure_admin_queue(dev);
+       if (result)
+               goto unmap;
+       dev->queue_count++;
+
+       spin_lock(&dev_list_lock);
+       list_add(&dev->node, &dev_list);
+       spin_unlock(&dev_list_lock);
+
+       result = nvme_dev_add(dev);
+       if (result)
+               goto delete;
+
+       return 0;
+
+ delete:
+       spin_lock(&dev_list_lock);
+       list_del(&dev->node);
+       spin_unlock(&dev_list_lock);
+
+       nvme_free_queues(dev);
+ unmap:
+       iounmap(dev->bar);
+ disable_msix:
+       pci_disable_msix(pdev);
+       nvme_release_instance(dev);
+       nvme_release_prp_pools(dev);
+ disable:
+       pci_disable_device(pdev);
+       pci_release_regions(pdev);
+ free:
+       kfree(dev->queues);
+       kfree(dev->entry);
+       kfree(dev);
+       return result;
+}
+
+static void __devexit nvme_remove(struct pci_dev *pdev)
+{
+       struct nvme_dev *dev = pci_get_drvdata(pdev);
+       nvme_dev_remove(dev);
+       pci_disable_msix(pdev);
+       iounmap(dev->bar);
+       nvme_release_instance(dev);
+       nvme_release_prp_pools(dev);
+       pci_disable_device(pdev);
+       pci_release_regions(pdev);
+       kfree(dev->queues);
+       kfree(dev->entry);
+       kfree(dev);
+}
+
+/* These functions are yet to be implemented */
+#define nvme_error_detected NULL
+#define nvme_dump_registers NULL
+#define nvme_link_reset NULL
+#define nvme_slot_reset NULL
+#define nvme_error_resume NULL
+#define nvme_suspend NULL
+#define nvme_resume NULL
+
+static struct pci_error_handlers nvme_err_handler = {
+       .error_detected = nvme_error_detected,
+       .mmio_enabled   = nvme_dump_registers,
+       .link_reset     = nvme_link_reset,
+       .slot_reset     = nvme_slot_reset,
+       .resume         = nvme_error_resume,
+};
+
+/* Move to pci_ids.h later */
+#define PCI_CLASS_STORAGE_EXPRESS      0x010802
+
+static DEFINE_PCI_DEVICE_TABLE(nvme_id_table) = {
+       { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, nvme_id_table);
+
+static struct pci_driver nvme_driver = {
+       .name           = "nvme",
+       .id_table       = nvme_id_table,
+       .probe          = nvme_probe,
+       .remove         = __devexit_p(nvme_remove),
+       .suspend        = nvme_suspend,
+       .resume         = nvme_resume,
+       .err_handler    = &nvme_err_handler,
+};
+
+static int __init nvme_init(void)
+{
+       int result = -EBUSY;
+
+       nvme_thread = kthread_run(nvme_kthread, NULL, "nvme");
+       if (IS_ERR(nvme_thread))
+               return PTR_ERR(nvme_thread);
+
+       nvme_major = register_blkdev(nvme_major, "nvme");
+       if (nvme_major <= 0)
+               goto kill_kthread;
+
+       result = pci_register_driver(&nvme_driver);
+       if (result)
+               goto unregister_blkdev;
+       return 0;
+
+ unregister_blkdev:
+       unregister_blkdev(nvme_major, "nvme");
+ kill_kthread:
+       kthread_stop(nvme_thread);
+       return result;
+}
+
+static void __exit nvme_exit(void)
+{
+       pci_unregister_driver(&nvme_driver);
+       unregister_blkdev(nvme_major, "nvme");
+       kthread_stop(nvme_thread);
+}
+
+MODULE_AUTHOR("Matthew Wilcox <willy@linux.intel.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.8");
+module_init(nvme_init);
+module_exit(nvme_exit);
index 3fd31dec8c9c1980fcdc8f7aa95b28d23addcb5b..a6278e7e61a00bfde01bcb6726524ffb3a06514e 100644 (file)
@@ -380,6 +380,7 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
        rbdc = __rbd_client_find(opt);
        if (rbdc) {
                ceph_destroy_options(opt);
+               kfree(rbd_opts);
 
                /* using an existing client */
                kref_get(&rbdc->kref);
@@ -406,15 +407,15 @@ done_err:
 
 /*
  * Destroy ceph client
+ *
+ * Caller must hold node_lock.
  */
 static void rbd_client_release(struct kref *kref)
 {
        struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
 
        dout("rbd_release_client %p\n", rbdc);
-       spin_lock(&node_lock);
        list_del(&rbdc->node);
-       spin_unlock(&node_lock);
 
        ceph_destroy_client(rbdc->client);
        kfree(rbdc->rbd_opts);
@@ -427,7 +428,9 @@ static void rbd_client_release(struct kref *kref)
  */
 static void rbd_put_client(struct rbd_device *rbd_dev)
 {
+       spin_lock(&node_lock);
        kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+       spin_unlock(&node_lock);
        rbd_dev->rbd_client = NULL;
        rbd_dev->client = NULL;
 }
index 55eaf474d32c3afa18aab0433552edc4dc193f6f..d620b44957454a80fcf444d10cb967e66fb9d7d5 100644 (file)
 
 /* used to tell the module to turn on full debugging messages */
 static bool debug;
-/* used to keep tray locked at all times */
-static int keeplocked;
 /* default compatibility mode */
 static bool autoclose=1;
 static bool autoeject;
@@ -1204,7 +1202,7 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
                cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
                cdrom_dvd_rw_close_write(cdi);
 
-               if ((cdo->capability & CDC_LOCK) && !keeplocked) {
+               if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) {
                        cdinfo(CD_CLOSE, "Unlocking door!\n");
                        cdo->lock_door(cdi, 0);
                }
@@ -1371,7 +1369,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
        curslot = info->hdr.curslot;
        kfree(info);
 
-       if (cdi->use_count > 1 || keeplocked) {
+       if (cdi->use_count > 1 || cdi->keeplocked) {
                if (slot == CDSL_CURRENT) {
                        return curslot;
                } else {
@@ -2119,11 +2117,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
        if (!nr)
                return -ENOMEM;
 
-       if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
        cgc.data_direction = CGC_DATA_READ;
        while (nframes > 0) {
                if (nr > nframes)
@@ -2132,7 +2125,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
                if (ret)
                        break;
-               if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
+               if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2140,7 +2133,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                nframes -= nr;
                lba += nr;
        }
-out:
        kfree(cgc.buffer);
        return ret;
 }
@@ -2295,7 +2287,7 @@ static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
 
        if (!CDROM_CAN(CDC_OPEN_TRAY))
                return -ENOSYS;
-       if (cdi->use_count != 1 || keeplocked)
+       if (cdi->use_count != 1 || cdi->keeplocked)
                return -EBUSY;
        if (CDROM_CAN(CDC_LOCK)) {
                int ret = cdi->ops->lock_door(cdi, 0);
@@ -2322,7 +2314,7 @@ static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,
 
        if (!CDROM_CAN(CDC_OPEN_TRAY))
                return -ENOSYS;
-       if (keeplocked)
+       if (cdi->keeplocked)
                return -EBUSY;
 
        cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
@@ -2453,7 +2445,7 @@ static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi,
        if (!CDROM_CAN(CDC_LOCK))
                return -EDRIVE_CANT_DO_THIS;
 
-       keeplocked = arg ? 1 : 0;
+       cdi->keeplocked = arg ? 1 : 0;
 
        /*
         * Don't unlock the door on multiple opens by default, but allow
index 4b71647782d03d16c38dd1cb319ed396daa9844c..317c28ce8328bb310c892c8bab4aca60cbbbc4f5 100644 (file)
@@ -194,10 +194,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
 
 err_out:
        if (bridge->driver->needs_scratch_page) {
-               void *va = page_address(bridge->scratch_page_page);
+               struct page *page = bridge->scratch_page_page;
 
-               bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
-               bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
+               bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+               bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
        }
        if (got_gatt)
                bridge->driver->free_gatt_table(bridge);
@@ -221,10 +221,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
 
        if (bridge->driver->agp_destroy_page &&
            bridge->driver->needs_scratch_page) {
-               void *va = page_address(bridge->scratch_page_page);
+               struct page *page = bridge->scratch_page_page;
 
-               bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
-               bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
+               bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+               bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
        }
 }
 
index 6a8771f47a55c799866468fe80946a479a0440f8..32362cf35b8d1a42c4b1f3e4f67881687ecad0cc 100644 (file)
@@ -846,6 +846,15 @@ int tpm_do_selftest(struct tpm_chip *chip)
 
        do {
                rc = __tpm_pcr_read(chip, 0, digest);
+               if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
+                       dev_info(chip->dev,
+                                "TPM is disabled/deactivated (0x%X)\n", rc);
+                       /* TPM is disabled and/or deactivated; driver can
+                        * proceed and TPM does handle commands for
+                        * suspend/resume correctly
+                        */
+                       return 0;
+               }
                if (rc != TPM_WARN_DOING_SELFTEST)
                        return rc;
                msleep(delay_msec);
index 8c1df302fbb6ce17cd9580cca1aaeca84f785745..01054713828128ea59fa1c06b2adf035b8b3f281 100644 (file)
@@ -39,6 +39,9 @@ enum tpm_addr {
 };
 
 #define TPM_WARN_DOING_SELFTEST 0x802
+#define TPM_ERR_DEACTIVATED     0x6
+#define TPM_ERR_DISABLED        0x7
+
 #define TPM_HEADER_SIZE                10
 extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
                                char *);
index 7dbc4a83c45c481cdf743fb531c95a4b67a8bb5a..78a666d1e5f589892620edc200b24c4b254ec273 100644 (file)
@@ -1,7 +1,7 @@
 
 config CPU_IDLE
        bool "CPU idle PM support"
-       default ACPI
+       default y if ACPI || PPC_PSERIES
        help
          CPU idle is a generic framework for supporting software-controlled
          idle processor power management.  It includes modular cross-platform
index 5a99bb3f255ae7c34fedc540949ab0163a15d5a5..f1a274994bb1fbdc1c8e0e54b26aebe58b161c2b 100644 (file)
@@ -124,7 +124,7 @@ config MV_XOR
 
 config MX3_IPU
        bool "MX3x Image Processing Unit support"
-       depends on SOC_IMX31 || SOC_IMX35
+       depends on ARCH_MXC
        select DMA_ENGINE
        default y
        help
@@ -187,6 +187,13 @@ config TIMB_DMA
        help
          Enable support for the Timberdale FPGA DMA engine.
 
+config SIRF_DMA
+       tristate "CSR SiRFprimaII DMA support"
+       depends on ARCH_PRIMA2
+       select DMA_ENGINE
+       help
+         Enable support for the CSR SiRFprimaII DMA engine.
+
 config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        bool
 
@@ -201,26 +208,26 @@ config PL330_DMA
          platform_data for a dma-pl330 device.
 
 config PCH_DMA
-       tristate "Intel EG20T PCH / OKI Semi IOH(ML7213/ML7223) DMA support"
+       tristate "Intel EG20T PCH / LAPIS Semicon IOH(ML7213/ML7223/ML7831) DMA"
        depends on PCI && X86
        select DMA_ENGINE
        help
          Enable support for Intel EG20T PCH DMA engine.
 
-         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 IMX_SDMA
        tristate "i.MX SDMA support"
-       depends on ARCH_MX25 || SOC_IMX31 || SOC_IMX35 || ARCH_MX5
+       depends on ARCH_MXC
        select DMA_ENGINE
        help
          Support the i.MX SDMA engine. This engine is integrated into
-         Freescale i.MX25/31/35/51 chips.
+         Freescale i.MX25/31/35/51/53 chips.
 
 config IMX_DMA
        tristate "i.MX DMA support"
index 30cf3b1f0c5ca4ff633d9e50474feef0a49fc565..009a222e8283cba3929fd8763ae9abe9b4d6d694 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
 obj-$(CONFIG_IMX_DMA) += imx-dma.o
 obj-$(CONFIG_MXS_DMA) += mxs-dma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
+obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
 obj-$(CONFIG_PCH_DMA) += pch_dma.o
index 0698695e8bf9508e0c0dac5cdad44f7f8f508c07..8a281584458b582bbb872137323ff82cdaac2eb1 100644 (file)
@@ -854,8 +854,10 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
        int ret;
 
        /* Check if we already have a channel */
-       if (plchan->phychan)
-               return 0;
+       if (plchan->phychan) {
+               ch = plchan->phychan;
+               goto got_channel;
+       }
 
        ch = pl08x_get_phy_channel(pl08x, plchan);
        if (!ch) {
@@ -880,21 +882,22 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
                        return -EBUSY;
                }
                ch->signal = ret;
-
-               /* Assign the flow control signal to this channel */
-               if (txd->direction == DMA_TO_DEVICE)
-                       txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT;
-               else if (txd->direction == DMA_FROM_DEVICE)
-                       txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT;
        }
 
+       plchan->phychan = ch;
        dev_dbg(&pl08x->adev->dev, "allocated physical channel %d and signal %d for xfer on %s\n",
                 ch->id,
                 ch->signal,
                 plchan->name);
 
+got_channel:
+       /* Assign the flow control signal to this channel */
+       if (txd->direction == DMA_MEM_TO_DEV)
+               txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT;
+       else if (txd->direction == DMA_DEV_TO_MEM)
+               txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT;
+
        plchan->phychan_hold++;
-       plchan->phychan = ch;
 
        return 0;
 }
@@ -1102,10 +1105,10 @@ static int dma_set_runtime_config(struct dma_chan *chan,
 
        /* Transfer direction */
        plchan->runtime_direction = config->direction;
-       if (config->direction == DMA_TO_DEVICE) {
+       if (config->direction == DMA_MEM_TO_DEV) {
                addr_width = config->dst_addr_width;
                maxburst = config->dst_maxburst;
-       } else if (config->direction == DMA_FROM_DEVICE) {
+       } else if (config->direction == DMA_DEV_TO_MEM) {
                addr_width = config->src_addr_width;
                maxburst = config->src_maxburst;
        } else {
@@ -1136,7 +1139,7 @@ static int dma_set_runtime_config(struct dma_chan *chan,
        cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT;
        cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT;
 
-       if (plchan->runtime_direction == DMA_FROM_DEVICE) {
+       if (plchan->runtime_direction == DMA_DEV_TO_MEM) {
                plchan->src_addr = config->src_addr;
                plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR |
                        pl08x_select_bus(plchan->cd->periph_buses,
@@ -1152,7 +1155,7 @@ static int dma_set_runtime_config(struct dma_chan *chan,
                "configured channel %s (%s) for %s, data width %d, "
                "maxburst %d words, LE, CCTL=0x%08x\n",
                dma_chan_name(chan), plchan->name,
-               (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
+               (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX",
                addr_width,
                maxburst,
                cctl);
@@ -1322,7 +1325,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
 
 static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
@@ -1354,10 +1357,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
         */
        txd->direction = direction;
 
-       if (direction == DMA_TO_DEVICE) {
+       if (direction == DMA_MEM_TO_DEV) {
                txd->cctl = plchan->dst_cctl;
                slave_addr = plchan->dst_addr;
-       } else if (direction == DMA_FROM_DEVICE) {
+       } else if (direction == DMA_DEV_TO_MEM) {
                txd->cctl = plchan->src_cctl;
                slave_addr = plchan->src_addr;
        } else {
@@ -1368,10 +1371,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        }
 
        if (plchan->cd->device_fc)
-               tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
+               tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER_PER :
                        PL080_FLOW_PER2MEM_PER;
        else
-               tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
+               tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER :
                        PL080_FLOW_PER2MEM;
 
        txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
@@ -1387,7 +1390,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                list_add_tail(&dsg->node, &txd->dsg_list);
 
                dsg->len = sg_dma_len(sg);
-               if (direction == DMA_TO_DEVICE) {
+               if (direction == DMA_MEM_TO_DEV) {
                        dsg->src_addr = sg_phys(sg);
                        dsg->dst_addr = slave_addr;
                } else {
index fcfa0a8b5c59956516060cd9ff5535f6524a819f..f4aed5fc2cb6c33d87d8932d8603f705d3d2e589 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include "at_hdmac_regs.h"
 
@@ -660,7 +662,7 @@ err_desc_get:
  */
 static struct dma_async_tx_descriptor *
 atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
@@ -678,7 +680,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
        dev_vdbg(chan2dev(chan), "prep_slave_sg (%d): %s f0x%lx\n",
                        sg_len,
-                       direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE",
+                       direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE",
                        flags);
 
        if (unlikely(!atslave || !sg_len)) {
@@ -692,7 +694,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        ctrlb = ATC_IEN;
 
        switch (direction) {
-       case DMA_TO_DEVICE:
+       case DMA_MEM_TO_DEV:
                ctrla |=  ATC_DST_WIDTH(reg_width);
                ctrlb |=  ATC_DST_ADDR_MODE_FIXED
                        | ATC_SRC_ADDR_MODE_INCR
@@ -725,7 +727,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        total_len += len;
                }
                break;
-       case DMA_FROM_DEVICE:
+       case DMA_DEV_TO_MEM:
                ctrla |=  ATC_SRC_WIDTH(reg_width);
                ctrlb |=  ATC_DST_ADDR_MODE_INCR
                        | ATC_SRC_ADDR_MODE_FIXED
@@ -787,7 +789,7 @@ err_desc_get:
  */
 static int
 atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        if (period_len > (ATC_BTSIZE_MAX << reg_width))
                goto err_out;
@@ -795,7 +797,7 @@ atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr,
                goto err_out;
        if (unlikely(buf_addr & ((1 << reg_width) - 1)))
                goto err_out;
-       if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE))))
+       if (unlikely(!(direction & (DMA_DEV_TO_MEM | DMA_MEM_TO_DEV))))
                goto err_out;
 
        return 0;
@@ -810,7 +812,7 @@ err_out:
 static int
 atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
                unsigned int period_index, dma_addr_t buf_addr,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        u32             ctrla;
        unsigned int    reg_width = atslave->reg_width;
@@ -822,7 +824,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
                | period_len >> reg_width;
 
        switch (direction) {
-       case DMA_TO_DEVICE:
+       case DMA_MEM_TO_DEV:
                desc->lli.saddr = buf_addr + (period_len * period_index);
                desc->lli.daddr = atslave->tx_reg;
                desc->lli.ctrla = ctrla;
@@ -833,7 +835,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
                                | ATC_DIF(AT_DMA_PER_IF);
                break;
 
-       case DMA_FROM_DEVICE:
+       case DMA_DEV_TO_MEM:
                desc->lli.saddr = atslave->rx_reg;
                desc->lli.daddr = buf_addr + (period_len * period_index);
                desc->lli.ctrla = ctrla;
@@ -861,7 +863,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
  */
 static struct dma_async_tx_descriptor *
 atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma_slave     *atslave = chan->private;
@@ -872,7 +874,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
        unsigned int            i;
 
        dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@0x%08x - %d (%d/%d)\n",
-                       direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE",
+                       direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE",
                        buf_addr,
                        periods, buf_len, period_len);
 
@@ -1175,6 +1177,56 @@ static void atc_free_chan_resources(struct dma_chan *chan)
 
 /*--  Module Management  -----------------------------------------------*/
 
+/* cap_mask is a multi-u32 bitfield, fill it with proper C code. */
+static struct at_dma_platform_data at91sam9rl_config = {
+       .nr_channels = 2,
+};
+static struct at_dma_platform_data at91sam9g45_config = {
+       .nr_channels = 8,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_dma_dt_ids[] = {
+       {
+               .compatible = "atmel,at91sam9rl-dma",
+               .data = &at91sam9rl_config,
+       }, {
+               .compatible = "atmel,at91sam9g45-dma",
+               .data = &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids);
+#endif
+
+static const struct platform_device_id atdma_devtypes[] = {
+       {
+               .name = "at91sam9rl_dma",
+               .driver_data = (unsigned long) &at91sam9rl_config,
+       }, {
+               .name = "at91sam9g45_dma",
+               .driver_data = (unsigned long) &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+
+static inline struct at_dma_platform_data * __init at_dma_get_driver_data(
+                                               struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(atmel_dma_dt_ids, pdev->dev.of_node);
+               if (match == NULL)
+                       return NULL;
+               return match->data;
+       }
+       return (struct at_dma_platform_data *)
+                       platform_get_device_id(pdev)->driver_data;
+}
+
 /**
  * at_dma_off - disable DMA controller
  * @atdma: the Atmel HDAMC device
@@ -1193,18 +1245,23 @@ static void at_dma_off(struct at_dma *atdma)
 
 static int __init at_dma_probe(struct platform_device *pdev)
 {
-       struct at_dma_platform_data *pdata;
        struct resource         *io;
        struct at_dma           *atdma;
        size_t                  size;
        int                     irq;
        int                     err;
        int                     i;
+       struct at_dma_platform_data *plat_dat;
 
-       /* get DMA Controller parameters from platform */
-       pdata = pdev->dev.platform_data;
-       if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS)
-               return -EINVAL;
+       /* setup platform data for each SoC */
+       dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask);
+       dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask);
+       dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask);
+
+       /* get DMA parameters from controller type */
+       plat_dat = at_dma_get_driver_data(pdev);
+       if (!plat_dat)
+               return -ENODEV;
 
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!io)
@@ -1215,14 +1272,14 @@ static int __init at_dma_probe(struct platform_device *pdev)
                return irq;
 
        size = sizeof(struct at_dma);
-       size += pdata->nr_channels * sizeof(struct at_dma_chan);
+       size += plat_dat->nr_channels * sizeof(struct at_dma_chan);
        atdma = kzalloc(size, GFP_KERNEL);
        if (!atdma)
                return -ENOMEM;
 
-       /* discover transaction capabilites from the platform data */
-       atdma->dma_common.cap_mask = pdata->cap_mask;
-       atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
+       /* discover transaction capabilities */
+       atdma->dma_common.cap_mask = plat_dat->cap_mask;
+       atdma->all_chan_mask = (1 << plat_dat->nr_channels) - 1;
 
        size = resource_size(io);
        if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
@@ -1268,7 +1325,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
 
        /* initialize channels related values */
        INIT_LIST_HEAD(&atdma->dma_common.channels);
-       for (i = 0; i < pdata->nr_channels; i++) {
+       for (i = 0; i < plat_dat->nr_channels; i++) {
                struct at_dma_chan      *atchan = &atdma->chan[i];
 
                atchan->chan_common.device = &atdma->dma_common;
@@ -1286,7 +1343,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
 
                tasklet_init(&atchan->tasklet, atc_tasklet,
                                (unsigned long)atchan);
-               atc_enable_irq(atchan);
+               atc_enable_chan_irq(atdma, i);
        }
 
        /* set base routines */
@@ -1313,7 +1370,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
          dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
          dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
-         pdata->nr_channels);
+         plat_dat->nr_channels);
 
        dma_async_device_register(&atdma->dma_common);
 
@@ -1353,7 +1410,7 @@ static int __exit at_dma_remove(struct platform_device *pdev)
                struct at_dma_chan      *atchan = to_at_dma_chan(chan);
 
                /* Disable interrupts */
-               atc_disable_irq(atchan);
+               atc_disable_chan_irq(atdma, chan->chan_id);
                tasklet_disable(&atchan->tasklet);
 
                tasklet_kill(&atchan->tasklet);
@@ -1495,9 +1552,11 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = {
 static struct platform_driver at_dma_driver = {
        .remove         = __exit_p(at_dma_remove),
        .shutdown       = at_dma_shutdown,
+       .id_table       = atdma_devtypes,
        .driver = {
                .name   = "at_hdmac",
                .pm     = &at_dma_dev_pm_ops,
+               .of_match_table = of_match_ptr(atmel_dma_dt_ids),
        },
 };
 
index aa4c9aebab7cedec68a42aececeb218aaea0208b..a8d3277d60b5cdd238ea77959c7b40185edfc077 100644 (file)
@@ -251,6 +251,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
 /**
  * struct at_dma - internal representation of an Atmel HDMA Controller
  * @chan_common: common dmaengine dma_device object members
+ * @atdma_devtype: identifier of DMA controller compatibility
  * @ch_regs: memory mapped register base
  * @clk: dma controller clock
  * @save_imr: interrupt mask register that is saved on suspend/resume cycle
@@ -326,28 +327,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
 }
 
 
-static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
 {
-       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
-       u32             ebci;
+       u32 ebci;
 
        /* enable interrupts on buffer transfer completion & error */
-       ebci =    AT_DMA_BTC(atchan->chan_common.chan_id)
-               | AT_DMA_ERR(atchan->chan_common.chan_id);
+       ebci =    AT_DMA_BTC(chan_id)
+               | AT_DMA_ERR(chan_id);
        if (on)
                dma_writel(atdma, EBCIER, ebci);
        else
                dma_writel(atdma, EBCIDR, ebci);
 }
 
-static inline void atc_enable_irq(struct at_dma_chan *atchan)
+static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
 {
-       atc_setup_irq(atchan, 1);
+       atc_setup_irq(atdma, chan_id, 1);
 }
 
-static inline void atc_disable_irq(struct at_dma_chan *atchan)
+static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
 {
-       atc_setup_irq(atchan, 0);
+       atc_setup_irq(atdma, chan_id, 0);
 }
 
 
index 4234f416ef115055cb425822a2c411a73dd41590..d65a718c0f9b1ae5819aef9af4c1c58200627a22 100644 (file)
@@ -39,7 +39,7 @@ struct coh901318_desc {
        struct scatterlist *sg;
        unsigned int sg_len;
        struct coh901318_lli *lli;
-       enum dma_data_direction dir;
+       enum dma_transfer_direction dir;
        unsigned long flags;
        u32 head_config;
        u32 head_ctrl;
@@ -1034,7 +1034,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 
 static struct dma_async_tx_descriptor *
 coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
-                       unsigned int sg_len, enum dma_data_direction direction,
+                       unsigned int sg_len, enum dma_transfer_direction direction,
                        unsigned long flags)
 {
        struct coh901318_chan *cohc = to_coh901318_chan(chan);
@@ -1077,7 +1077,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        ctrl_last |= cohc->runtime_ctrl;
        ctrl |= cohc->runtime_ctrl;
 
-       if (direction == DMA_TO_DEVICE) {
+       if (direction == DMA_MEM_TO_DEV) {
                u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
                        COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
 
@@ -1085,7 +1085,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                ctrl_chained |= tx_flags;
                ctrl_last |= tx_flags;
                ctrl |= tx_flags;
-       } else if (direction == DMA_FROM_DEVICE) {
+       } else if (direction == DMA_DEV_TO_MEM) {
                u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
                        COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
 
@@ -1274,11 +1274,11 @@ static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan,
        int i = 0;
 
        /* We only support mem to per or per to mem transfers */
-       if (config->direction == DMA_FROM_DEVICE) {
+       if (config->direction == DMA_DEV_TO_MEM) {
                addr = config->src_addr;
                addr_width = config->src_addr_width;
                maxburst = config->src_maxburst;
-       } else if (config->direction == DMA_TO_DEVICE) {
+       } else if (config->direction == DMA_MEM_TO_DEV) {
                addr = config->dst_addr;
                addr_width = config->dst_addr_width;
                maxburst = config->dst_maxburst;
index 9f7e0e6a7eea12e8487cef8fd1395c38cfbdc7a0..6c0e2d4c66827c7a179a55c8bc52375b932dfaa1 100644 (file)
@@ -7,11 +7,10 @@
  * Author: Per Friden <per.friden@stericsson.com>
  */
 
-#include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
-#include <linux/dmapool.h>
 #include <linux/memory.h>
 #include <linux/gfp.h>
+#include <linux/dmapool.h>
 #include <mach/coh901318.h>
 
 #include "coh901318_lli.h"
@@ -177,18 +176,18 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
                          struct coh901318_lli *lli,
                          dma_addr_t buf, unsigned int size,
                          dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom,
-                         enum dma_data_direction dir)
+                         enum dma_transfer_direction dir)
 {
        int s = size;
        dma_addr_t src;
        dma_addr_t dst;
 
 
-       if (dir == DMA_TO_DEVICE) {
+       if (dir == DMA_MEM_TO_DEV) {
                src = buf;
                dst = dev_addr;
 
-       } else if (dir == DMA_FROM_DEVICE) {
+       } else if (dir == DMA_DEV_TO_MEM) {
 
                src = dev_addr;
                dst = buf;
@@ -215,9 +214,9 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
 
                lli = coh901318_lli_next(lli);
 
-               if (dir == DMA_TO_DEVICE)
+               if (dir == DMA_MEM_TO_DEV)
                        src += block_size;
-               else if (dir == DMA_FROM_DEVICE)
+               else if (dir == DMA_DEV_TO_MEM)
                        dst += block_size;
        }
 
@@ -234,7 +233,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
                      struct scatterlist *sgl, unsigned int nents,
                      dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl,
                      u32 ctrl_last,
-                     enum dma_data_direction dir, u32 ctrl_irq_mask)
+                     enum dma_transfer_direction dir, u32 ctrl_irq_mask)
 {
        int i;
        struct scatterlist *sg;
@@ -249,9 +248,9 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
 
        spin_lock(&pool->lock);
 
-       if (dir == DMA_TO_DEVICE)
+       if (dir == DMA_MEM_TO_DEV)
                dst = dev_addr;
-       else if (dir == DMA_FROM_DEVICE)
+       else if (dir == DMA_DEV_TO_MEM)
                src = dev_addr;
        else
                goto err;
@@ -269,7 +268,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
                        ctrl_sg = ctrl ? ctrl : ctrl_last;
 
 
-               if (dir == DMA_TO_DEVICE)
+               if (dir == DMA_MEM_TO_DEV)
                        /* increment source address */
                        src = sg_phys(sg);
                else
@@ -293,7 +292,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
                        lli->src_addr = src;
                        lli->dst_addr = dst;
 
-                       if (dir == DMA_FROM_DEVICE)
+                       if (dir == DMA_DEV_TO_MEM)
                                dst += elem_size;
                        else
                                src += elem_size;
index 7a5c80990e9ef795def59abeb4e8b310e1245759..abff3714fdda73ed508d588c3b1b3fc923d08e89 100644 (file)
@@ -97,7 +97,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
                          struct coh901318_lli *lli,
                          dma_addr_t buf, unsigned int size,
                          dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_last,
-                         enum dma_data_direction dir);
+                         enum dma_transfer_direction dir);
 
 /**
  * coh901318_lli_fill_single() - Prepares the lli:s for dma scatter list transfer
@@ -119,6 +119,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
                      struct scatterlist *sg, unsigned int nents,
                      dma_addr_t dev_addr, u32 ctrl_chained,
                      u32 ctrl, u32 ctrl_last,
-                     enum dma_data_direction dir, u32 ctrl_irq_mask);
+                     enum dma_transfer_direction dir, u32 ctrl_irq_mask);
 
 #endif /* COH901318_LLI_H */
index b48967b499da0bad30529501492def4695dc1f25..a6c6051ec85811041277c64d675810f14d9da851 100644 (file)
@@ -693,12 +693,12 @@ int dma_async_device_register(struct dma_device *device)
                !device->device_prep_dma_interrupt);
        BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) &&
                !device->device_prep_dma_sg);
-       BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
-               !device->device_prep_slave_sg);
        BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) &&
                !device->device_prep_dma_cyclic);
        BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
                !device->device_control);
+       BUG_ON(dma_has_cap(DMA_INTERLEAVE, device->cap_mask) &&
+               !device->device_prep_interleaved_dma);
 
        BUG_ON(!device->device_alloc_chan_resources);
        BUG_ON(!device->device_free_chan_resources);
index 2b8661b54eaf7ec159d563b7798e6f07ec9dc34e..24225f0fdcd85f93d5feccae6d935e1563a679fb 100644 (file)
@@ -599,7 +599,7 @@ static int dmatest_add_channel(struct dma_chan *chan)
        }
        if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
                cnt = dmatest_add_threads(dtc, DMA_PQ);
-               thread_count += cnt > 0 ?: 0;
+               thread_count += cnt > 0 ? cnt : 0;
        }
 
        pr_info("dmatest: Started %u threads using %s\n",
index 9bfd6d3607180930692140b43f31db630c25bee6..9b592b02b5f49a3023cdc883322af7c451448a0a 100644 (file)
@@ -166,6 +166,38 @@ dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
        return cookie;
 }
 
+static void dwc_initialize(struct dw_dma_chan *dwc)
+{
+       struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+       struct dw_dma_slave *dws = dwc->chan.private;
+       u32 cfghi = DWC_CFGH_FIFO_MODE;
+       u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
+
+       if (dwc->initialized == true)
+               return;
+
+       if (dws) {
+               /*
+                * We need controller-specific data to set up slave
+                * transfers.
+                */
+               BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
+
+               cfghi = dws->cfg_hi;
+               cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
+       }
+
+       channel_writel(dwc, CFG_LO, cfglo);
+       channel_writel(dwc, CFG_HI, cfghi);
+
+       /* Enable interrupts */
+       channel_set_bit(dw, MASK.XFER, dwc->mask);
+       channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+       channel_set_bit(dw, MASK.ERROR, dwc->mask);
+
+       dwc->initialized = true;
+}
+
 /*----------------------------------------------------------------------*/
 
 /* Called with dwc->lock held and bh disabled */
@@ -189,6 +221,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
                return;
        }
 
+       dwc_initialize(dwc);
+
        channel_writel(dwc, LLP, first->txd.phys);
        channel_writel(dwc, CTL_LO,
                        DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
@@ -696,7 +730,7 @@ err_desc_get:
 
 static struct dma_async_tx_descriptor *
 dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
@@ -720,7 +754,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        prev = first = NULL;
 
        switch (direction) {
-       case DMA_TO_DEVICE:
+       case DMA_MEM_TO_DEV:
                ctllo = (DWC_DEFAULT_CTLLO(chan->private)
                                | DWC_CTLL_DST_WIDTH(reg_width)
                                | DWC_CTLL_DST_FIX
@@ -777,7 +811,7 @@ slave_sg_todev_fill_desc:
                                goto slave_sg_todev_fill_desc;
                }
                break;
-       case DMA_FROM_DEVICE:
+       case DMA_DEV_TO_MEM:
                ctllo = (DWC_DEFAULT_CTLLO(chan->private)
                                | DWC_CTLL_SRC_WIDTH(reg_width)
                                | DWC_CTLL_DST_INC
@@ -959,10 +993,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
        struct dw_dma           *dw = to_dw_dma(chan->device);
        struct dw_desc          *desc;
-       struct dw_dma_slave     *dws;
        int                     i;
-       u32                     cfghi;
-       u32                     cfglo;
        unsigned long           flags;
 
        dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
@@ -975,26 +1006,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
 
        dwc->completed = chan->cookie = 1;
 
-       cfghi = DWC_CFGH_FIFO_MODE;
-       cfglo = 0;
-
-       dws = chan->private;
-       if (dws) {
-               /*
-                * We need controller-specific data to set up slave
-                * transfers.
-                */
-               BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
-
-               cfghi = dws->cfg_hi;
-               cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
-       }
-
-       cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority);
-
-       channel_writel(dwc, CFG_LO, cfglo);
-       channel_writel(dwc, CFG_HI, cfghi);
-
        /*
         * NOTE: some controllers may have additional features that we
         * need to initialize here, like "scatter-gather" (which
@@ -1026,11 +1037,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
                i = ++dwc->descs_allocated;
        }
 
-       /* Enable interrupts */
-       channel_set_bit(dw, MASK.XFER, dwc->mask);
-       channel_set_bit(dw, MASK.BLOCK, dwc->mask);
-       channel_set_bit(dw, MASK.ERROR, dwc->mask);
-
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        dev_dbg(chan2dev(chan),
@@ -1058,6 +1064,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
        spin_lock_irqsave(&dwc->lock, flags);
        list_splice_init(&dwc->free_list, &list);
        dwc->descs_allocated = 0;
+       dwc->initialized = false;
 
        /* Disable interrupts */
        channel_clear_bit(dw, MASK.XFER, dwc->mask);
@@ -1165,7 +1172,7 @@ EXPORT_SYMBOL(dw_dma_cyclic_stop);
  */
 struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                dma_addr_t buf_addr, size_t buf_len, size_t period_len,
-               enum dma_data_direction direction)
+               enum dma_transfer_direction direction)
 {
        struct dw_dma_chan              *dwc = to_dw_dma_chan(chan);
        struct dw_cyclic_desc           *cdesc;
@@ -1206,7 +1213,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                goto out_err;
        if (unlikely(buf_addr & ((1 << reg_width) - 1)))
                goto out_err;
-       if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE))))
+       if (unlikely(!(direction & (DMA_MEM_TO_DEV | DMA_DEV_TO_MEM))))
                goto out_err;
 
        retval = ERR_PTR(-ENOMEM);
@@ -1228,7 +1235,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                        goto out_err_desc_get;
 
                switch (direction) {
-               case DMA_TO_DEVICE:
+               case DMA_MEM_TO_DEV:
                        desc->lli.dar = dws->tx_reg;
                        desc->lli.sar = buf_addr + (period_len * i);
                        desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
@@ -1239,7 +1246,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                                        | DWC_CTLL_FC(dws->fc)
                                        | DWC_CTLL_INT_EN);
                        break;
-               case DMA_FROM_DEVICE:
+               case DMA_DEV_TO_MEM:
                        desc->lli.dar = buf_addr + (period_len * i);
                        desc->lli.sar = dws->rx_reg;
                        desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
@@ -1335,6 +1342,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free);
 
 static void dw_dma_off(struct dw_dma *dw)
 {
+       int i;
+
        dma_writel(dw, CFG, 0);
 
        channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
@@ -1345,6 +1354,9 @@ static void dw_dma_off(struct dw_dma *dw)
 
        while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
                cpu_relax();
+
+       for (i = 0; i < dw->dma.chancnt; i++)
+               dw->chan[i].initialized = false;
 }
 
 static int __init dw_probe(struct platform_device *pdev)
@@ -1533,6 +1545,7 @@ static int dw_suspend_noirq(struct device *dev)
 
        dw_dma_off(platform_get_drvdata(pdev));
        clk_disable(dw->clk);
+
        return 0;
 }
 
index c3419518d701dbe3a0671cbc906a88c7ee3823a3..5eef6946a36713bd7413ecd29c1751291c4cc41c 100644 (file)
@@ -140,6 +140,7 @@ struct dw_dma_chan {
        u8                      mask;
        u8                      priority;
        bool                    paused;
+       bool                    initialized;
 
        spinlock_t              lock;
 
index b47e2b803fafdaedaf7c8a765858790ce869f2db..59e7a965772bfdff900aa1d82063d6f2510dd8c4 100644 (file)
@@ -246,6 +246,9 @@ static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac,
 static struct ep93xx_dma_desc *
 ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
 {
+       if (list_empty(&edmac->active))
+               return NULL;
+
        return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node);
 }
 
@@ -263,16 +266,22 @@ ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
  */
 static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
 {
+       struct ep93xx_dma_desc *desc;
+
        list_rotate_left(&edmac->active);
 
        if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
                return true;
 
+       desc = ep93xx_dma_get_active(edmac);
+       if (!desc)
+               return false;
+
        /*
         * If txd.cookie is set it means that we are back in the first
         * descriptor in the chain and hence done with it.
         */
-       return !ep93xx_dma_get_active(edmac)->txd.cookie;
+       return !desc->txd.cookie;
 }
 
 /*
@@ -327,10 +336,16 @@ static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
 
 static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
 {
-       struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+       struct ep93xx_dma_desc *desc;
        u32 bus_addr;
 
-       if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE)
+       desc = ep93xx_dma_get_active(edmac);
+       if (!desc) {
+               dev_warn(chan2dev(edmac), "M2P: empty descriptor list\n");
+               return;
+       }
+
+       if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_MEM_TO_DEV)
                bus_addr = desc->src_addr;
        else
                bus_addr = desc->dst_addr;
@@ -443,7 +458,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
                control = (5 << M2M_CONTROL_PWSC_SHIFT);
                control |= M2M_CONTROL_NO_HDSK;
 
-               if (data->direction == DMA_TO_DEVICE) {
+               if (data->direction == DMA_MEM_TO_DEV) {
                        control |= M2M_CONTROL_DAH;
                        control |= M2M_CONTROL_TM_TX;
                        control |= M2M_CONTROL_RSS_SSPTX;
@@ -459,11 +474,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
                 * This IDE part is totally untested. Values below are taken
                 * from the EP93xx Users's Guide and might not be correct.
                 */
-               control |= M2M_CONTROL_NO_HDSK;
-               control |= M2M_CONTROL_RSS_IDE;
-               control |= M2M_CONTROL_PW_16;
-
-               if (data->direction == DMA_TO_DEVICE) {
+               if (data->direction == DMA_MEM_TO_DEV) {
                        /* Worst case from the UG */
                        control = (3 << M2M_CONTROL_PWSC_SHIFT);
                        control |= M2M_CONTROL_DAH;
@@ -473,6 +484,10 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
                        control |= M2M_CONTROL_SAH;
                        control |= M2M_CONTROL_TM_RX;
                }
+
+               control |= M2M_CONTROL_NO_HDSK;
+               control |= M2M_CONTROL_RSS_IDE;
+               control |= M2M_CONTROL_PW_16;
                break;
 
        default:
@@ -491,7 +506,13 @@ static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac)
 
 static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
 {
-       struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+       struct ep93xx_dma_desc *desc;
+
+       desc = ep93xx_dma_get_active(edmac);
+       if (!desc) {
+               dev_warn(chan2dev(edmac), "M2M: empty descriptor list\n");
+               return;
+       }
 
        if (edmac->buffer == 0) {
                writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0);
@@ -669,24 +690,30 @@ static void ep93xx_dma_tasklet(unsigned long data)
 {
        struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
        struct ep93xx_dma_desc *desc, *d;
-       dma_async_tx_callback callback;
-       void *callback_param;
+       dma_async_tx_callback callback = NULL;
+       void *callback_param = NULL;
        LIST_HEAD(list);
 
        spin_lock_irq(&edmac->lock);
+       /*
+        * If dma_terminate_all() was called before we get to run, the active
+        * list has become empty. If that happens we aren't supposed to do
+        * anything more than call ep93xx_dma_advance_work().
+        */
        desc = ep93xx_dma_get_active(edmac);
-       if (desc->complete) {
-               edmac->last_completed = desc->txd.cookie;
-               list_splice_init(&edmac->active, &list);
+       if (desc) {
+               if (desc->complete) {
+                       edmac->last_completed = desc->txd.cookie;
+                       list_splice_init(&edmac->active, &list);
+               }
+               callback = desc->txd.callback;
+               callback_param = desc->txd.callback_param;
        }
        spin_unlock_irq(&edmac->lock);
 
        /* Pick up the next descriptor from the queue */
        ep93xx_dma_advance_work(edmac);
 
-       callback = desc->txd.callback;
-       callback_param = desc->txd.callback_param;
-
        /* Now we can release all the chained descriptors */
        list_for_each_entry_safe(desc, d, &list, node) {
                /*
@@ -706,13 +733,22 @@ static void ep93xx_dma_tasklet(unsigned long data)
 static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
 {
        struct ep93xx_dma_chan *edmac = dev_id;
+       struct ep93xx_dma_desc *desc;
        irqreturn_t ret = IRQ_HANDLED;
 
        spin_lock(&edmac->lock);
 
+       desc = ep93xx_dma_get_active(edmac);
+       if (!desc) {
+               dev_warn(chan2dev(edmac),
+                        "got interrupt while active list is empty\n");
+               spin_unlock(&edmac->lock);
+               return IRQ_NONE;
+       }
+
        switch (edmac->edma->hw_interrupt(edmac)) {
        case INTERRUPT_DONE:
-               ep93xx_dma_get_active(edmac)->complete = true;
+               desc->complete = true;
                tasklet_schedule(&edmac->tasklet);
                break;
 
@@ -803,8 +839,8 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
                        switch (data->port) {
                        case EP93XX_DMA_SSP:
                        case EP93XX_DMA_IDE:
-                               if (data->direction != DMA_TO_DEVICE &&
-                                   data->direction != DMA_FROM_DEVICE)
+                               if (data->direction != DMA_MEM_TO_DEV &&
+                                   data->direction != DMA_DEV_TO_MEM)
                                        return -EINVAL;
                                break;
                        default:
@@ -952,7 +988,7 @@ fail:
  */
 static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
-                        unsigned int sg_len, enum dma_data_direction dir,
+                        unsigned int sg_len, enum dma_transfer_direction dir,
                         unsigned long flags)
 {
        struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
@@ -988,7 +1024,7 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        goto fail;
                }
 
-               if (dir == DMA_TO_DEVICE) {
+               if (dir == DMA_MEM_TO_DEV) {
                        desc->src_addr = sg_dma_address(sg);
                        desc->dst_addr = edmac->runtime_addr;
                } else {
@@ -1032,7 +1068,7 @@ fail:
 static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
                           size_t buf_len, size_t period_len,
-                          enum dma_data_direction dir)
+                          enum dma_transfer_direction dir)
 {
        struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
        struct ep93xx_dma_desc *desc, *first;
@@ -1065,7 +1101,7 @@ ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
                        goto fail;
                }
 
-               if (dir == DMA_TO_DEVICE) {
+               if (dir == DMA_MEM_TO_DEV) {
                        desc->src_addr = dma_addr + offset;
                        desc->dst_addr = edmac->runtime_addr;
                } else {
@@ -1133,12 +1169,12 @@ static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac,
                return -EINVAL;
 
        switch (config->direction) {
-       case DMA_FROM_DEVICE:
+       case DMA_DEV_TO_MEM:
                width = config->src_addr_width;
                addr = config->src_addr;
                break;
 
-       case DMA_TO_DEVICE:
+       case DMA_MEM_TO_DEV:
                width = config->dst_addr_width;
                addr = config->dst_addr;
                break;
index 8a781540590cdf1e76e79c74d137a647c02642f6..b98070c33ca9d3b8aa42d1fb5085da9772957733 100644 (file)
@@ -772,7 +772,7 @@ fail:
  */
 static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
        struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
-       enum dma_data_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags)
 {
        /*
         * This operation is not supported on the Freescale DMA controller
@@ -819,7 +819,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
                        return -ENXIO;
 
                /* we set the controller burst size depending on direction */
-               if (config->direction == DMA_TO_DEVICE)
+               if (config->direction == DMA_MEM_TO_DEV)
                        size = config->dst_addr_width * config->dst_maxburst;
                else
                        size = config->src_addr_width * config->src_maxburst;
index 4be55f9bb6c19c6b6165a6de82eea9b2d977c18d..e4383ee2c9acd015b72675557ad03a06357f4eda 100644 (file)
@@ -107,7 +107,7 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                imx_dma_disable(imxdmac->imxdma_channel);
                return 0;
        case DMA_SLAVE_CONFIG:
-               if (dmaengine_cfg->direction == DMA_FROM_DEVICE) {
+               if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
                        imxdmac->per_address = dmaengine_cfg->src_addr;
                        imxdmac->watermark_level = dmaengine_cfg->src_maxburst;
                        imxdmac->word_size = dmaengine_cfg->src_addr_width;
@@ -224,7 +224,7 @@ static void imxdma_free_chan_resources(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
@@ -241,7 +241,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
                dma_length += sg->length;
        }
 
-       if (direction == DMA_FROM_DEVICE)
+       if (direction == DMA_DEV_TO_MEM)
                dmamode = DMA_MODE_READ;
        else
                dmamode = DMA_MODE_WRITE;
@@ -271,7 +271,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
 
 static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
        struct imxdma_engine *imxdma = imxdmac->imxdma;
@@ -317,7 +317,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
        imxdmac->sg_list[periods].page_link =
                ((unsigned long)imxdmac->sg_list | 0x01) & ~0x02;
 
-       if (direction == DMA_FROM_DEVICE)
+       if (direction == DMA_DEV_TO_MEM)
                dmamode = DMA_MODE_READ;
        else
                dmamode = DMA_MODE_WRITE;
index f993955a640c376342498d3336668348ecd78884..8bc5acf36ee5b2e1a633f2cd7f1f39bd5e41059b 100644 (file)
@@ -247,7 +247,7 @@ struct sdma_engine;
 struct sdma_channel {
        struct sdma_engine              *sdma;
        unsigned int                    channel;
-       enum dma_data_direction         direction;
+       enum dma_transfer_direction             direction;
        enum sdma_peripheral_type       peripheral_type;
        unsigned int                    event_id0;
        unsigned int                    event_id1;
@@ -268,6 +268,8 @@ struct sdma_channel {
        struct dma_async_tx_descriptor  desc;
        dma_cookie_t                    last_completed;
        enum dma_status                 status;
+       unsigned int                    chn_count;
+       unsigned int                    chn_real_count;
 };
 
 #define IMX_DMA_SG_LOOP                (1 << 0)
@@ -503,6 +505,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
        struct sdma_buffer_descriptor *bd;
        int i, error = 0;
 
+       sdmac->chn_real_count = 0;
        /*
         * non loop mode. Iterate over all descriptors, collect
         * errors and call callback function
@@ -512,6 +515,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
 
                 if (bd->mode.status & (BD_DONE | BD_RROR))
                        error = -EIO;
+                sdmac->chn_real_count += bd->mode.count;
        }
 
        if (error)
@@ -519,9 +523,9 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
        else
                sdmac->status = DMA_SUCCESS;
 
+       sdmac->last_completed = sdmac->desc.cookie;
        if (sdmac->desc.callback)
                sdmac->desc.callback(sdmac->desc.callback_param);
-       sdmac->last_completed = sdmac->desc.cookie;
 }
 
 static void mxc_sdma_handle_channel(struct sdma_channel *sdmac)
@@ -650,7 +654,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
        struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
        int ret;
 
-       if (sdmac->direction == DMA_FROM_DEVICE) {
+       if (sdmac->direction == DMA_DEV_TO_MEM) {
                load_address = sdmac->pc_from_device;
        } else {
                load_address = sdmac->pc_to_device;
@@ -832,17 +836,18 @@ static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
 
 static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
+       unsigned long flags;
        struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
        struct sdma_engine *sdma = sdmac->sdma;
        dma_cookie_t cookie;
 
-       spin_lock_irq(&sdmac->lock);
+       spin_lock_irqsave(&sdmac->lock, flags);
 
        cookie = sdma_assign_cookie(sdmac);
 
        sdma_enable_channel(sdma, sdmac->channel);
 
-       spin_unlock_irq(&sdmac->lock);
+       spin_unlock_irqrestore(&sdmac->lock, flags);
 
        return cookie;
 }
@@ -911,7 +916,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags)
 {
        struct sdma_channel *sdmac = to_sdma_chan(chan);
@@ -941,6 +946,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                goto err_out;
        }
 
+       sdmac->chn_count = 0;
        for_each_sg(sgl, sg, sg_len, i) {
                struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
                int param;
@@ -957,6 +963,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                }
 
                bd->mode.count = count;
+               sdmac->chn_count += count;
 
                if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
                        ret =  -EINVAL;
@@ -1008,7 +1015,7 @@ err_out:
 
 static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        struct sdma_channel *sdmac = to_sdma_chan(chan);
        struct sdma_engine *sdma = sdmac->sdma;
@@ -1093,15 +1100,18 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                sdma_disable_channel(sdmac);
                return 0;
        case DMA_SLAVE_CONFIG:
-               if (dmaengine_cfg->direction == DMA_FROM_DEVICE) {
+               if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
                        sdmac->per_address = dmaengine_cfg->src_addr;
-                       sdmac->watermark_level = dmaengine_cfg->src_maxburst;
+                       sdmac->watermark_level = dmaengine_cfg->src_maxburst *
+                                               dmaengine_cfg->src_addr_width;
                        sdmac->word_size = dmaengine_cfg->src_addr_width;
                } else {
                        sdmac->per_address = dmaengine_cfg->dst_addr;
-                       sdmac->watermark_level = dmaengine_cfg->dst_maxburst;
+                       sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
+                                               dmaengine_cfg->dst_addr_width;
                        sdmac->word_size = dmaengine_cfg->dst_addr_width;
                }
+               sdmac->direction = dmaengine_cfg->direction;
                return sdma_config_channel(sdmac);
        default:
                return -ENOSYS;
@@ -1119,7 +1129,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
 
        last_used = chan->cookie;
 
-       dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0);
+       dma_set_tx_state(txstate, sdmac->last_completed, last_used,
+                       sdmac->chn_count - sdmac->chn_real_count);
 
        return sdmac->status;
 }
index 19a0c64d45d3643a99e7b8972c8c3f3a16fc6e5f..74f70aadf9e47313cb23e3bee95781c8f24a2e02 100644 (file)
@@ -280,7 +280,8 @@ static void midc_dostart(struct intel_mid_dma_chan *midc,
  * callbacks but must be called with the lock held.
  */
 static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
-              struct intel_mid_dma_desc *desc)
+               struct intel_mid_dma_desc *desc)
+               __releases(&midc->lock) __acquires(&midc->lock)
 {
        struct dma_async_tx_descriptor  *txd = &desc->txd;
        dma_async_tx_callback callback_txd = NULL;
@@ -311,6 +312,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
                        pci_pool_free(desc->lli_pool, desc->lli,
                                                desc->lli_phys);
                        pci_pool_destroy(desc->lli_pool);
+                       desc->lli = NULL;
                }
                list_move(&desc->desc_node, &midc->free_list);
                midc->busy = false;
@@ -395,10 +397,10 @@ static int midc_lli_fill_sg(struct intel_mid_dma_chan *midc,
                                                        midc->dma->block_size);
                /*Populate SAR and DAR values*/
                sg_phy_addr = sg_phys(sg);
-               if (desc->dirn ==  DMA_TO_DEVICE) {
+               if (desc->dirn ==  DMA_MEM_TO_DEV) {
                        lli_bloc_desc->sar  = sg_phy_addr;
                        lli_bloc_desc->dar  = mids->dma_slave.dst_addr;
-               } else if (desc->dirn ==  DMA_FROM_DEVICE) {
+               } else if (desc->dirn ==  DMA_DEV_TO_MEM) {
                        lli_bloc_desc->sar  = mids->dma_slave.src_addr;
                        lli_bloc_desc->dar  = sg_phy_addr;
                }
@@ -490,7 +492,9 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
 
        ret = dma_async_is_complete(cookie, last_complete, last_used);
        if (ret != DMA_SUCCESS) {
+               spin_lock_bh(&midc->lock);
                midc_scan_descriptors(to_middma_device(chan->device), midc);
+               spin_unlock_bh(&midc->lock);
 
                last_complete = midc->completed;
                last_used = chan->cookie;
@@ -566,6 +570,7 @@ static int intel_mid_dma_device_control(struct dma_chan *chan,
                        pci_pool_free(desc->lli_pool, desc->lli,
                                                desc->lli_phys);
                        pci_pool_destroy(desc->lli_pool);
+                       desc->lli = NULL;
                }
                list_move(&desc->desc_node, &midc->free_list);
        }
@@ -632,13 +637,13 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy(
                if (midc->dma->pimr_mask) {
                        cfg_hi.cfgx.protctl = 0x0; /*default value*/
                        cfg_hi.cfgx.fifo_mode = 1;
-                       if (mids->dma_slave.direction == DMA_TO_DEVICE) {
+                       if (mids->dma_slave.direction == DMA_MEM_TO_DEV) {
                                cfg_hi.cfgx.src_per = 0;
                                if (mids->device_instance == 0)
                                        cfg_hi.cfgx.dst_per = 3;
                                if (mids->device_instance == 1)
                                        cfg_hi.cfgx.dst_per = 1;
-                       } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) {
+                       } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) {
                                if (mids->device_instance == 0)
                                        cfg_hi.cfgx.src_per = 2;
                                if (mids->device_instance == 1)
@@ -682,11 +687,11 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy(
                ctl_lo.ctlx.sinc = 0;
                ctl_lo.ctlx.dinc = 0;
        } else {
-               if (mids->dma_slave.direction == DMA_TO_DEVICE) {
+               if (mids->dma_slave.direction == DMA_MEM_TO_DEV) {
                        ctl_lo.ctlx.sinc = 0;
                        ctl_lo.ctlx.dinc = 2;
                        ctl_lo.ctlx.tt_fc = 1;
-               } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) {
+               } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) {
                        ctl_lo.ctlx.sinc = 2;
                        ctl_lo.ctlx.dinc = 0;
                        ctl_lo.ctlx.tt_fc = 2;
@@ -732,7 +737,7 @@ err_desc_get:
  */
 static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg(
                        struct dma_chan *chan, struct scatterlist *sgl,
-                       unsigned int sg_len, enum dma_data_direction direction,
+                       unsigned int sg_len, enum dma_transfer_direction direction,
                        unsigned long flags)
 {
        struct intel_mid_dma_chan *midc = NULL;
@@ -868,7 +873,7 @@ static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan)
        pm_runtime_get_sync(&mid->pdev->dev);
 
        if (mid->state == SUSPENDED) {
-               if (dma_resume(mid->pdev)) {
+               if (dma_resume(&mid->pdev->dev)) {
                        pr_err("ERR_MDMA: resume failed");
                        return -EFAULT;
                }
@@ -1099,7 +1104,8 @@ static int mid_setup_dma(struct pci_dev *pdev)
                                        LNW_PERIPHRAL_MASK_SIZE);
                if (dma->mask_reg == NULL) {
                        pr_err("ERR_MDMA:Can't map periphral intr space !!\n");
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto err_ioremap;
                }
        } else
                dma->mask_reg = NULL;
@@ -1196,6 +1202,9 @@ static int mid_setup_dma(struct pci_dev *pdev)
 err_engine:
        free_irq(pdev->irq, dma);
 err_irq:
+       if (dma->mask_reg)
+               iounmap(dma->mask_reg);
+err_ioremap:
        pci_pool_destroy(dma->dma_pool);
 err_dma_pool:
        pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
@@ -1337,8 +1346,9 @@ static void __devexit intel_mid_dma_remove(struct pci_dev *pdev)
 *
 * This function is called by OS when a power event occurs
 */
-int dma_suspend(struct pci_dev *pci, pm_message_t state)
+static int dma_suspend(struct device *dev)
 {
+       struct pci_dev *pci = to_pci_dev(dev);
        int i;
        struct middma_device *device = pci_get_drvdata(pci);
        pr_debug("MDMA: dma_suspend called\n");
@@ -1362,8 +1372,9 @@ int dma_suspend(struct pci_dev *pci, pm_message_t state)
 *
 * This function is called by OS when a power event occurs
 */
-int dma_resume(struct pci_dev *pci)
+int dma_resume(struct device *dev)
 {
+       struct pci_dev *pci = to_pci_dev(dev);
        int ret;
        struct middma_device *device = pci_get_drvdata(pci);
 
@@ -1429,6 +1440,8 @@ static const struct dev_pm_ops intel_mid_dma_pm = {
        .runtime_suspend = dma_runtime_suspend,
        .runtime_resume = dma_runtime_resume,
        .runtime_idle = dma_runtime_idle,
+       .suspend = dma_suspend,
+       .resume = dma_resume,
 };
 
 static struct pci_driver intel_mid_dma_pci_driver = {
@@ -1437,8 +1450,6 @@ static struct pci_driver intel_mid_dma_pci_driver = {
        .probe          =       intel_mid_dma_probe,
        .remove         =       __devexit_p(intel_mid_dma_remove),
 #ifdef CONFIG_PM
-       .suspend = dma_suspend,
-       .resume = dma_resume,
        .driver = {
                .pm = &intel_mid_dma_pm,
        },
index aea5ee88ce035a1d432eb836ef6b4b938f163ab4..c83d35b97bd8e38a91330854c3d8b10acbe4cedf 100644 (file)
@@ -262,7 +262,7 @@ struct intel_mid_dma_desc {
        unsigned int                    lli_length;
        unsigned int                    current_lli;
        dma_addr_t                      next;
-       enum dma_data_direction         dirn;
+       enum dma_transfer_direction             dirn;
        enum dma_status                 status;
        enum dma_slave_buswidth         width; /*width of DMA txn*/
        enum intel_mid_dma_mode         cfg_mode; /*mode configuration*/
@@ -296,6 +296,6 @@ static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave
 }
 
 
-int dma_resume(struct pci_dev *pci);
+int dma_resume(struct device *dev);
 
 #endif /*__INTEL_MID_DMAC_REGS_H__*/
index e03f811a83dd980e5aad9e2b25b0acdc291769f5..04be90b645b839e929512032a234089cfe2d082c 100644 (file)
@@ -1735,8 +1735,6 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
        spin_unlock_bh(&iop_chan->lock);
 }
 
-MODULE_ALIAS("platform:iop-adma");
-
 static struct platform_driver iop_adma_driver = {
        .probe          = iop_adma_probe,
        .remove         = __devexit_p(iop_adma_remove),
@@ -1746,19 +1744,9 @@ static struct platform_driver iop_adma_driver = {
        },
 };
 
-static int __init iop_adma_init (void)
-{
-       return platform_driver_register(&iop_adma_driver);
-}
-
-static void __exit iop_adma_exit (void)
-{
-       platform_driver_unregister(&iop_adma_driver);
-       return;
-}
-module_exit(iop_adma_exit);
-module_init(iop_adma_init);
+module_platform_driver(iop_adma_driver);
 
 MODULE_AUTHOR("Intel Corporation");
 MODULE_DESCRIPTION("IOP ADMA Engine Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:iop-adma");
index 0e5ef33f90a17ad75bebaa889a7ae7a46d75248c..6212b16e8cf21ea32ae05732ae1f3b1147b134b8 100644 (file)
@@ -312,7 +312,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params,
        case IPU_PIX_FMT_RGB565:
                params->ip.bpp  = 2;
                params->ip.pfs  = 4;
-               params->ip.npb  = 7;
+               params->ip.npb  = 15;
                params->ip.sat  = 2;            /* SAT = 32-bit access */
                params->ip.ofs0 = 0;            /* Red bit offset */
                params->ip.ofs1 = 5;            /* Green bit offset */
@@ -422,12 +422,6 @@ static void ipu_ch_param_set_size(union chan_param_mem *params,
        params->pp.nsb = 1;
 }
 
-static void ipu_ch_param_set_burst_size(union chan_param_mem *params,
-                                       uint16_t burst_pixels)
-{
-       params->pp.npb = burst_pixels - 1;
-}
-
 static void ipu_ch_param_set_buffer(union chan_param_mem *params,
                                    dma_addr_t buf0, dma_addr_t buf1)
 {
@@ -690,23 +684,6 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan,
        ipu_ch_param_set_size(&params, pixel_fmt, width, height, stride_bytes);
        ipu_ch_param_set_buffer(&params, phyaddr_0, phyaddr_1);
        ipu_ch_param_set_rotation(&params, rot_mode);
-       /* Some channels (rotation) have restriction on burst length */
-       switch (channel) {
-       case IDMAC_IC_7:        /* Hangs with burst 8, 16, other values
-                                  invalid - Table 44-30 */
-/*
-               ipu_ch_param_set_burst_size(&params, 8);
- */
-               break;
-       case IDMAC_SDC_0:
-       case IDMAC_SDC_1:
-               /* In original code only IPU_PIX_FMT_RGB565 was setting burst */
-               ipu_ch_param_set_burst_size(&params, 16);
-               break;
-       case IDMAC_IC_0:
-       default:
-               break;
-       }
 
        spin_lock_irqsave(&ipu->lock, flags);
 
@@ -1364,7 +1341,7 @@ static void ipu_gc_tasklet(unsigned long arg)
 /* Allocate and initialise a transfer descriptor. */
 static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan,
                struct scatterlist *sgl, unsigned int sg_len,
-               enum dma_data_direction direction, unsigned long tx_flags)
+               enum dma_transfer_direction direction, unsigned long tx_flags)
 {
        struct idmac_channel *ichan = to_idmac_chan(chan);
        struct idmac_tx_desc *desc = NULL;
@@ -1376,7 +1353,7 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan
            chan->chan_id != IDMAC_IC_7)
                return NULL;
 
-       if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) {
+       if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
                dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction);
                return NULL;
        }
index 8ba4edc6185e904ea65b98537a1c09a2b38549bb..4d6d4cf669496ff0afc65d5dee450452b143a2c6 100644 (file)
@@ -835,17 +835,7 @@ static struct platform_driver mpc_dma_driver = {
        },
 };
 
-static int __init mpc_dma_init(void)
-{
-       return platform_driver_register(&mpc_dma_driver);
-}
-module_init(mpc_dma_init);
-
-static void __exit mpc_dma_exit(void)
-{
-       platform_driver_unregister(&mpc_dma_driver);
-}
-module_exit(mpc_dma_exit);
+module_platform_driver(mpc_dma_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Piotr Ziecik <kosmo@semihalf.com>");
index fc903c0ed234eae754d06911b94f73f463a3b7eb..b06cd4ca626fb4fd93d5ab3b7fedddbfd6ea6c25 100644 (file)
@@ -44,7 +44,6 @@
 #define HW_APBHX_CTRL0                         0x000
 #define BM_APBH_CTRL0_APB_BURST8_EN            (1 << 29)
 #define BM_APBH_CTRL0_APB_BURST_EN             (1 << 28)
-#define BP_APBH_CTRL0_CLKGATE_CHANNEL          8
 #define BP_APBH_CTRL0_RESET_CHANNEL            16
 #define HW_APBHX_CTRL1                         0x010
 #define HW_APBHX_CTRL2                         0x020
@@ -111,6 +110,7 @@ struct mxs_dma_chan {
        int                             chan_irq;
        struct mxs_dma_ccw              *ccw;
        dma_addr_t                      ccw_phys;
+       int                             desc_count;
        dma_cookie_t                    last_completed;
        enum dma_status                 status;
        unsigned int                    flags;
@@ -130,23 +130,6 @@ struct mxs_dma_engine {
        struct mxs_dma_chan             mxs_chans[MXS_DMA_CHANNELS];
 };
 
-static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
-{
-       struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
-       int chan_id = mxs_chan->chan.chan_id;
-       int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
-
-       /* enable apbh channel clock */
-       if (dma_is_apbh()) {
-               if (apbh_is_old())
-                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-                               mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
-               else
-                       writel(1 << chan_id,
-                               mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
-       }
-}
-
 static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
 {
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -165,9 +148,6 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
        int chan_id = mxs_chan->chan.chan_id;
 
-       /* clkgate needs to be enabled before writing other registers */
-       mxs_dma_clkgate(mxs_chan, 1);
-
        /* set cmd_addr up */
        writel(mxs_chan->ccw_phys,
                mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
@@ -178,9 +158,6 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
 
 static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
 {
-       /* disable apbh channel clock */
-       mxs_dma_clkgate(mxs_chan, 0);
-
        mxs_chan->status = DMA_SUCCESS;
 }
 
@@ -268,7 +245,7 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
        /*
         * When both completion and error of termination bits set at the
         * same time, we do not take it as an error.  IOW, it only becomes
-        * an error we need to handler here in case of ether it's (1) an bus
+        * an error we need to handle here in case of either it's (1) a bus
         * error or (2) a termination error with no completion.
         */
        stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */
@@ -338,10 +315,7 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
        if (ret)
                goto err_clk;
 
-       /* clkgate needs to be enabled for reset to finish */
-       mxs_dma_clkgate(mxs_chan, 1);
        mxs_dma_reset_chan(mxs_chan);
-       mxs_dma_clkgate(mxs_chan, 0);
 
        dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
        mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
@@ -377,7 +351,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long append)
 {
        struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
@@ -386,7 +360,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
        struct scatterlist *sg;
        int i, j;
        u32 *pio;
-       static int idx;
+       int idx = append ? mxs_chan->desc_count : 0;
 
        if (mxs_chan->status == DMA_IN_PROGRESS && !append)
                return NULL;
@@ -417,7 +391,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                idx = 0;
        }
 
-       if (direction == DMA_NONE) {
+       if (direction == DMA_TRANS_NONE) {
                ccw = &mxs_chan->ccw[idx++];
                pio = (u32 *) sgl;
 
@@ -450,7 +424,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                        ccw->bits |= CCW_CHAIN;
                        ccw->bits |= CCW_HALT_ON_TERM;
                        ccw->bits |= CCW_TERM_FLUSH;
-                       ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+                       ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ?
                                        MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ,
                                        COMMAND);
 
@@ -462,6 +436,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                        }
                }
        }
+       mxs_chan->desc_count = idx;
 
        return &mxs_chan->desc;
 
@@ -472,7 +447,7 @@ err_out:
 
 static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -515,7 +490,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
                ccw->bits |= CCW_IRQ;
                ccw->bits |= CCW_HALT_ON_TERM;
                ccw->bits |= CCW_TERM_FLUSH;
-               ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+               ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ?
                                MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND);
 
                dma_addr += period_len;
@@ -523,6 +498,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
 
                i++;
        }
+       mxs_chan->desc_count = i;
 
        return &mxs_chan->desc;
 
@@ -539,8 +515,8 @@ static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
        switch (cmd) {
        case DMA_TERMINATE_ALL:
-               mxs_dma_disable_chan(mxs_chan);
                mxs_dma_reset_chan(mxs_chan);
+               mxs_dma_disable_chan(mxs_chan);
                break;
        case DMA_PAUSE:
                mxs_dma_pause_chan(mxs_chan);
@@ -580,7 +556,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
 
        ret = clk_prepare_enable(mxs_dma->clk);
        if (ret)
-               goto err_out;
+               return ret;
 
        ret = mxs_reset_block(mxs_dma->base);
        if (ret)
@@ -604,11 +580,8 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
        writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS,
                mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR);
 
-       clk_disable_unprepare(mxs_dma->clk);
-
-       return 0;
-
 err_out:
+       clk_disable_unprepare(mxs_dma->clk);
        return ret;
 }
 
index a6d0e3dbed0748f1d666f5972b4109dfb043a3e2..823f58179f9d46a8a169dbbaf7551b1d91ec5f28 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Topcliff PCH DMA controller driver
  * Copyright (c) 2010 Intel Corporation
- * Copyright (C) 2011 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 version 2 as
@@ -99,7 +99,7 @@ struct pch_dma_desc {
 struct pch_dma_chan {
        struct dma_chan         chan;
        void __iomem *membase;
-       enum dma_data_direction dir;
+       enum dma_transfer_direction dir;
        struct tasklet_struct   tasklet;
        unsigned long           err_status;
 
@@ -224,7 +224,7 @@ static void pdc_set_dir(struct dma_chan *chan)
                mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
                                       (DMA_CTL0_BITS_PER_CH * chan->chan_id));
                val &= mask_mode;
-               if (pd_chan->dir == DMA_TO_DEVICE)
+               if (pd_chan->dir == DMA_MEM_TO_DEV)
                        val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
                                       DMA_CTL0_DIR_SHIFT_BITS);
                else
@@ -242,7 +242,7 @@ static void pdc_set_dir(struct dma_chan *chan)
                mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
                                                 (DMA_CTL0_BITS_PER_CH * ch));
                val &= mask_mode;
-               if (pd_chan->dir == DMA_TO_DEVICE)
+               if (pd_chan->dir == DMA_MEM_TO_DEV)
                        val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch +
                                       DMA_CTL0_DIR_SHIFT_BITS);
                else
@@ -607,7 +607,7 @@ static void pd_issue_pending(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
                        struct scatterlist *sgl, unsigned int sg_len,
-                       enum dma_data_direction direction, unsigned long flags)
+                       enum dma_transfer_direction direction, unsigned long flags)
 {
        struct pch_dma_chan *pd_chan = to_pd_chan(chan);
        struct pch_dma_slave *pd_slave = chan->private;
@@ -623,9 +623,9 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
                return NULL;
        }
 
-       if (direction == DMA_FROM_DEVICE)
+       if (direction == DMA_DEV_TO_MEM)
                reg = pd_slave->rx_reg;
-       else if (direction == DMA_TO_DEVICE)
+       else if (direction == DMA_MEM_TO_DEV)
                reg = pd_slave->tx_reg;
        else
                return NULL;
@@ -1018,6 +1018,8 @@ static void __devexit pch_dma_remove(struct pci_dev *pdev)
 #define PCI_DEVICE_ID_ML7223_DMA2_4CH  0x800E
 #define PCI_DEVICE_ID_ML7223_DMA3_4CH  0x8017
 #define PCI_DEVICE_ID_ML7223_DMA4_4CH  0x803B
+#define PCI_DEVICE_ID_ML7831_DMA1_8CH  0x8810
+#define PCI_DEVICE_ID_ML7831_DMA2_4CH  0x8815
 
 DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 },
@@ -1030,6 +1032,8 @@ DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA2_4CH), 4}, /* Video SPI */
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA3_4CH), 4}, /* Security */
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA4_4CH), 4}, /* FPGA */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA1_8CH), 8}, /* UART */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA2_4CH), 4}, /* SPI */
        { 0, },
 };
 
@@ -1057,7 +1061,7 @@ static void __exit pch_dma_exit(void)
 module_init(pch_dma_init);
 module_exit(pch_dma_exit);
 
-MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH "
+MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semicon ML7213/ML7223/ML7831 IOH "
                   "DMA controller driver");
 MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
 MODULE_LICENSE("GPL v2");
index 09adcfcd953e6841e840fb9caa663212c20c03f7..b8ec03ee8e22e495e633ff95bf9faf0d02756dac 100644 (file)
@@ -350,14 +350,14 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
        case DMA_SLAVE_CONFIG:
                slave_config = (struct dma_slave_config *)arg;
 
-               if (slave_config->direction == DMA_TO_DEVICE) {
+               if (slave_config->direction == DMA_MEM_TO_DEV) {
                        if (slave_config->dst_addr)
                                pch->fifo_addr = slave_config->dst_addr;
                        if (slave_config->dst_addr_width)
                                pch->burst_sz = __ffs(slave_config->dst_addr_width);
                        if (slave_config->dst_maxburst)
                                pch->burst_len = slave_config->dst_maxburst;
-               } else if (slave_config->direction == DMA_FROM_DEVICE) {
+               } else if (slave_config->direction == DMA_DEV_TO_MEM) {
                        if (slave_config->src_addr)
                                pch->fifo_addr = slave_config->src_addr;
                        if (slave_config->src_addr_width)
@@ -621,7 +621,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 
 static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
-               size_t period_len, enum dma_data_direction direction)
+               size_t period_len, enum dma_transfer_direction direction)
 {
        struct dma_pl330_desc *desc;
        struct dma_pl330_chan *pch = to_pchan(chan);
@@ -636,14 +636,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
        }
 
        switch (direction) {
-       case DMA_TO_DEVICE:
+       case DMA_MEM_TO_DEV:
                desc->rqcfg.src_inc = 1;
                desc->rqcfg.dst_inc = 0;
                desc->req.rqtype = MEMTODEV;
                src = dma_addr;
                dst = pch->fifo_addr;
                break;
-       case DMA_FROM_DEVICE:
+       case DMA_DEV_TO_MEM:
                desc->rqcfg.src_inc = 0;
                desc->rqcfg.dst_inc = 1;
                desc->req.rqtype = DEVTOMEM;
@@ -710,7 +710,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 
 static struct dma_async_tx_descriptor *
 pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flg)
 {
        struct dma_pl330_desc *first, *desc = NULL;
@@ -759,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                else
                        list_add_tail(&desc->node, &first->node);
 
-               if (direction == DMA_TO_DEVICE) {
+               if (direction == DMA_MEM_TO_DEV) {
                        desc->rqcfg.src_inc = 1;
                        desc->rqcfg.dst_inc = 0;
                        desc->req.rqtype = MEMTODEV;
@@ -834,17 +834,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
        amba_set_drvdata(adev, pdmac);
 
-#ifdef CONFIG_PM_RUNTIME
-       /* to use the runtime PM helper functions */
-       pm_runtime_enable(&adev->dev);
-
-       /* enable the power domain */
-       if (pm_runtime_get_sync(&adev->dev)) {
-               dev_err(&adev->dev, "failed to get runtime pm\n");
-               ret = -ENODEV;
-               goto probe_err1;
-       }
-#else
+#ifndef CONFIG_PM_RUNTIME
        /* enable dma clk */
        clk_enable(pdmac->clk);
 #endif
@@ -977,10 +967,7 @@ static int __devexit pl330_remove(struct amba_device *adev)
        res = &adev->res;
        release_mem_region(res->start, resource_size(res));
 
-#ifdef CONFIG_PM_RUNTIME
-       pm_runtime_put(&adev->dev);
-       pm_runtime_disable(&adev->dev);
-#else
+#ifndef CONFIG_PM_RUNTIME
        clk_disable(pdmac->clk);
 #endif
 
index 81809c2b46abef271cb2ac90408914990d0376a7..812fd76e9c18e4b2b210f20125324560a873ddeb 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
 #include <linux/delay.h>
-#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/sh_dma.h>
@@ -57,6 +56,15 @@ static LIST_HEAD(sh_dmae_devices);
 static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
 
 static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+
+static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+       struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+       __raw_writel(data, shdev->chan_reg +
+                    shdev->pdata->channel[sh_dc->id].chclr_offset);
+}
 
 static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
 {
@@ -129,6 +137,15 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
 
        dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME);
 
+       if (shdev->pdata->chclr_present) {
+               int i;
+               for (i = 0; i < shdev->pdata->channel_num; i++) {
+                       struct sh_dmae_chan *sh_chan = shdev->chan[i];
+                       if (sh_chan)
+                               chclr_write(sh_chan, 0);
+               }
+       }
+
        dmaor_write(shdev, dmaor | shdev->pdata->dmaor_init);
 
        dmaor = dmaor_read(shdev);
@@ -139,6 +156,10 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
                dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n");
                return -EIO;
        }
+       if (shdev->pdata->dmaor_init & ~dmaor)
+               dev_warn(shdev->common.dev,
+                        "DMAOR=0x%x hasn't latched the initial value 0x%x.\n",
+                        dmaor, shdev->pdata->dmaor_init);
        return 0;
 }
 
@@ -259,8 +280,6 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
        return 0;
 }
 
-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
-
 static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
@@ -340,6 +359,8 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
                                sh_chan_xfer_ld_queue(sh_chan);
                        sh_chan->pm_state = DMAE_PM_ESTABLISHED;
                }
+       } else {
+               sh_chan->pm_state = DMAE_PM_PENDING;
        }
 
        spin_unlock_irq(&sh_chan->desc_lock);
@@ -479,19 +500,19 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
  * @sh_chan:   DMA channel
  * @flags:     DMA transfer flags
  * @dest:      destination DMA address, incremented when direction equals
- *             DMA_FROM_DEVICE or DMA_BIDIRECTIONAL
+ *             DMA_DEV_TO_MEM
  * @src:       source DMA address, incremented when direction equals
- *             DMA_TO_DEVICE or DMA_BIDIRECTIONAL
+ *             DMA_MEM_TO_DEV
  * @len:       DMA transfer length
  * @first:     if NULL, set to the current descriptor and cookie set to -EBUSY
  * @direction: needed for slave DMA to decide which address to keep constant,
- *             equals DMA_BIDIRECTIONAL for MEMCPY
+ *             equals DMA_MEM_TO_MEM for MEMCPY
  * Returns 0 or an error
  * Locks: called with desc_lock held
  */
 static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
        unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
-       struct sh_desc **first, enum dma_data_direction direction)
+       struct sh_desc **first, enum dma_transfer_direction direction)
 {
        struct sh_desc *new;
        size_t copy_size;
@@ -531,9 +552,9 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
        new->direction = direction;
 
        *len -= copy_size;
-       if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE)
+       if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
                *src += copy_size;
-       if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE)
+       if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM)
                *dest += copy_size;
 
        return new;
@@ -546,12 +567,12 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
  * converted to scatter-gather to guarantee consistent locking and a correct
  * list manipulation. For slave DMA direction carries the usual meaning, and,
  * logically, the SG list is RAM and the addr variable contains slave address,
- * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL
+ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM
  * and the SG list contains only one element and points at the source buffer.
  */
 static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
        struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
-       enum dma_data_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags)
 {
        struct scatterlist *sg;
        struct sh_desc *first = NULL, *new = NULL /* compiler... */;
@@ -592,7 +613,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c
                        dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
                                i, sg, len, (unsigned long long)sg_addr);
 
-                       if (direction == DMA_FROM_DEVICE)
+                       if (direction == DMA_DEV_TO_MEM)
                                new = sh_dmae_add_desc(sh_chan, flags,
                                                &sg_addr, addr, &len, &first,
                                                direction);
@@ -646,13 +667,13 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
        sg_dma_address(&sg) = dma_src;
        sg_dma_len(&sg) = len;
 
-       return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL,
+       return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM,
                               flags);
 }
 
 static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
        struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
-       enum dma_data_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags)
 {
        struct sh_dmae_slave *param;
        struct sh_dmae_chan *sh_chan;
@@ -996,7 +1017,7 @@ static void dmae_do_tasklet(unsigned long data)
        spin_lock_irq(&sh_chan->desc_lock);
        list_for_each_entry(desc, &sh_chan->ld_queue, node) {
                if (desc->mark == DESC_SUBMITTED &&
-                   ((desc->direction == DMA_FROM_DEVICE &&
+                   ((desc->direction == DMA_DEV_TO_MEM &&
                      (desc->hw.dar + desc->hw.tcr) == dar_buf) ||
                     (desc->hw.sar + desc->hw.tcr) == sar_buf)) {
                        dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
@@ -1225,6 +1246,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, shdev);
 
+       shdev->common.dev = &pdev->dev;
+
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
 
@@ -1239,7 +1262,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&shdev->common.channels);
 
-       dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+       if (!pdata->slave_only)
+               dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
        if (pdata->slave && pdata->slave_num)
                dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
 
@@ -1254,7 +1278,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
        shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
        shdev->common.device_control = sh_dmae_control;
 
-       shdev->common.dev = &pdev->dev;
        /* Default transfer size of 32 bytes requires 32-byte alignment */
        shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
 
@@ -1435,22 +1458,17 @@ static int sh_dmae_runtime_resume(struct device *dev)
 #ifdef CONFIG_PM
 static int sh_dmae_suspend(struct device *dev)
 {
-       struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-       int i;
-
-       for (i = 0; i < shdev->pdata->channel_num; i++) {
-               struct sh_dmae_chan *sh_chan = shdev->chan[i];
-               if (sh_chan->descs_allocated)
-                       sh_chan->pm_error = pm_runtime_put_sync(dev);
-       }
-
        return 0;
 }
 
 static int sh_dmae_resume(struct device *dev)
 {
        struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-       int i;
+       int i, ret;
+
+       ret = sh_dmae_rst(shdev);
+       if (ret < 0)
+               dev_err(dev, "Failed to reset!\n");
 
        for (i = 0; i < shdev->pdata->channel_num; i++) {
                struct sh_dmae_chan *sh_chan = shdev->chan[i];
@@ -1459,9 +1477,6 @@ static int sh_dmae_resume(struct device *dev)
                if (!sh_chan->descs_allocated)
                        continue;
 
-               if (!sh_chan->pm_error)
-                       pm_runtime_get_sync(dev);
-
                if (param) {
                        const struct sh_dmae_slave_config *cfg = param->config;
                        dmae_set_dmars(sh_chan, cfg->mid_rid);
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
new file mode 100644 (file)
index 0000000..2333810
--- /dev/null
@@ -0,0 +1,707 @@
+/*
+ * DMA controller driver for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/sirfsoc_dma.h>
+
+#define SIRFSOC_DMA_DESCRIPTORS                 16
+#define SIRFSOC_DMA_CHANNELS                    16
+
+#define SIRFSOC_DMA_CH_ADDR                     0x00
+#define SIRFSOC_DMA_CH_XLEN                     0x04
+#define SIRFSOC_DMA_CH_YLEN                     0x08
+#define SIRFSOC_DMA_CH_CTRL                     0x0C
+
+#define SIRFSOC_DMA_WIDTH_0                     0x100
+#define SIRFSOC_DMA_CH_VALID                    0x140
+#define SIRFSOC_DMA_CH_INT                      0x144
+#define SIRFSOC_DMA_INT_EN                      0x148
+#define SIRFSOC_DMA_CH_LOOP_CTRL                0x150
+
+#define SIRFSOC_DMA_MODE_CTRL_BIT               4
+#define SIRFSOC_DMA_DIR_CTRL_BIT                5
+
+/* xlen and dma_width register is in 4 bytes boundary */
+#define SIRFSOC_DMA_WORD_LEN                   4
+
+struct sirfsoc_dma_desc {
+       struct dma_async_tx_descriptor  desc;
+       struct list_head                node;
+
+       /* SiRFprimaII 2D-DMA parameters */
+
+       int             xlen;           /* DMA xlen */
+       int             ylen;           /* DMA ylen */
+       int             width;          /* DMA width */
+       int             dir;
+       bool            cyclic;         /* is loop DMA? */
+       u32             addr;           /* DMA buffer address */
+};
+
+struct sirfsoc_dma_chan {
+       struct dma_chan                 chan;
+       struct list_head                free;
+       struct list_head                prepared;
+       struct list_head                queued;
+       struct list_head                active;
+       struct list_head                completed;
+       dma_cookie_t                    completed_cookie;
+       unsigned long                   happened_cyclic;
+       unsigned long                   completed_cyclic;
+
+       /* Lock for this structure */
+       spinlock_t                      lock;
+
+       int                             mode;
+};
+
+struct sirfsoc_dma {
+       struct dma_device               dma;
+       struct tasklet_struct           tasklet;
+       struct sirfsoc_dma_chan         channels[SIRFSOC_DMA_CHANNELS];
+       void __iomem                    *base;
+       int                             irq;
+};
+
+#define DRV_NAME       "sirfsoc_dma"
+
+/* Convert struct dma_chan to struct sirfsoc_dma_chan */
+static inline
+struct sirfsoc_dma_chan *dma_chan_to_sirfsoc_dma_chan(struct dma_chan *c)
+{
+       return container_of(c, struct sirfsoc_dma_chan, chan);
+}
+
+/* Convert struct dma_chan to struct sirfsoc_dma */
+static inline struct sirfsoc_dma *dma_chan_to_sirfsoc_dma(struct dma_chan *c)
+{
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(c);
+       return container_of(schan, struct sirfsoc_dma, channels[c->chan_id]);
+}
+
+/* Execute all queued DMA descriptors */
+static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
+{
+       struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
+       int cid = schan->chan.chan_id;
+       struct sirfsoc_dma_desc *sdesc = NULL;
+
+       /*
+        * lock has been held by functions calling this, so we don't hold
+        * lock again
+        */
+
+       sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
+               node);
+       /* Move the first queued descriptor to active list */
+       list_move_tail(&schan->queued, &schan->active);
+
+       /* Start the DMA transfer */
+       writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
+               cid * 4);
+       writel_relaxed(cid | (schan->mode << SIRFSOC_DMA_MODE_CTRL_BIT) |
+               (sdesc->dir << SIRFSOC_DMA_DIR_CTRL_BIT),
+               sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_CTRL);
+       writel_relaxed(sdesc->xlen, sdma->base + cid * 0x10 +
+               SIRFSOC_DMA_CH_XLEN);
+       writel_relaxed(sdesc->ylen, sdma->base + cid * 0x10 +
+               SIRFSOC_DMA_CH_YLEN);
+       writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) |
+               (1 << cid), sdma->base + SIRFSOC_DMA_INT_EN);
+
+       /*
+        * writel has an implict memory write barrier to make sure data is
+        * flushed into memory before starting DMA
+        */
+       writel(sdesc->addr >> 2, sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_ADDR);
+
+       if (sdesc->cyclic) {
+               writel((1 << cid) | 1 << (cid + 16) |
+                       readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL),
+                       sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
+               schan->happened_cyclic = schan->completed_cyclic = 0;
+       }
+}
+
+/* Interrupt handler */
+static irqreturn_t sirfsoc_dma_irq(int irq, void *data)
+{
+       struct sirfsoc_dma *sdma = data;
+       struct sirfsoc_dma_chan *schan;
+       struct sirfsoc_dma_desc *sdesc = NULL;
+       u32 is;
+       int ch;
+
+       is = readl(sdma->base + SIRFSOC_DMA_CH_INT);
+       while ((ch = fls(is) - 1) >= 0) {
+               is &= ~(1 << ch);
+               writel_relaxed(1 << ch, sdma->base + SIRFSOC_DMA_CH_INT);
+               schan = &sdma->channels[ch];
+
+               spin_lock(&schan->lock);
+
+               sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc,
+                       node);
+               if (!sdesc->cyclic) {
+                       /* Execute queued descriptors */
+                       list_splice_tail_init(&schan->active, &schan->completed);
+                       if (!list_empty(&schan->queued))
+                               sirfsoc_dma_execute(schan);
+               } else
+                       schan->happened_cyclic++;
+
+               spin_unlock(&schan->lock);
+       }
+
+       /* Schedule tasklet */
+       tasklet_schedule(&sdma->tasklet);
+
+       return IRQ_HANDLED;
+}
+
+/* process completed descriptors */
+static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma)
+{
+       dma_cookie_t last_cookie = 0;
+       struct sirfsoc_dma_chan *schan;
+       struct sirfsoc_dma_desc *sdesc;
+       struct dma_async_tx_descriptor *desc;
+       unsigned long flags;
+       unsigned long happened_cyclic;
+       LIST_HEAD(list);
+       int i;
+
+       for (i = 0; i < sdma->dma.chancnt; i++) {
+               schan = &sdma->channels[i];
+
+               /* Get all completed descriptors */
+               spin_lock_irqsave(&schan->lock, flags);
+               if (!list_empty(&schan->completed)) {
+                       list_splice_tail_init(&schan->completed, &list);
+                       spin_unlock_irqrestore(&schan->lock, flags);
+
+                       /* Execute callbacks and run dependencies */
+                       list_for_each_entry(sdesc, &list, node) {
+                               desc = &sdesc->desc;
+
+                               if (desc->callback)
+                                       desc->callback(desc->callback_param);
+
+                               last_cookie = desc->cookie;
+                               dma_run_dependencies(desc);
+                       }
+
+                       /* Free descriptors */
+                       spin_lock_irqsave(&schan->lock, flags);
+                       list_splice_tail_init(&list, &schan->free);
+                       schan->completed_cookie = last_cookie;
+                       spin_unlock_irqrestore(&schan->lock, flags);
+               } else {
+                       /* for cyclic channel, desc is always in active list */
+                       sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc,
+                               node);
+
+                       if (!sdesc || (sdesc && !sdesc->cyclic)) {
+                               /* without active cyclic DMA */
+                               spin_unlock_irqrestore(&schan->lock, flags);
+                               continue;
+                       }
+
+                       /* cyclic DMA */
+                       happened_cyclic = schan->happened_cyclic;
+                       spin_unlock_irqrestore(&schan->lock, flags);
+
+                       desc = &sdesc->desc;
+                       while (happened_cyclic != schan->completed_cyclic) {
+                               if (desc->callback)
+                                       desc->callback(desc->callback_param);
+                               schan->completed_cyclic++;
+                       }
+               }
+       }
+}
+
+/* DMA Tasklet */
+static void sirfsoc_dma_tasklet(unsigned long data)
+{
+       struct sirfsoc_dma *sdma = (void *)data;
+
+       sirfsoc_dma_process_completed(sdma);
+}
+
+/* Submit descriptor to hardware */
+static dma_cookie_t sirfsoc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
+{
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(txd->chan);
+       struct sirfsoc_dma_desc *sdesc;
+       unsigned long flags;
+       dma_cookie_t cookie;
+
+       sdesc = container_of(txd, struct sirfsoc_dma_desc, desc);
+
+       spin_lock_irqsave(&schan->lock, flags);
+
+       /* Move descriptor to queue */
+       list_move_tail(&sdesc->node, &schan->queued);
+
+       /* Update cookie */
+       cookie = schan->chan.cookie + 1;
+       if (cookie <= 0)
+               cookie = 1;
+
+       schan->chan.cookie = cookie;
+       sdesc->desc.cookie = cookie;
+
+       spin_unlock_irqrestore(&schan->lock, flags);
+
+       return cookie;
+}
+
+static int sirfsoc_dma_slave_config(struct sirfsoc_dma_chan *schan,
+       struct dma_slave_config *config)
+{
+       unsigned long flags;
+
+       if ((config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+               (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES))
+               return -EINVAL;
+
+       spin_lock_irqsave(&schan->lock, flags);
+       schan->mode = (config->src_maxburst == 4 ? 1 : 0);
+       spin_unlock_irqrestore(&schan->lock, flags);
+
+       return 0;
+}
+
+static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan)
+{
+       struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
+       int cid = schan->chan.chan_id;
+       unsigned long flags;
+
+       writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) &
+               ~(1 << cid), sdma->base + SIRFSOC_DMA_INT_EN);
+       writel_relaxed(1 << cid, sdma->base + SIRFSOC_DMA_CH_VALID);
+
+       writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL)
+               & ~((1 << cid) | 1 << (cid + 16)),
+                       sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
+
+       spin_lock_irqsave(&schan->lock, flags);
+       list_splice_tail_init(&schan->active, &schan->free);
+       list_splice_tail_init(&schan->queued, &schan->free);
+       spin_unlock_irqrestore(&schan->lock, flags);
+
+       return 0;
+}
+
+static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+       unsigned long arg)
+{
+       struct dma_slave_config *config;
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+
+       switch (cmd) {
+       case DMA_TERMINATE_ALL:
+               return sirfsoc_dma_terminate_all(schan);
+       case DMA_SLAVE_CONFIG:
+               config = (struct dma_slave_config *)arg;
+               return sirfsoc_dma_slave_config(schan, config);
+
+       default:
+               break;
+       }
+
+       return -ENOSYS;
+}
+
+/* Alloc channel resources */
+static int sirfsoc_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan);
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+       struct sirfsoc_dma_desc *sdesc;
+       unsigned long flags;
+       LIST_HEAD(descs);
+       int i;
+
+       /* Alloc descriptors for this channel */
+       for (i = 0; i < SIRFSOC_DMA_DESCRIPTORS; i++) {
+               sdesc = kzalloc(sizeof(*sdesc), GFP_KERNEL);
+               if (!sdesc) {
+                       dev_notice(sdma->dma.dev, "Memory allocation error. "
+                               "Allocated only %u descriptors\n", i);
+                       break;
+               }
+
+               dma_async_tx_descriptor_init(&sdesc->desc, chan);
+               sdesc->desc.flags = DMA_CTRL_ACK;
+               sdesc->desc.tx_submit = sirfsoc_dma_tx_submit;
+
+               list_add_tail(&sdesc->node, &descs);
+       }
+
+       /* Return error only if no descriptors were allocated */
+       if (i == 0)
+               return -ENOMEM;
+
+       spin_lock_irqsave(&schan->lock, flags);
+
+       list_splice_tail_init(&descs, &schan->free);
+       spin_unlock_irqrestore(&schan->lock, flags);
+
+       return i;
+}
+
+/* Free channel resources */
+static void sirfsoc_dma_free_chan_resources(struct dma_chan *chan)
+{
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+       struct sirfsoc_dma_desc *sdesc, *tmp;
+       unsigned long flags;
+       LIST_HEAD(descs);
+
+       spin_lock_irqsave(&schan->lock, flags);
+
+       /* Channel must be idle */
+       BUG_ON(!list_empty(&schan->prepared));
+       BUG_ON(!list_empty(&schan->queued));
+       BUG_ON(!list_empty(&schan->active));
+       BUG_ON(!list_empty(&schan->completed));
+
+       /* Move data */
+       list_splice_tail_init(&schan->free, &descs);
+
+       spin_unlock_irqrestore(&schan->lock, flags);
+
+       /* Free descriptors */
+       list_for_each_entry_safe(sdesc, tmp, &descs, node)
+               kfree(sdesc);
+}
+
+/* Send pending descriptor to hardware */
+static void sirfsoc_dma_issue_pending(struct dma_chan *chan)
+{
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&schan->lock, flags);
+
+       if (list_empty(&schan->active) && !list_empty(&schan->queued))
+               sirfsoc_dma_execute(schan);
+
+       spin_unlock_irqrestore(&schan->lock, flags);
+}
+
+/* Check request completion status */
+static enum dma_status
+sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+       struct dma_tx_state *txstate)
+{
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+       unsigned long flags;
+       dma_cookie_t last_used;
+       dma_cookie_t last_complete;
+
+       spin_lock_irqsave(&schan->lock, flags);
+       last_used = schan->chan.cookie;
+       last_complete = schan->completed_cookie;
+       spin_unlock_irqrestore(&schan->lock, flags);
+
+       dma_set_tx_state(txstate, last_complete, last_used, 0);
+       return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
+       struct dma_chan *chan, struct dma_interleaved_template *xt,
+       unsigned long flags)
+{
+       struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan);
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+       struct sirfsoc_dma_desc *sdesc = NULL;
+       unsigned long iflags;
+       int ret;
+
+       if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+               ret = -EINVAL;
+               goto err_dir;
+       }
+
+       /* Get free descriptor */
+       spin_lock_irqsave(&schan->lock, iflags);
+       if (!list_empty(&schan->free)) {
+               sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc,
+                       node);
+               list_del(&sdesc->node);
+       }
+       spin_unlock_irqrestore(&schan->lock, iflags);
+
+       if (!sdesc) {
+               /* try to free completed descriptors */
+               sirfsoc_dma_process_completed(sdma);
+               ret = 0;
+               goto no_desc;
+       }
+
+       /* Place descriptor in prepared list */
+       spin_lock_irqsave(&schan->lock, iflags);
+
+       /*
+        * Number of chunks in a frame can only be 1 for prima2
+        * and ylen (number of frame - 1) must be at least 0
+        */
+       if ((xt->frame_size == 1) && (xt->numf > 0)) {
+               sdesc->cyclic = 0;
+               sdesc->xlen = xt->sgl[0].size / SIRFSOC_DMA_WORD_LEN;
+               sdesc->width = (xt->sgl[0].size + xt->sgl[0].icg) /
+                               SIRFSOC_DMA_WORD_LEN;
+               sdesc->ylen = xt->numf - 1;
+               if (xt->dir == DMA_MEM_TO_DEV) {
+                       sdesc->addr = xt->src_start;
+                       sdesc->dir = 1;
+               } else {
+                       sdesc->addr = xt->dst_start;
+                       sdesc->dir = 0;
+               }
+
+               list_add_tail(&sdesc->node, &schan->prepared);
+       } else {
+               pr_err("sirfsoc DMA Invalid xfer\n");
+               ret = -EINVAL;
+               goto err_xfer;
+       }
+       spin_unlock_irqrestore(&schan->lock, iflags);
+
+       return &sdesc->desc;
+err_xfer:
+       spin_unlock_irqrestore(&schan->lock, iflags);
+no_desc:
+err_dir:
+       return ERR_PTR(ret);
+}
+
+static struct dma_async_tx_descriptor *
+sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr,
+       size_t buf_len, size_t period_len,
+       enum dma_transfer_direction direction)
+{
+       struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+       struct sirfsoc_dma_desc *sdesc = NULL;
+       unsigned long iflags;
+
+       /*
+        * we only support cycle transfer with 2 period
+        * If the X-length is set to 0, it would be the loop mode.
+        * The DMA address keeps increasing until reaching the end of a loop
+        * area whose size is defined by (DMA_WIDTH x (Y_LENGTH + 1)). Then
+        * the DMA address goes back to the beginning of this area.
+        * In loop mode, the DMA data region is divided into two parts, BUFA
+        * and BUFB. DMA controller generates interrupts twice in each loop:
+        * when the DMA address reaches the end of BUFA or the end of the
+        * BUFB
+        */
+       if (buf_len !=  2 * period_len)
+               return ERR_PTR(-EINVAL);
+
+       /* Get free descriptor */
+       spin_lock_irqsave(&schan->lock, iflags);
+       if (!list_empty(&schan->free)) {
+               sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc,
+                       node);
+               list_del(&sdesc->node);
+       }
+       spin_unlock_irqrestore(&schan->lock, iflags);
+
+       if (!sdesc)
+               return 0;
+
+       /* Place descriptor in prepared list */
+       spin_lock_irqsave(&schan->lock, iflags);
+       sdesc->addr = addr;
+       sdesc->cyclic = 1;
+       sdesc->xlen = 0;
+       sdesc->ylen = buf_len / SIRFSOC_DMA_WORD_LEN - 1;
+       sdesc->width = 1;
+       list_add_tail(&sdesc->node, &schan->prepared);
+       spin_unlock_irqrestore(&schan->lock, iflags);
+
+       return &sdesc->desc;
+}
+
+/*
+ * The DMA controller consists of 16 independent DMA channels.
+ * Each channel is allocated to a different function
+ */
+bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id)
+{
+       unsigned int ch_nr = (unsigned int) chan_id;
+
+       if (ch_nr == chan->chan_id +
+               chan->device->dev_id * SIRFSOC_DMA_CHANNELS)
+               return true;
+
+       return false;
+}
+EXPORT_SYMBOL(sirfsoc_dma_filter_id);
+
+static int __devinit sirfsoc_dma_probe(struct platform_device *op)
+{
+       struct device_node *dn = op->dev.of_node;
+       struct device *dev = &op->dev;
+       struct dma_device *dma;
+       struct sirfsoc_dma *sdma;
+       struct sirfsoc_dma_chan *schan;
+       struct resource res;
+       ulong regs_start, regs_size;
+       u32 id;
+       int ret, i;
+
+       sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL);
+       if (!sdma) {
+               dev_err(dev, "Memory exhausted!\n");
+               return -ENOMEM;
+       }
+
+       if (of_property_read_u32(dn, "cell-index", &id)) {
+               dev_err(dev, "Fail to get DMAC index\n");
+               ret = -ENODEV;
+               goto free_mem;
+       }
+
+       sdma->irq = irq_of_parse_and_map(dn, 0);
+       if (sdma->irq == NO_IRQ) {
+               dev_err(dev, "Error mapping IRQ!\n");
+               ret = -EINVAL;
+               goto free_mem;
+       }
+
+       ret = of_address_to_resource(dn, 0, &res);
+       if (ret) {
+               dev_err(dev, "Error parsing memory region!\n");
+               goto free_mem;
+       }
+
+       regs_start = res.start;
+       regs_size = resource_size(&res);
+
+       sdma->base = devm_ioremap(dev, regs_start, regs_size);
+       if (!sdma->base) {
+               dev_err(dev, "Error mapping memory region!\n");
+               ret = -ENOMEM;
+               goto irq_dispose;
+       }
+
+       ret = devm_request_irq(dev, sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME,
+               sdma);
+       if (ret) {
+               dev_err(dev, "Error requesting IRQ!\n");
+               ret = -EINVAL;
+               goto unmap_mem;
+       }
+
+       dma = &sdma->dma;
+       dma->dev = dev;
+       dma->chancnt = SIRFSOC_DMA_CHANNELS;
+
+       dma->device_alloc_chan_resources = sirfsoc_dma_alloc_chan_resources;
+       dma->device_free_chan_resources = sirfsoc_dma_free_chan_resources;
+       dma->device_issue_pending = sirfsoc_dma_issue_pending;
+       dma->device_control = sirfsoc_dma_control;
+       dma->device_tx_status = sirfsoc_dma_tx_status;
+       dma->device_prep_interleaved_dma = sirfsoc_dma_prep_interleaved;
+       dma->device_prep_dma_cyclic = sirfsoc_dma_prep_cyclic;
+
+       INIT_LIST_HEAD(&dma->channels);
+       dma_cap_set(DMA_SLAVE, dma->cap_mask);
+       dma_cap_set(DMA_CYCLIC, dma->cap_mask);
+       dma_cap_set(DMA_INTERLEAVE, dma->cap_mask);
+       dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+
+       for (i = 0; i < dma->chancnt; i++) {
+               schan = &sdma->channels[i];
+
+               schan->chan.device = dma;
+               schan->chan.cookie = 1;
+               schan->completed_cookie = schan->chan.cookie;
+
+               INIT_LIST_HEAD(&schan->free);
+               INIT_LIST_HEAD(&schan->prepared);
+               INIT_LIST_HEAD(&schan->queued);
+               INIT_LIST_HEAD(&schan->active);
+               INIT_LIST_HEAD(&schan->completed);
+
+               spin_lock_init(&schan->lock);
+               list_add_tail(&schan->chan.device_node, &dma->channels);
+       }
+
+       tasklet_init(&sdma->tasklet, sirfsoc_dma_tasklet, (unsigned long)sdma);
+
+       /* Register DMA engine */
+       dev_set_drvdata(dev, sdma);
+       ret = dma_async_device_register(dma);
+       if (ret)
+               goto free_irq;
+
+       dev_info(dev, "initialized SIRFSOC DMAC driver\n");
+
+       return 0;
+
+free_irq:
+       devm_free_irq(dev, sdma->irq, sdma);
+irq_dispose:
+       irq_dispose_mapping(sdma->irq);
+unmap_mem:
+       iounmap(sdma->base);
+free_mem:
+       devm_kfree(dev, sdma);
+       return ret;
+}
+
+static int __devexit sirfsoc_dma_remove(struct platform_device *op)
+{
+       struct device *dev = &op->dev;
+       struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
+
+       dma_async_device_unregister(&sdma->dma);
+       devm_free_irq(dev, sdma->irq, sdma);
+       irq_dispose_mapping(sdma->irq);
+       iounmap(sdma->base);
+       devm_kfree(dev, sdma);
+       return 0;
+}
+
+static struct of_device_id sirfsoc_dma_match[] = {
+       { .compatible = "sirf,prima2-dmac", },
+       {},
+};
+
+static struct platform_driver sirfsoc_dma_driver = {
+       .probe          = sirfsoc_dma_probe,
+       .remove         = __devexit_p(sirfsoc_dma_remove),
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = sirfsoc_dma_match,
+       },
+};
+
+module_platform_driver(sirfsoc_dma_driver);
+
+MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
+       "Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("SIRFSOC DMA control driver");
+MODULE_LICENSE("GPL v2");
index 13259cad0ceb61df6a593af758ebf1aec4ec877b..cc5ecbc067a3d8a8d88c97190b0248fb0851593b 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/err.h>
 #include <linux/amba/bus.h>
 
@@ -32,6 +34,9 @@
 /* Maximum iterations taken before giving up suspending a channel */
 #define D40_SUSPEND_MAX_IT 500
 
+/* Milliseconds */
+#define DMA40_AUTOSUSPEND_DELAY        100
+
 /* Hardware requirement on LCLA alignment */
 #define LCLA_ALIGNMENT 0x40000
 
@@ -62,6 +67,55 @@ enum d40_command {
        D40_DMA_SUSPENDED       = 3
 };
 
+/*
+ * These are the registers that has to be saved and later restored
+ * when the DMA hw is powered off.
+ * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works.
+ */
+static u32 d40_backup_regs[] = {
+       D40_DREG_LCPA,
+       D40_DREG_LCLA,
+       D40_DREG_PRMSE,
+       D40_DREG_PRMSO,
+       D40_DREG_PRMOE,
+       D40_DREG_PRMOO,
+};
+
+#define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs)
+
+/* TODO: Check if all these registers have to be saved/restored on dma40 v3 */
+static u32 d40_backup_regs_v3[] = {
+       D40_DREG_PSEG1,
+       D40_DREG_PSEG2,
+       D40_DREG_PSEG3,
+       D40_DREG_PSEG4,
+       D40_DREG_PCEG1,
+       D40_DREG_PCEG2,
+       D40_DREG_PCEG3,
+       D40_DREG_PCEG4,
+       D40_DREG_RSEG1,
+       D40_DREG_RSEG2,
+       D40_DREG_RSEG3,
+       D40_DREG_RSEG4,
+       D40_DREG_RCEG1,
+       D40_DREG_RCEG2,
+       D40_DREG_RCEG3,
+       D40_DREG_RCEG4,
+};
+
+#define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3)
+
+static u32 d40_backup_regs_chan[] = {
+       D40_CHAN_REG_SSCFG,
+       D40_CHAN_REG_SSELT,
+       D40_CHAN_REG_SSPTR,
+       D40_CHAN_REG_SSLNK,
+       D40_CHAN_REG_SDCFG,
+       D40_CHAN_REG_SDELT,
+       D40_CHAN_REG_SDPTR,
+       D40_CHAN_REG_SDLNK,
+};
+
 /**
  * struct d40_lli_pool - Structure for keeping LLIs in memory
  *
@@ -96,7 +150,7 @@ struct d40_lli_pool {
  * during a transfer.
  * @node: List entry.
  * @is_in_client_list: true if the client owns this descriptor.
- * the previous one.
+ * @cyclic: true if this is a cyclic job
  *
  * This descriptor is used for both logical and physical transfers.
  */
@@ -143,6 +197,7 @@ struct d40_lcla_pool {
  * channels.
  *
  * @lock: A lock protection this entity.
+ * @reserved: True if used by secure world or otherwise.
  * @num: The physical channel number of this entity.
  * @allocated_src: Bit mapped to show which src event line's are mapped to
  * this physical channel. Can also be free or physically allocated.
@@ -152,6 +207,7 @@ struct d40_lcla_pool {
  */
 struct d40_phy_res {
        spinlock_t lock;
+       bool       reserved;
        int        num;
        u32        allocated_src;
        u32        allocated_dst;
@@ -185,7 +241,6 @@ struct d40_base;
  * @src_def_cfg: Default cfg register setting for src.
  * @dst_def_cfg: Default cfg register setting for dst.
  * @log_def: Default logical channel settings.
- * @lcla: Space for one dst src pair for logical channel transfers.
  * @lcpa: Pointer to dst and src lcpa settings.
  * @runtime_addr: runtime configured address.
  * @runtime_direction: runtime configured direction.
@@ -217,7 +272,7 @@ struct d40_chan {
        struct d40_log_lli_full         *lcpa;
        /* Runtime reconfiguration */
        dma_addr_t                      runtime_addr;
-       enum dma_data_direction         runtime_direction;
+       enum dma_transfer_direction     runtime_direction;
 };
 
 /**
@@ -241,6 +296,7 @@ struct d40_chan {
  * @dma_both: dma_device channels that can do both memcpy and slave transfers.
  * @dma_slave: dma_device channels that can do only do slave transfers.
  * @dma_memcpy: dma_device channels that can do only do memcpy transfers.
+ * @phy_chans: Room for all possible physical channels in system.
  * @log_chans: Room for all possible logical channels in system.
  * @lookup_log_chans: Used to map interrupt number to logical channel. Points
  * to log_chans entries.
@@ -248,12 +304,20 @@ struct d40_chan {
  * to phy_chans entries.
  * @plat_data: Pointer to provided platform_data which is the driver
  * configuration.
+ * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
  * @phy_res: Vector containing all physical channels.
  * @lcla_pool: lcla pool settings and data.
  * @lcpa_base: The virtual mapped address of LCPA.
  * @phy_lcpa: The physical address of the LCPA.
  * @lcpa_size: The size of the LCPA area.
  * @desc_slab: cache for descriptors.
+ * @reg_val_backup: Here the values of some hardware registers are stored
+ * before the DMA is powered off. They are restored when the power is back on.
+ * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and
+ * later.
+ * @reg_val_backup_chan: Backup data for standard channel parameter registers.
+ * @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off.
+ * @initialized: true if the dma has been initialized
  */
 struct d40_base {
        spinlock_t                       interrupt_lock;
@@ -275,6 +339,7 @@ struct d40_base {
        struct d40_chan                 **lookup_log_chans;
        struct d40_chan                 **lookup_phy_chans;
        struct stedma40_platform_data    *plat_data;
+       struct regulator                 *lcpa_regulator;
        /* Physical half channels */
        struct d40_phy_res               *phy_res;
        struct d40_lcla_pool              lcla_pool;
@@ -282,6 +347,11 @@ struct d40_base {
        dma_addr_t                        phy_lcpa;
        resource_size_t                   lcpa_size;
        struct kmem_cache                *desc_slab;
+       u32                               reg_val_backup[BACKUP_REGS_SZ];
+       u32                               reg_val_backup_v3[BACKUP_REGS_SZ_V3];
+       u32                              *reg_val_backup_chan;
+       u16                               gcc_pwr_off_mask;
+       bool                              initialized;
 };
 
 /**
@@ -479,13 +549,14 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c)
                struct d40_desc *d;
                struct d40_desc *_d;
 
-               list_for_each_entry_safe(d, _d, &d40c->client, node)
+               list_for_each_entry_safe(d, _d, &d40c->client, node) {
                        if (async_tx_test_ack(&d->txd)) {
                                d40_desc_remove(d);
                                desc = d;
                                memset(desc, 0, sizeof(*desc));
                                break;
                        }
+               }
        }
 
        if (!desc)
@@ -536,6 +607,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
        bool cyclic = desc->cyclic;
        int curr_lcla = -EINVAL;
        int first_lcla = 0;
+       bool use_esram_lcla = chan->base->plat_data->use_esram_lcla;
        bool linkback;
 
        /*
@@ -608,11 +680,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
                                       &lli->src[lli_current],
                                       next_lcla, flags);
 
-               dma_sync_single_range_for_device(chan->base->dev,
-                                       pool->dma_addr, lcla_offset,
-                                       2 * sizeof(struct d40_log_lli),
-                                       DMA_TO_DEVICE);
-
+               /*
+                * Cache maintenance is not needed if lcla is
+                * mapped in esram
+                */
+               if (!use_esram_lcla) {
+                       dma_sync_single_range_for_device(chan->base->dev,
+                                               pool->dma_addr, lcla_offset,
+                                               2 * sizeof(struct d40_log_lli),
+                                               DMA_TO_DEVICE);
+               }
                curr_lcla = next_lcla;
 
                if (curr_lcla == -EINVAL || curr_lcla == first_lcla) {
@@ -740,7 +817,61 @@ static int d40_sg_2_dmalen(struct scatterlist *sgl, int sg_len,
        return len;
 }
 
-/* Support functions for logical channels */
+
+#ifdef CONFIG_PM
+static void dma40_backup(void __iomem *baseaddr, u32 *backup,
+                        u32 *regaddr, int num, bool save)
+{
+       int i;
+
+       for (i = 0; i < num; i++) {
+               void __iomem *addr = baseaddr + regaddr[i];
+
+               if (save)
+                       backup[i] = readl_relaxed(addr);
+               else
+                       writel_relaxed(backup[i], addr);
+       }
+}
+
+static void d40_save_restore_registers(struct d40_base *base, bool save)
+{
+       int i;
+
+       /* Save/Restore channel specific registers */
+       for (i = 0; i < base->num_phy_chans; i++) {
+               void __iomem *addr;
+               int idx;
+
+               if (base->phy_res[i].reserved)
+                       continue;
+
+               addr = base->virtbase + D40_DREG_PCBASE + i * D40_DREG_PCDELTA;
+               idx = i * ARRAY_SIZE(d40_backup_regs_chan);
+
+               dma40_backup(addr, &base->reg_val_backup_chan[idx],
+                            d40_backup_regs_chan,
+                            ARRAY_SIZE(d40_backup_regs_chan),
+                            save);
+       }
+
+       /* Save/Restore global registers */
+       dma40_backup(base->virtbase, base->reg_val_backup,
+                    d40_backup_regs, ARRAY_SIZE(d40_backup_regs),
+                    save);
+
+       /* Save/Restore registers only existing on dma40 v3 and later */
+       if (base->rev >= 3)
+               dma40_backup(base->virtbase, base->reg_val_backup_v3,
+                            d40_backup_regs_v3,
+                            ARRAY_SIZE(d40_backup_regs_v3),
+                            save);
+}
+#else
+static void d40_save_restore_registers(struct d40_base *base, bool save)
+{
+}
+#endif
 
 static int d40_channel_execute_command(struct d40_chan *d40c,
                                       enum d40_command command)
@@ -973,6 +1104,10 @@ static void d40_config_write(struct d40_chan *d40c)
                /* Set LIDX for lcla */
                writel(lidx, chanbase + D40_CHAN_REG_SSELT);
                writel(lidx, chanbase + D40_CHAN_REG_SDELT);
+
+               /* Clear LNK which will be used by d40_chan_has_events() */
+               writel(0, chanbase + D40_CHAN_REG_SSLNK);
+               writel(0, chanbase + D40_CHAN_REG_SDLNK);
        }
 }
 
@@ -1013,6 +1148,7 @@ static int d40_pause(struct d40_chan *d40c)
        if (!d40c->busy)
                return 0;
 
+       pm_runtime_get_sync(d40c->base->dev);
        spin_lock_irqsave(&d40c->lock, flags);
 
        res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
@@ -1025,7 +1161,8 @@ static int d40_pause(struct d40_chan *d40c)
                                                                  D40_DMA_RUN);
                }
        }
-
+       pm_runtime_mark_last_busy(d40c->base->dev);
+       pm_runtime_put_autosuspend(d40c->base->dev);
        spin_unlock_irqrestore(&d40c->lock, flags);
        return res;
 }
@@ -1039,7 +1176,7 @@ static int d40_resume(struct d40_chan *d40c)
                return 0;
 
        spin_lock_irqsave(&d40c->lock, flags);
-
+       pm_runtime_get_sync(d40c->base->dev);
        if (d40c->base->rev == 0)
                if (chan_is_logical(d40c)) {
                        res = d40_channel_execute_command(d40c,
@@ -1057,6 +1194,8 @@ static int d40_resume(struct d40_chan *d40c)
        }
 
 no_suspend:
+       pm_runtime_mark_last_busy(d40c->base->dev);
+       pm_runtime_put_autosuspend(d40c->base->dev);
        spin_unlock_irqrestore(&d40c->lock, flags);
        return res;
 }
@@ -1129,7 +1268,10 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
        d40d = d40_first_queued(d40c);
 
        if (d40d != NULL) {
-               d40c->busy = true;
+               if (!d40c->busy)
+                       d40c->busy = true;
+
+               pm_runtime_get_sync(d40c->base->dev);
 
                /* Remove from queue */
                d40_desc_remove(d40d);
@@ -1190,6 +1332,8 @@ static void dma_tc_handle(struct d40_chan *d40c)
 
                if (d40_queue_start(d40c) == NULL)
                        d40c->busy = false;
+               pm_runtime_mark_last_busy(d40c->base->dev);
+               pm_runtime_put_autosuspend(d40c->base->dev);
        }
 
        d40c->pending_tx++;
@@ -1405,11 +1549,16 @@ static int d40_validate_conf(struct d40_chan *d40c,
        return res;
 }
 
-static bool d40_alloc_mask_set(struct d40_phy_res *phy, bool is_src,
-                              int log_event_line, bool is_log)
+static bool d40_alloc_mask_set(struct d40_phy_res *phy,
+                              bool is_src, int log_event_line, bool is_log,
+                              bool *first_user)
 {
        unsigned long flags;
        spin_lock_irqsave(&phy->lock, flags);
+
+       *first_user = ((phy->allocated_src | phy->allocated_dst)
+                       == D40_ALLOC_FREE);
+
        if (!is_log) {
                /* Physical interrupts are masked per physical full channel */
                if (phy->allocated_src == D40_ALLOC_FREE &&
@@ -1490,7 +1639,7 @@ out:
        return is_free;
 }
 
-static int d40_allocate_channel(struct d40_chan *d40c)
+static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
 {
        int dev_type;
        int event_group;
@@ -1526,7 +1675,8 @@ static int d40_allocate_channel(struct d40_chan *d40c)
                        for (i = 0; i < d40c->base->num_phy_chans; i++) {
 
                                if (d40_alloc_mask_set(&phys[i], is_src,
-                                                      0, is_log))
+                                                      0, is_log,
+                                                      first_phy_user))
                                        goto found_phy;
                        }
                } else
@@ -1536,7 +1686,8 @@ static int d40_allocate_channel(struct d40_chan *d40c)
                                        if (d40_alloc_mask_set(&phys[i],
                                                               is_src,
                                                               0,
-                                                              is_log))
+                                                              is_log,
+                                                              first_phy_user))
                                                goto found_phy;
                                }
                        }
@@ -1552,6 +1703,25 @@ found_phy:
        /* Find logical channel */
        for (j = 0; j < d40c->base->num_phy_chans; j += 8) {
                int phy_num = j + event_group * 2;
+
+               if (d40c->dma_cfg.use_fixed_channel) {
+                       i = d40c->dma_cfg.phy_channel;
+
+                       if ((i != phy_num) && (i != phy_num + 1)) {
+                               dev_err(chan2dev(d40c),
+                                       "invalid fixed phy channel %d\n", i);
+                               return -EINVAL;
+                       }
+
+                       if (d40_alloc_mask_set(&phys[i], is_src, event_line,
+                                              is_log, first_phy_user))
+                               goto found_log;
+
+                       dev_err(chan2dev(d40c),
+                               "could not allocate fixed phy channel %d\n", i);
+                       return -EINVAL;
+               }
+
                /*
                 * Spread logical channels across all available physical rather
                 * than pack every logical channel at the first available phy
@@ -1560,13 +1730,15 @@ found_phy:
                if (is_src) {
                        for (i = phy_num; i < phy_num + 2; i++) {
                                if (d40_alloc_mask_set(&phys[i], is_src,
-                                                      event_line, is_log))
+                                                      event_line, is_log,
+                                                      first_phy_user))
                                        goto found_log;
                        }
                } else {
                        for (i = phy_num + 1; i >= phy_num; i--) {
                                if (d40_alloc_mask_set(&phys[i], is_src,
-                                                      event_line, is_log))
+                                                      event_line, is_log,
+                                                      first_phy_user))
                                        goto found_log;
                        }
                }
@@ -1643,10 +1815,11 @@ static int d40_free_dma(struct d40_chan *d40c)
                return -EINVAL;
        }
 
+       pm_runtime_get_sync(d40c->base->dev);
        res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
        if (res) {
                chan_err(d40c, "suspend failed\n");
-               return res;
+               goto out;
        }
 
        if (chan_is_logical(d40c)) {
@@ -1664,13 +1837,11 @@ static int d40_free_dma(struct d40_chan *d40c)
                        if (d40_chan_has_events(d40c)) {
                                res = d40_channel_execute_command(d40c,
                                                                  D40_DMA_RUN);
-                               if (res) {
+                               if (res)
                                        chan_err(d40c,
                                                "Executing RUN command\n");
-                                       return res;
-                               }
                        }
-                       return 0;
+                       goto out;
                }
        } else {
                (void) d40_alloc_mask_free(phy, is_src, 0);
@@ -1680,13 +1851,23 @@ static int d40_free_dma(struct d40_chan *d40c)
        res = d40_channel_execute_command(d40c, D40_DMA_STOP);
        if (res) {
                chan_err(d40c, "Failed to stop channel\n");
-               return res;
+               goto out;
        }
+
+       if (d40c->busy) {
+               pm_runtime_mark_last_busy(d40c->base->dev);
+               pm_runtime_put_autosuspend(d40c->base->dev);
+       }
+
+       d40c->busy = false;
        d40c->phy_chan = NULL;
        d40c->configured = false;
        d40c->base->lookup_phy_chans[phy->num] = NULL;
+out:
 
-       return 0;
+       pm_runtime_mark_last_busy(d40c->base->dev);
+       pm_runtime_put_autosuspend(d40c->base->dev);
+       return res;
 }
 
 static bool d40_is_paused(struct d40_chan *d40c)
@@ -1855,7 +2036,7 @@ err:
 }
 
 static dma_addr_t
-d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
+d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction)
 {
        struct stedma40_platform_data *plat = chan->base->plat_data;
        struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
@@ -1864,9 +2045,9 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
        if (chan->runtime_addr)
                return chan->runtime_addr;
 
-       if (direction == DMA_FROM_DEVICE)
+       if (direction == DMA_DEV_TO_MEM)
                addr = plat->dev_rx[cfg->src_dev_type];
-       else if (direction == DMA_TO_DEVICE)
+       else if (direction == DMA_MEM_TO_DEV)
                addr = plat->dev_tx[cfg->dst_dev_type];
 
        return addr;
@@ -1875,7 +2056,7 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
 static struct dma_async_tx_descriptor *
 d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
            struct scatterlist *sg_dst, unsigned int sg_len,
-           enum dma_data_direction direction, unsigned long dma_flags)
+           enum dma_transfer_direction direction, unsigned long dma_flags)
 {
        struct d40_chan *chan = container_of(dchan, struct d40_chan, chan);
        dma_addr_t src_dev_addr = 0;
@@ -1902,9 +2083,9 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
        if (direction != DMA_NONE) {
                dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
 
-               if (direction == DMA_FROM_DEVICE)
+               if (direction == DMA_DEV_TO_MEM)
                        src_dev_addr = dev_addr;
-               else if (direction == DMA_TO_DEVICE)
+               else if (direction == DMA_MEM_TO_DEV)
                        dst_dev_addr = dev_addr;
        }
 
@@ -2011,14 +2192,15 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
                        goto fail;
                }
        }
-       is_free_phy = (d40c->phy_chan == NULL);
 
-       err = d40_allocate_channel(d40c);
+       err = d40_allocate_channel(d40c, &is_free_phy);
        if (err) {
                chan_err(d40c, "Failed to allocate channel\n");
+               d40c->configured = false;
                goto fail;
        }
 
+       pm_runtime_get_sync(d40c->base->dev);
        /* Fill in basic CFG register values */
        d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg,
                    &d40c->dst_def_cfg, chan_is_logical(d40c));
@@ -2038,6 +2220,12 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
                          D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
        }
 
+       dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n",
+                chan_is_logical(d40c) ? "logical" : "physical",
+                d40c->phy_chan->num,
+                d40c->dma_cfg.use_fixed_channel ? ", fixed" : "");
+
+
        /*
         * Only write channel configuration to the DMA if the physical
         * resource is free. In case of multiple logical channels
@@ -2046,6 +2234,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
        if (is_free_phy)
                d40_config_write(d40c);
 fail:
+       pm_runtime_mark_last_busy(d40c->base->dev);
+       pm_runtime_put_autosuspend(d40c->base->dev);
        spin_unlock_irqrestore(&d40c->lock, flags);
        return err;
 }
@@ -2108,10 +2298,10 @@ d40_prep_memcpy_sg(struct dma_chan *chan,
 static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
                                                         struct scatterlist *sgl,
                                                         unsigned int sg_len,
-                                                        enum dma_data_direction direction,
+                                                        enum dma_transfer_direction direction,
                                                         unsigned long dma_flags)
 {
-       if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE)
+       if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV)
                return NULL;
 
        return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags);
@@ -2120,7 +2310,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
 static struct dma_async_tx_descriptor *
 dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
                     size_t buf_len, size_t period_len,
-                    enum dma_data_direction direction)
+                    enum dma_transfer_direction direction)
 {
        unsigned int periods = buf_len / period_len;
        struct dma_async_tx_descriptor *txd;
@@ -2269,7 +2459,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
        dst_addr_width = config->dst_addr_width;
        dst_maxburst = config->dst_maxburst;
 
-       if (config->direction == DMA_FROM_DEVICE) {
+       if (config->direction == DMA_DEV_TO_MEM) {
                dma_addr_t dev_addr_rx =
                        d40c->base->plat_data->dev_rx[cfg->src_dev_type];
 
@@ -2292,7 +2482,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
                if (dst_maxburst == 0)
                        dst_maxburst = src_maxburst;
 
-       } else if (config->direction == DMA_TO_DEVICE) {
+       } else if (config->direction == DMA_MEM_TO_DEV) {
                dma_addr_t dev_addr_tx =
                        d40c->base->plat_data->dev_tx[cfg->dst_dev_type];
 
@@ -2357,7 +2547,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
                "configured channel %s for %s, data width %d/%d, "
                "maxburst %d/%d elements, LE, no flow control\n",
                dma_chan_name(chan),
-               (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
+               (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX",
                src_addr_width, dst_addr_width,
                src_maxburst, dst_maxburst);
 
@@ -2519,6 +2709,72 @@ failure1:
        return err;
 }
 
+/* Suspend resume functionality */
+#ifdef CONFIG_PM
+static int dma40_pm_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct d40_base *base = platform_get_drvdata(pdev);
+       int ret = 0;
+       if (!pm_runtime_suspended(dev))
+               return -EBUSY;
+
+       if (base->lcpa_regulator)
+               ret = regulator_disable(base->lcpa_regulator);
+       return ret;
+}
+
+static int dma40_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct d40_base *base = platform_get_drvdata(pdev);
+
+       d40_save_restore_registers(base, true);
+
+       /* Don't disable/enable clocks for v1 due to HW bugs */
+       if (base->rev != 1)
+               writel_relaxed(base->gcc_pwr_off_mask,
+                              base->virtbase + D40_DREG_GCC);
+
+       return 0;
+}
+
+static int dma40_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct d40_base *base = platform_get_drvdata(pdev);
+
+       if (base->initialized)
+               d40_save_restore_registers(base, false);
+
+       writel_relaxed(D40_DREG_GCC_ENABLE_ALL,
+                      base->virtbase + D40_DREG_GCC);
+       return 0;
+}
+
+static int dma40_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct d40_base *base = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       if (base->lcpa_regulator)
+               ret = regulator_enable(base->lcpa_regulator);
+
+       return ret;
+}
+
+static const struct dev_pm_ops dma40_pm_ops = {
+       .suspend                = dma40_pm_suspend,
+       .runtime_suspend        = dma40_runtime_suspend,
+       .runtime_resume         = dma40_runtime_resume,
+       .resume                 = dma40_resume,
+};
+#define DMA40_PM_OPS   (&dma40_pm_ops)
+#else
+#define DMA40_PM_OPS   NULL
+#endif
+
 /* Initialization functions. */
 
 static int __init d40_phy_res_init(struct d40_base *base)
@@ -2527,6 +2783,7 @@ static int __init d40_phy_res_init(struct d40_base *base)
        int num_phy_chans_avail = 0;
        u32 val[2];
        int odd_even_bit = -2;
+       int gcc = D40_DREG_GCC_ENA;
 
        val[0] = readl(base->virtbase + D40_DREG_PRSME);
        val[1] = readl(base->virtbase + D40_DREG_PRSMO);
@@ -2538,9 +2795,17 @@ static int __init d40_phy_res_init(struct d40_base *base)
                        /* Mark security only channels as occupied */
                        base->phy_res[i].allocated_src = D40_ALLOC_PHY;
                        base->phy_res[i].allocated_dst = D40_ALLOC_PHY;
+                       base->phy_res[i].reserved = true;
+                       gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i),
+                                                      D40_DREG_GCC_SRC);
+                       gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i),
+                                                      D40_DREG_GCC_DST);
+
+
                } else {
                        base->phy_res[i].allocated_src = D40_ALLOC_FREE;
                        base->phy_res[i].allocated_dst = D40_ALLOC_FREE;
+                       base->phy_res[i].reserved = false;
                        num_phy_chans_avail++;
                }
                spin_lock_init(&base->phy_res[i].lock);
@@ -2552,6 +2817,11 @@ static int __init d40_phy_res_init(struct d40_base *base)
 
                base->phy_res[chan].allocated_src = D40_ALLOC_PHY;
                base->phy_res[chan].allocated_dst = D40_ALLOC_PHY;
+               base->phy_res[chan].reserved = true;
+               gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan),
+                                              D40_DREG_GCC_SRC);
+               gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan),
+                                              D40_DREG_GCC_DST);
                num_phy_chans_avail--;
        }
 
@@ -2572,6 +2842,15 @@ static int __init d40_phy_res_init(struct d40_base *base)
                val[0] = val[0] >> 2;
        }
 
+       /*
+        * To keep things simple, Enable all clocks initially.
+        * The clocks will get managed later post channel allocation.
+        * The clocks for the event lines on which reserved channels exists
+        * are not managed here.
+        */
+       writel(D40_DREG_GCC_ENABLE_ALL, base->virtbase + D40_DREG_GCC);
+       base->gcc_pwr_off_mask = gcc;
+
        return num_phy_chans_avail;
 }
 
@@ -2699,10 +2978,15 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
                        goto failure;
        }
 
-       base->lcla_pool.alloc_map = kzalloc(num_phy_chans *
-                                           sizeof(struct d40_desc *) *
-                                           D40_LCLA_LINK_PER_EVENT_GRP,
+       base->reg_val_backup_chan = kmalloc(base->num_phy_chans *
+                                           sizeof(d40_backup_regs_chan),
                                            GFP_KERNEL);
+       if (!base->reg_val_backup_chan)
+               goto failure;
+
+       base->lcla_pool.alloc_map =
+               kzalloc(num_phy_chans * sizeof(struct d40_desc *)
+                       * D40_LCLA_LINK_PER_EVENT_GRP, GFP_KERNEL);
        if (!base->lcla_pool.alloc_map)
                goto failure;
 
@@ -2741,9 +3025,9 @@ failure:
 static void __init d40_hw_init(struct d40_base *base)
 {
 
-       static const struct d40_reg_val dma_init_reg[] = {
+       static struct d40_reg_val dma_init_reg[] = {
                /* Clock every part of the DMA block from start */
-               { .reg = D40_DREG_GCC,    .val = 0x0000ff01},
+               { .reg = D40_DREG_GCC,    .val = D40_DREG_GCC_ENABLE_ALL},
 
                /* Interrupts on all logical channels */
                { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF},
@@ -2943,11 +3227,31 @@ static int __init d40_probe(struct platform_device *pdev)
                d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
                goto failure;
        }
+       /* If lcla has to be located in ESRAM we don't need to allocate */
+       if (base->plat_data->use_esram_lcla) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                       "lcla_esram");
+               if (!res) {
+                       ret = -ENOENT;
+                       d40_err(&pdev->dev,
+                               "No \"lcla_esram\" memory resource\n");
+                       goto failure;
+               }
+               base->lcla_pool.base = ioremap(res->start,
+                                               resource_size(res));
+               if (!base->lcla_pool.base) {
+                       ret = -ENOMEM;
+                       d40_err(&pdev->dev, "Failed to ioremap LCLA region\n");
+                       goto failure;
+               }
+               writel(res->start, base->virtbase + D40_DREG_LCLA);
 
-       ret = d40_lcla_allocate(base);
-       if (ret) {
-               d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
-               goto failure;
+       } else {
+               ret = d40_lcla_allocate(base);
+               if (ret) {
+                       d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
+                       goto failure;
+               }
        }
 
        spin_lock_init(&base->lcla_pool.lock);
@@ -2960,6 +3264,32 @@ static int __init d40_probe(struct platform_device *pdev)
                goto failure;
        }
 
+       pm_runtime_irq_safe(base->dev);
+       pm_runtime_set_autosuspend_delay(base->dev, DMA40_AUTOSUSPEND_DELAY);
+       pm_runtime_use_autosuspend(base->dev);
+       pm_runtime_enable(base->dev);
+       pm_runtime_resume(base->dev);
+
+       if (base->plat_data->use_esram_lcla) {
+
+               base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
+               if (IS_ERR(base->lcpa_regulator)) {
+                       d40_err(&pdev->dev, "Failed to get lcpa_regulator\n");
+                       base->lcpa_regulator = NULL;
+                       goto failure;
+               }
+
+               ret = regulator_enable(base->lcpa_regulator);
+               if (ret) {
+                       d40_err(&pdev->dev,
+                               "Failed to enable lcpa_regulator\n");
+                       regulator_put(base->lcpa_regulator);
+                       base->lcpa_regulator = NULL;
+                       goto failure;
+               }
+       }
+
+       base->initialized = true;
        err = d40_dmaengine_init(base, num_reserved_chans);
        if (err)
                goto failure;
@@ -2976,6 +3306,11 @@ failure:
                if (base->virtbase)
                        iounmap(base->virtbase);
 
+               if (base->lcla_pool.base && base->plat_data->use_esram_lcla) {
+                       iounmap(base->lcla_pool.base);
+                       base->lcla_pool.base = NULL;
+               }
+
                if (base->lcla_pool.dma_addr)
                        dma_unmap_single(base->dev, base->lcla_pool.dma_addr,
                                         SZ_1K * base->num_phy_chans,
@@ -2998,6 +3333,11 @@ failure:
                        clk_put(base->clk);
                }
 
+               if (base->lcpa_regulator) {
+                       regulator_disable(base->lcpa_regulator);
+                       regulator_put(base->lcpa_regulator);
+               }
+
                kfree(base->lcla_pool.alloc_map);
                kfree(base->lookup_log_chans);
                kfree(base->lookup_phy_chans);
@@ -3013,6 +3353,7 @@ static struct platform_driver d40_driver = {
        .driver = {
                .owner = THIS_MODULE,
                .name  = D40_NAME,
+               .pm = DMA40_PM_OPS,
        },
 };
 
index b44c455158de3461f31ee5a0b0594cb136b2ad6a..8d3d490968a3a8240b6f91e1631609a2425c3f4f 100644 (file)
@@ -16,6 +16,8 @@
 
 #define D40_TYPE_TO_GROUP(type) (type / 16)
 #define D40_TYPE_TO_EVENT(type) (type % 16)
+#define D40_GROUP_SIZE 8
+#define D40_PHYS_TO_GROUP(phys) ((phys & (D40_GROUP_SIZE - 1)) / 2)
 
 /* Most bits of the CFG register are the same in log as in phy mode */
 #define D40_SREG_CFG_MST_POS           15
 
 /* DMA Register Offsets */
 #define D40_DREG_GCC           0x000
+#define D40_DREG_GCC_ENA       0x1
+/* This assumes that there are only 4 event groups */
+#define D40_DREG_GCC_ENABLE_ALL        0xff01
+#define D40_DREG_GCC_EVTGRP_POS 8
+#define D40_DREG_GCC_SRC 0
+#define D40_DREG_GCC_DST 1
+#define D40_DREG_GCC_EVTGRP_ENA(x, y) \
+       (1 << (D40_DREG_GCC_EVTGRP_POS + 2 * x + y))
+
 #define D40_DREG_PRTYP         0x004
 #define D40_DREG_PRSME         0x008
 #define D40_DREG_PRSMO         0x00C
index a4a398f2ef61eb5a362ca20c37ebe9a479e2121a..a6f9c1684a0fc1dc4a9c7a2dbd2407fe6252b68d 100644 (file)
@@ -90,7 +90,7 @@ struct timb_dma_chan {
        struct list_head        queue;
        struct list_head        free_list;
        unsigned int            bytes_per_line;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction     direction;
        unsigned int            descs; /* Descriptors to allocate */
        unsigned int            desc_elems; /* number of elems per descriptor */
 };
@@ -166,10 +166,10 @@ static void __td_unmap_desc(struct timb_dma_chan *td_chan, const u8 *dma_desc,
 
        if (single)
                dma_unmap_single(chan2dev(&td_chan->chan), addr, len,
-                       td_chan->direction);
+                       DMA_TO_DEVICE);
        else
                dma_unmap_page(chan2dev(&td_chan->chan), addr, len,
-                       td_chan->direction);
+                       DMA_TO_DEVICE);
 }
 
 static void __td_unmap_descs(struct timb_dma_desc *td_desc, bool single)
@@ -235,7 +235,7 @@ static void __td_start_dma(struct timb_dma_chan *td_chan)
                "td_chan: %p, chan: %d, membase: %p\n",
                td_chan, td_chan->chan.chan_id, td_chan->membase);
 
-       if (td_chan->direction == DMA_FROM_DEVICE) {
+       if (td_chan->direction == DMA_DEV_TO_MEM) {
 
                /* descriptor address */
                iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_DHAR);
@@ -278,7 +278,7 @@ static void __td_finish(struct timb_dma_chan *td_chan)
                txd->cookie);
 
        /* make sure to stop the transfer */
-       if (td_chan->direction == DMA_FROM_DEVICE)
+       if (td_chan->direction == DMA_DEV_TO_MEM)
                iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_ER);
 /* Currently no support for stopping DMA transfers
        else
@@ -558,7 +558,7 @@ static void td_issue_pending(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan,
        struct scatterlist *sgl, unsigned int sg_len,
-       enum dma_data_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags)
 {
        struct timb_dma_chan *td_chan =
                container_of(chan, struct timb_dma_chan, chan);
@@ -606,7 +606,7 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan,
        }
 
        dma_sync_single_for_device(chan2dmadev(chan), td_desc->txd.phys,
-               td_desc->desc_list_len, DMA_TO_DEVICE);
+               td_desc->desc_list_len, DMA_MEM_TO_DEV);
 
        return &td_desc->txd;
 }
@@ -775,8 +775,8 @@ static int __devinit td_probe(struct platform_device *pdev)
                td_chan->descs = pchan->descriptors;
                td_chan->desc_elems = pchan->descriptor_elements;
                td_chan->bytes_per_line = pchan->bytes_per_line;
-               td_chan->direction = pchan->rx ? DMA_FROM_DEVICE :
-                       DMA_TO_DEVICE;
+               td_chan->direction = pchan->rx ? DMA_DEV_TO_MEM :
+                       DMA_MEM_TO_DEV;
 
                td_chan->membase = td->membase +
                        (i / 2) * TIMBDMA_INSTANCE_OFFSET +
@@ -841,17 +841,7 @@ static struct platform_driver td_driver = {
        .remove = __exit_p(td_remove),
 };
 
-static int __init td_init(void)
-{
-       return platform_driver_register(&td_driver);
-}
-module_init(td_init);
-
-static void __exit td_exit(void)
-{
-       platform_driver_unregister(&td_driver);
-}
-module_exit(td_exit);
+module_platform_driver(td_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Timberdale DMA controller driver");
index cbd83e362b5e0a78bcb25dec65f4fb29663710d9..6122c364cf11bb0050fb2b029c083b3c40233722 100644 (file)
@@ -845,7 +845,7 @@ txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 
 static struct dma_async_tx_descriptor *
 txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags)
 {
        struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
@@ -860,9 +860,9 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
        BUG_ON(!ds || !ds->reg_width);
        if (ds->tx_reg)
-               BUG_ON(direction != DMA_TO_DEVICE);
+               BUG_ON(direction != DMA_MEM_TO_DEV);
        else
-               BUG_ON(direction != DMA_FROM_DEVICE);
+               BUG_ON(direction != DMA_DEV_TO_MEM);
        if (unlikely(!sg_len))
                return NULL;
 
@@ -882,7 +882,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                mem = sg_dma_address(sg);
 
                if (__is_dmac64(ddev)) {
-                       if (direction == DMA_TO_DEVICE) {
+                       if (direction == DMA_MEM_TO_DEV) {
                                desc->hwdesc.SAR = mem;
                                desc->hwdesc.DAR = ds->tx_reg;
                        } else {
@@ -891,7 +891,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        }
                        desc->hwdesc.CNTR = sg_dma_len(sg);
                } else {
-                       if (direction == DMA_TO_DEVICE) {
+                       if (direction == DMA_MEM_TO_DEV) {
                                desc->hwdesc32.SAR = mem;
                                desc->hwdesc32.DAR = ds->tx_reg;
                        } else {
@@ -900,7 +900,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        }
                        desc->hwdesc32.CNTR = sg_dma_len(sg);
                }
-               if (direction == DMA_TO_DEVICE) {
+               if (direction == DMA_MEM_TO_DEV) {
                        sai = ds->reg_width;
                        dai = 0;
                } else {
index aa08497a075a70d1e33ee0de9dcdc9a64c9221ea..73f55e2008c2dcec72259b235d3304e84d663c8a 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/io.h>
 #include "edac_core.h"
 
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
 #define I3200_REVISION        "1.1"
 
 #define EDAC_MOD_STR        "i3200_edac"
@@ -101,19 +103,6 @@ struct i3200_priv {
 
 static int nr_channels;
 
-#ifndef readq
-static inline __u64 readq(const volatile void __iomem *addr)
-{
-       const volatile u32 __iomem *p = addr;
-       u32 low, high;
-
-       low = readl(p);
-       high = readl(p + 1);
-
-       return low + ((u64)high << 32);
-}
-#endif
-
 static int how_many_channels(struct pci_dev *pdev)
 {
        unsigned char capid0_8b; /* 8th byte of CAPID0 */
index 6628feaa76229009f1bf5f62b3419d9e79dcea35..7f5f0da726dafde5ae23ad1343861e12857c5002 100644 (file)
@@ -263,6 +263,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
 #define PCI_DEVICE_ID_AGERE_FW643      0x5901
+#define PCI_DEVICE_ID_CREATIVE_SB1394  0x4001
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
 #define PCI_DEVICE_ID_TI_TSB12LV26     0x8020
@@ -289,6 +290,9 @@ static const struct {
        {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
                QUIRK_NO_MSI},
 
+       {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+               QUIRK_RESET_PACKET},
+
        {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
                QUIRK_NO_MSI},
 
@@ -299,7 +303,7 @@ static const struct {
                QUIRK_NO_MSI},
 
        {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
-               QUIRK_CYCLE_TIMER},
+               QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
 
        {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
                QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
index 37c4bd1cacd579bfe66523bc5f371d00af1969b4..d0c41188d4e536b4983857de9c834913f1355c13 100644 (file)
@@ -87,6 +87,7 @@ config GPIO_GENERIC_PLATFORM
 
 config GPIO_IT8761E
        tristate "IT8761E GPIO support"
+       depends on X86  # unconditional access to IO space.
        help
          Say yes here to support GPIO functionality of IT8761E super I/O chip.
 
index 5b6948081f8fb3d953d5f95703ed6dac95f9e23d..ddfacc5ce56d55fce87d0131e535b27671ed5828 100644 (file)
@@ -96,7 +96,7 @@ static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
 };
 
 static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
-       "gpi000", "gpio01", "gpio02", "gpio03",
+       "gpio00", "gpio01", "gpio02", "gpio03",
        "gpio04", "gpio05"
 };
 
index 461958fc2264e91321a5bb80f7ba9cbed0a1a5bc..f0febe5b8221384c390711208c191a56cc2ee4f8 100644 (file)
@@ -248,7 +248,7 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
 static int ioh_irq_type(struct irq_data *d, unsigned int type)
 {
        u32 im;
-       u32 *im_reg;
+       void __iomem *im_reg;
        u32 ien;
        u32 im_pos;
        int ch;
@@ -412,7 +412,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
        int i, j;
        struct ioh_gpio *chip;
        void __iomem *base;
-       void __iomem *chip_save;
+       void *chip_save;
        int irq_base;
 
        ret = pci_enable_device(pdev);
@@ -428,7 +428,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
        }
 
        base = pci_iomap(pdev, 1, 0);
-       if (base == 0) {
+       if (!base) {
                dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
                ret = -ENOMEM;
                goto err_iomap;
@@ -448,6 +448,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
                chip->reg = chip->base;
                chip->ch = i;
                mutex_init(&chip->lock);
+               spin_lock_init(&chip->spinlock);
                ioh_gpio_setup(chip, num_ports[i]);
                ret = gpiochip_add(&chip->gpio);
                if (ret) {
@@ -521,7 +522,7 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
        int err;
        int i;
        struct ioh_gpio *chip = pci_get_drvdata(pdev);
-       void __iomem *chip_save;
+       void *chip_save;
 
        chip_save = chip;
 
index f0603297f829e787129f4bf0c34beb980a17f368..e8729cc2ba2b9f1dc864a17803252ef40b2adbfa 100644 (file)
@@ -231,7 +231,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)
 static int pch_irq_type(struct irq_data *d, unsigned int type)
 {
        u32 im;
-       u32 *im_reg;
+       u32 __iomem *im_reg;
        u32 ien;
        u32 im_pos;
        int ch;
@@ -376,7 +376,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
        }
 
        chip->base = pci_iomap(pdev, 1, 0);
-       if (chip->base == 0) {
+       if (!chip->base) {
                dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
                ret = -ENOMEM;
                goto err_iomap;
@@ -392,6 +392,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
        chip->reg = chip->base;
        pci_set_drvdata(pdev, chip);
        mutex_init(&chip->lock);
+       spin_lock_init(&chip->spinlock);
        pch_gpio_setup(chip);
        ret = gpiochip_add(&chip->gpio);
        if (ret) {
index a7661773c0525a43367de809c851053c78e6a186..0a79a1167a251dd71cd1c02dc82aedd1b1842213 100644 (file)
@@ -2387,27 +2387,30 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
 };
 
 #if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF)
-static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np,
-                             const void *gpio_spec, u32 *flags)
+static int exynos4_gpio_xlate(struct gpio_chip *gc,
+                       const struct of_phandle_args *gpiospec, u32 *flags)
 {
-       const __be32 *gpio = gpio_spec;
-       const u32 n = be32_to_cpup(gpio);
-       unsigned int pin = gc->base + be32_to_cpu(gpio[0]);
+       unsigned int pin;
 
        if (WARN_ON(gc->of_gpio_n_cells < 4))
                return -EINVAL;
 
-       if (n > gc->ngpio)
+       if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
                return -EINVAL;
 
-       if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1]))))
+       if (gpiospec->args[0] > gc->ngpio)
+               return -EINVAL;
+
+       pin = gc->base + gpiospec->args[0];
+
+       if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
                pr_warn("gpio_xlate: failed to set pin function\n");
-       if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2])))
+       if (s3c_gpio_setpull(pin, gpiospec->args[2]))
                pr_warn("gpio_xlate: failed to set pin pull up/down\n");
-       if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3])))
+       if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
                pr_warn("gpio_xlate: failed to set pin drive strength\n");
 
-       return n;
+       return gpiospec->args[0];
 }
 
 static const struct of_device_id exynos4_gpio_dt_match[] __initdata = {
index b9c1c297669e64a167a9257021a82d54e1f854c5..91f45b965d1e812d542e81d2c81ab6e60ae52843 100644 (file)
@@ -52,7 +52,7 @@ static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
        struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
 
        /* Set the initial value */
-       tps65910_gpio_set(gc, 0, value);
+       tps65910_gpio_set(gc, offset, value);
 
        return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
                                                GPIO_CFG_MASK);
index 3f46772f0cb212d5135ad686fbd20857e6b54a25..ba23790450e9d4877ec8721ed5280140a18272ea 100644 (file)
@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
  * Searches and unlinks the entry in drm_device::magiclist with the magic
  * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
 {
        struct drm_magic_entry *pt;
        struct drm_hash_item *hash;
@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
  * If there is a magic number in drm_file::magic then use it, otherwise
  * searches an unique non-zero magic number and add it associating it with \p
  * file_priv.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
  */
 int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
  * \return zero if authentication successed, or a negative number otherwise.
  *
  * Checks if \p file_priv is associated with the magic number passed in \arg.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
  */
 int drm_authmagic(struct drm_device *dev, void *data,
                  struct drm_file *file_priv)
index c00cf154cc0bbd81ce3c807fde6bffb2a5ff777f..6263b0147598de9688fcdfefb8a0dadc841f9ad9 100644 (file)
@@ -487,6 +487,11 @@ int drm_release(struct inode *inode, struct file *filp)
                  (long)old_encode_dev(file_priv->minor->device),
                  dev->open_count);
 
+       /* Release any auth tokens that might point to this file_priv,
+          (do that under the drm_global_mutex) */
+       if (file_priv->magic)
+               (void) drm_remove_magic(file_priv->master, file_priv->magic);
+
        /* if the master has gone away we can't do anything with the lock */
        if (file_priv->minor->master)
                drm_master_release(dev, filp);
index 396e60ce811467bc95117368517a302d51390611..f8625e2907288f590552183ff579a9c7aa756d40 100644 (file)
@@ -140,7 +140,7 @@ int drm_gem_object_init(struct drm_device *dev,
        obj->dev = dev;
        obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
        if (IS_ERR(obj->filp))
-               return -ENOMEM;
+               return PTR_ERR(obj->filp);
 
        kref_init(&obj->refcount);
        atomic_set(&obj->handle_count, 0);
index ddd70db45f7611747ee63551db2846d31383bc34..637fcc3766c7d706fb3ec0c6957d2d6f6c957568 100644 (file)
@@ -315,7 +315,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
        if (err)
                return err;
 
-       if (__get_user(c32.auth, &client->auth)
+       if (__get_user(c32.idx, &client->idx)
+           || __get_user(c32.auth, &client->auth)
            || __get_user(c32.pid, &client->pid)
            || __get_user(c32.uid, &client->uid)
            || __get_user(c32.magic, &client->magic)
index f9aaa56eae07c76575c090ac0ded6a086b215ca1..b9e5266c341baae491412e1fe75887c270b1fdb7 100644 (file)
@@ -13,7 +13,7 @@ config DRM_EXYNOS
 
 config DRM_EXYNOS_FIMD
        tristate "Exynos DRM FIMD"
-       depends on DRM_EXYNOS
+       depends on DRM_EXYNOS && !FB_S3C
        default n
        help
          Choose this option if you want to use Exynos FIMD for DRM.
@@ -21,7 +21,7 @@ config DRM_EXYNOS_FIMD
 
 config DRM_EXYNOS_HDMI
        tristate "Exynos DRM HDMI"
-       depends on DRM_EXYNOS
+       depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
        help
          Choose this option if you want to use Exynos HDMI for DRM.
          If M is selected, the module will be called exynos_drm_hdmi
index 661a03571d0c6ba672ea28b8fae172c2a7681a57..d08a55896d50adce1345902bbe8072c399179378 100644 (file)
@@ -193,6 +193,9 @@ int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
                        return err;
                }
 
+               /* setup possible_clones. */
+               exynos_drm_encoder_setup(drm_dev);
+
                /*
                 * if any specific driver such as fimd or hdmi driver called
                 * exynos_drm_subdrv_register() later than drm_load(),
index e3861ac492950b97773ceacbdc86557c2a914e08..de818831a51144393a6f237feb5d81077a1776bc 100644 (file)
@@ -307,9 +307,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
                 */
                event->pipe = exynos_crtc->pipe;
 
-               list_add_tail(&event->base.link,
-                               &dev_priv->pageflip_event_list);
-
                ret = drm_vblank_get(dev, exynos_crtc->pipe);
                if (ret) {
                        DRM_DEBUG("failed to acquire vblank counter\n");
@@ -318,6 +315,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
                        goto out;
                }
 
+               list_add_tail(&event->base.link,
+                               &dev_priv->pageflip_event_list);
+
                crtc->fb = fb;
                ret = exynos_drm_crtc_update(crtc);
                if (ret) {
index 35889ca255e93996f6cc37094a44147f756051f8..58820ebd35588f8b1e493234022b0e2132996369 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_encoder.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
@@ -99,6 +100,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto err_vblank;
 
+       /* setup possible_clones. */
+       exynos_drm_encoder_setup(dev);
+
        /*
         * create and configure fb helper and also exynos specific
         * fbdev object.
@@ -141,16 +145,21 @@ static int exynos_drm_unload(struct drm_device *dev)
 }
 
 static void exynos_drm_preclose(struct drm_device *dev,
-                                       struct drm_file *file_priv)
+                                       struct drm_file *file)
 {
-       struct exynos_drm_private *dev_priv = dev->dev_private;
+       DRM_DEBUG_DRIVER("%s\n", __FILE__);
 
-       /*
-        * drm framework frees all events at release time,
-        * so private event list should be cleared.
-        */
-       if (!list_empty(&dev_priv->pageflip_event_list))
-               INIT_LIST_HEAD(&dev_priv->pageflip_event_list);
+}
+
+static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
+{
+       DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+       if (!file->driver_priv)
+               return;
+
+       kfree(file->driver_priv);
+       file->driver_priv = NULL;
 }
 
 static void exynos_drm_lastclose(struct drm_device *dev)
@@ -195,6 +204,7 @@ static struct drm_driver exynos_drm_driver = {
        .unload                 = exynos_drm_unload,
        .preclose               = exynos_drm_preclose,
        .lastclose              = exynos_drm_lastclose,
+       .postclose              = exynos_drm_postclose,
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = exynos_drm_crtc_enable_vblank,
        .disable_vblank         = exynos_drm_crtc_disable_vblank,
index 86b93dde219a51a3a4e224fa800841ab76dcc92b..ef4754f1519bfbb4334b71c1372cc8d594526bd9 100644 (file)
@@ -195,6 +195,40 @@ static struct drm_encoder_funcs exynos_encoder_funcs = {
        .destroy = exynos_drm_encoder_destroy,
 };
 
+static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
+{
+       struct drm_encoder *clone;
+       struct drm_device *dev = encoder->dev;
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_display_ops *display_ops =
+                               exynos_encoder->manager->display_ops;
+       unsigned int clone_mask = 0;
+       int cnt = 0;
+
+       list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
+               switch (display_ops->type) {
+               case EXYNOS_DISPLAY_TYPE_LCD:
+               case EXYNOS_DISPLAY_TYPE_HDMI:
+                       clone_mask |= (1 << (cnt++));
+                       break;
+               default:
+                       continue;
+               }
+       }
+
+       return clone_mask;
+}
+
+void exynos_drm_encoder_setup(struct drm_device *dev)
+{
+       struct drm_encoder *encoder;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+               encoder->possible_clones = exynos_drm_encoder_clones(encoder);
+}
+
 struct drm_encoder *
 exynos_drm_encoder_create(struct drm_device *dev,
                           struct exynos_drm_manager *manager,
index 97b087a51cb6033a473716b687149c2e063e13e1..eb7d2316847edff9e4faa2940f241e9a19f8739c 100644 (file)
@@ -30,6 +30,7 @@
 
 struct exynos_drm_manager;
 
+void exynos_drm_encoder_setup(struct drm_device *dev);
 struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
                                               struct exynos_drm_manager *mgr,
                                               unsigned int possible_crtcs);
index d7ae29d2f3d68b0668f0979ade06e244e7ddf07c..3508700e529bbcd3c92c49a45be915ab885458d7 100644 (file)
@@ -195,66 +195,6 @@ out:
        return ret;
 }
 
-static bool
-exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb,
-                           struct drm_fb_helper_surface_size *sizes)
-{
-       if (fb->width != sizes->surface_width)
-               return false;
-       if (fb->height != sizes->surface_height)
-               return false;
-       if (fb->bits_per_pixel != sizes->surface_bpp)
-               return false;
-       if (fb->depth != sizes->surface_depth)
-               return false;
-
-       return true;
-}
-
-static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
-                                     struct drm_fb_helper_surface_size *sizes)
-{
-       struct drm_device *dev = helper->dev;
-       struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
-       struct exynos_drm_gem_obj *exynos_gem_obj;
-       struct drm_framebuffer *fb = helper->fb;
-       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-       unsigned long size;
-
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       if (exynos_drm_fbdev_is_samefb(fb, sizes))
-               return 0;
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3);
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                         sizes->surface_depth);
-
-       if (exynos_fbdev->exynos_gem_obj)
-               exynos_drm_gem_destroy(exynos_fbdev->exynos_gem_obj);
-
-       if (fb->funcs->destroy)
-               fb->funcs->destroy(fb);
-
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-       exynos_gem_obj = exynos_drm_gem_create(dev, size);
-       if (IS_ERR(exynos_gem_obj))
-               return PTR_ERR(exynos_gem_obj);
-
-       exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
-
-       helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
-                       &exynos_gem_obj->base);
-       if (IS_ERR_OR_NULL(helper->fb)) {
-               DRM_ERROR("failed to create drm framebuffer.\n");
-               return PTR_ERR(helper->fb);
-       }
-
-       return exynos_drm_fbdev_update(helper, helper->fb);
-}
-
 static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
                                   struct drm_fb_helper_surface_size *sizes)
 {
@@ -262,6 +202,10 @@ static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
+       /*
+        * with !helper->fb, it means that this funcion is called first time
+        * and after that, the helper->fb would be used as clone mode.
+        */
        if (!helper->fb) {
                ret = exynos_drm_fbdev_create(helper, sizes);
                if (ret < 0) {
@@ -274,12 +218,6 @@ static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
                 * because register_framebuffer() should be called.
                 */
                ret = 1;
-       } else {
-               ret = exynos_drm_fbdev_recreate(helper, sizes);
-               if (ret < 0) {
-                       DRM_ERROR("failed to reconfigure fbdev\n");
-                       return ret;
-               }
        }
 
        return ret;
index ca83139cd30997fcb2eb2d0df791e6bbea9df8ba..0dbb32bb18a359075f3421afea2f8ef856261dc9 100644 (file)
@@ -158,7 +158,8 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
-               pm_runtime_put_sync(subdrv_dev);
+               if (!ctx->suspended)
+                       pm_runtime_put_sync(subdrv_dev);
                break;
        default:
                DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -603,7 +604,12 @@ static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
        }
 
        if (is_checked) {
-               drm_vblank_put(drm_dev, crtc);
+               /*
+                * call drm_vblank_put only in case that drm_vblank_get was
+                * called.
+                */
+               if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
+                       drm_vblank_put(drm_dev, crtc);
 
                /*
                 * don't off vblank if vblank_disable_allowed is 1,
@@ -734,6 +740,46 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
        writel(val, ctx->regs + SHADOWCON);
 }
 
+static int fimd_power_on(struct fimd_context *ctx, bool enable)
+{
+       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+       struct device *dev = subdrv->manager.dev;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       if (enable != false && enable != true)
+               return -EINVAL;
+
+       if (enable) {
+               int ret;
+
+               ret = clk_enable(ctx->bus_clk);
+               if (ret < 0)
+                       return ret;
+
+               ret = clk_enable(ctx->lcd_clk);
+               if  (ret < 0) {
+                       clk_disable(ctx->bus_clk);
+                       return ret;
+               }
+
+               ctx->suspended = false;
+
+               /* if vblank was enabled status, enable it again. */
+               if (test_and_clear_bit(0, &ctx->irq_flags))
+                       fimd_enable_vblank(dev);
+
+               fimd_apply(dev);
+       } else {
+               clk_disable(ctx->lcd_clk);
+               clk_disable(ctx->bus_clk);
+
+               ctx->suspended = true;
+       }
+
+       return 0;
+}
+
 static int __devinit fimd_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -911,39 +957,30 @@ out:
 #ifdef CONFIG_PM_SLEEP
 static int fimd_suspend(struct device *dev)
 {
-       int ret;
+       struct fimd_context *ctx = get_fimd_context(dev);
 
        if (pm_runtime_suspended(dev))
                return 0;
 
-       ret = pm_runtime_suspend(dev);
-       if (ret < 0)
-               return ret;
-
-       return 0;
+       /*
+        * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
+        * called here, an error would be returned by that interface
+        * because the usage_count of pm runtime is more than 1.
+        */
+       return fimd_power_on(ctx, false);
 }
 
 static int fimd_resume(struct device *dev)
 {
-       int ret;
-
-       ret = pm_runtime_resume(dev);
-       if (ret < 0) {
-               DRM_ERROR("failed to resume runtime pm.\n");
-               return ret;
-       }
-
-       pm_runtime_disable(dev);
-
-       ret = pm_runtime_set_active(dev);
-       if (ret < 0) {
-               DRM_ERROR("failed to active runtime pm.\n");
-               pm_runtime_enable(dev);
-               pm_runtime_suspend(dev);
-               return ret;
-       }
+       struct fimd_context *ctx = get_fimd_context(dev);
 
-       pm_runtime_enable(dev);
+       /*
+        * if entered to sleep when lcd panel was on, the usage_count
+        * of pm runtime would still be 1 so in this case, fimd driver
+        * should be on directly not drawing on pm runtime interface.
+        */
+       if (!pm_runtime_suspended(dev))
+               return fimd_power_on(ctx, true);
 
        return 0;
 }
@@ -956,39 +993,16 @@ static int fimd_runtime_suspend(struct device *dev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       clk_disable(ctx->lcd_clk);
-       clk_disable(ctx->bus_clk);
-
-       ctx->suspended = true;
-       return 0;
+       return fimd_power_on(ctx, false);
 }
 
 static int fimd_runtime_resume(struct device *dev)
 {
        struct fimd_context *ctx = get_fimd_context(dev);
-       int ret;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ret = clk_enable(ctx->bus_clk);
-       if (ret < 0)
-               return ret;
-
-       ret = clk_enable(ctx->lcd_clk);
-       if  (ret < 0) {
-               clk_disable(ctx->bus_clk);
-               return ret;
-       }
-
-       ctx->suspended = false;
-
-       /* if vblank was enabled status, enable it again. */
-       if (test_and_clear_bit(0, &ctx->irq_flags))
-               fimd_enable_vblank(dev);
-
-       fimd_apply(dev);
-
-       return 0;
+       return fimd_power_on(ctx, true);
 }
 #endif
 
index f48f7ce92f5f5e37fd1aa208429d5c4395b9b354..3429d3fd93f3265d31cb3cad101b87eccc74964d 100644 (file)
@@ -1116,8 +1116,8 @@ err_ddc:
 err_iomap:
        iounmap(hdata->regs);
 err_req_region:
-       release_resource(hdata->regs_res);
-       kfree(hdata->regs_res);
+       release_mem_region(hdata->regs_res->start,
+                       resource_size(hdata->regs_res));
 err_resource:
        hdmi_resources_cleanup(hdata);
 err_data:
@@ -1145,8 +1145,8 @@ static int __devexit hdmi_remove(struct platform_device *pdev)
 
        iounmap(hdata->regs);
 
-       release_resource(hdata->regs_res);
-       kfree(hdata->regs_res);
+       release_mem_region(hdata->regs_res->start,
+                       resource_size(hdata->regs_res));
 
        /* hdmiphy i2c driver */
        i2c_del_driver(&hdmiphy_driver);
index ac24cff3977552694fe60ca59bf4382ee48520c2..93846e810e38c85c45f4a06d92e0f5306a89396e 100644 (file)
@@ -712,7 +712,12 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
        }
 
        if (is_checked)
-               drm_vblank_put(drm_dev, crtc);
+               /*
+                * call drm_vblank_put only in case that drm_vblank_get was
+                * called.
+                */
+               if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
+                       drm_vblank_put(drm_dev, crtc);
 
        spin_unlock_irqrestore(&drm_dev->event_lock, flags);
 }
@@ -779,15 +784,15 @@ static void mixer_win_reset(struct mixer_context *ctx)
        mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
                MXR_STATUS_BURST_MASK);
 
-       /* setting default layer priority: layer1 > video > layer0
+       /* setting default layer priority: layer1 > layer0 > video
         * because typical usage scenario would be
+        * layer1 - OSD
         * layer0 - framebuffer
         * video - video overlay
-        * layer1 - OSD
         */
-       val  = MXR_LAYER_CFG_GRP0_VAL(1);
-       val |= MXR_LAYER_CFG_VP_VAL(2);
-       val |= MXR_LAYER_CFG_GRP1_VAL(3);
+       val = MXR_LAYER_CFG_GRP1_VAL(3);
+       val |= MXR_LAYER_CFG_GRP0_VAL(2);
+       val |= MXR_LAYER_CFG_VP_VAL(1);
        mixer_reg_write(res, MXR_LAYER_CFG, val);
 
        /* setting background color */
@@ -1044,7 +1049,7 @@ static int mixer_remove(struct platform_device *pdev)
                                        platform_get_drvdata(pdev);
        struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx;
 
-       dev_info(dev, "remove sucessful\n");
+       dev_info(dev, "remove successful\n");
 
        mixer_resource_poweroff(ctx);
        mixer_resources_cleanup(ctx);
index 791c0ef1a65b0433ccedf258b59fdf986ddbdcd3..830dfdd6bf154a473e15357654cf4d19be8d6b81 100644 (file)
@@ -113,12 +113,12 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
 
 void psbfb_suspend(struct drm_device *dev)
 {
-       struct drm_framebuffer *fb = 0;
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
+       struct drm_framebuffer *fb;
 
        console_lock();
        mutex_lock(&dev->mode_config.mutex);
        list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+               struct psb_framebuffer *psbfb = to_psb_fb(fb);
                struct fb_info *info = psbfb->fbdev;
                fb_set_suspend(info, 1);
                drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
@@ -129,12 +129,12 @@ void psbfb_suspend(struct drm_device *dev)
 
 void psbfb_resume(struct drm_device *dev)
 {
-       struct drm_framebuffer *fb = 0;
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
+       struct drm_framebuffer *fb;
 
        console_lock();
        mutex_lock(&dev->mode_config.mutex);
        list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+               struct psb_framebuffer *psbfb = to_psb_fb(fb);
                struct fb_info *info = psbfb->fbdev;
                fb_set_suspend(info, 0);
                drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
index e770bd190a5c8a2efda446339805869944528a81..5d5330f667f14031512c022e12ed3d8eb61bc530 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <drm/drmP.h>
+#include <linux/shmem_fs.h>
 #include "psb_drv.h"
 
 
@@ -203,9 +204,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
        gt->npage = pages;
 
        for (i = 0; i < pages; i++) {
-               /* FIXME: needs updating as per mail from Hugh Dickins */
-               p = read_cache_page_gfp(mapping, i,
-                                       __GFP_COLD | GFP_KERNEL);
+               p = shmem_read_mapping_page(mapping, i);
                if (IS_ERR(p))
                        goto err;
                gt->pages[i] = p;
index f7c17b23983389ae7b978224180dadcd4b6616c3..7f4b4e10246ecfbb087ac825c1969b69dc9742c5 100644 (file)
@@ -886,7 +886,7 @@ static int i810_flush_queue(struct drm_device *dev)
 }
 
 /* Must be called with the lock held */
-void i810_driver_reclaim_buffers(struct drm_device *dev,
+static void i810_reclaim_buffers(struct drm_device *dev,
                                 struct drm_file *file_priv)
 {
        struct drm_device_dma *dma = dev->dma;
@@ -1223,17 +1223,12 @@ void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
                if (dev_priv->page_flipping)
                        i810_do_cleanup_pageflip(dev);
        }
+}
 
-       if (file_priv->master && file_priv->master->lock.hw_lock) {
-               drm_idlelock_take(&file_priv->master->lock);
-               i810_driver_reclaim_buffers(dev, file_priv);
-               drm_idlelock_release(&file_priv->master->lock);
-       } else {
-               /* master disappeared, clean up stuff anyway and hope nothing
-                * goes wrong */
-               i810_driver_reclaim_buffers(dev, file_priv);
-       }
-
+void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+                                       struct drm_file *file_priv)
+{
+       i810_reclaim_buffers(dev, file_priv);
 }
 
 int i810_driver_dma_quiescent(struct drm_device *dev)
index 053f1ee58393a885e6aff3d1b8e9c5de8f7c5cf5..ec12f7dc717a863ed7fcd17911aec55a1c486fce 100644 (file)
@@ -63,6 +63,7 @@ static struct drm_driver driver = {
        .lastclose = i810_driver_lastclose,
        .preclose = i810_driver_preclose,
        .device_is_agp = i810_driver_device_is_agp,
+       .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
        .dma_quiescent = i810_driver_dma_quiescent,
        .ioctls = i810_ioctls,
        .fops = &i810_driver_fops,
index 6e0acad9e0f556549621e7945a00d7cafd0abbac..c9339f48179551dacd84b03bd74bd327d4750d80 100644 (file)
@@ -116,12 +116,14 @@ typedef struct drm_i810_private {
 
                                /* i810_dma.c */
 extern int i810_driver_dma_quiescent(struct drm_device *dev);
-void i810_driver_reclaim_buffers(struct drm_device *dev,
-                                struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+                                              struct drm_file *file_priv);
 extern int i810_driver_load(struct drm_device *, unsigned long flags);
 extern void i810_driver_lastclose(struct drm_device *dev);
 extern void i810_driver_preclose(struct drm_device *dev,
                                 struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+                                              struct drm_file *file_priv);
 extern int i810_driver_device_is_agp(struct drm_device *dev);
 
 extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
index 11807989f918b351d0585e5e4a54b9d87c0a3125..deaa657292b45b910a81cd9a018baf81c1fce6dc 100644 (file)
@@ -121,11 +121,11 @@ static const char *cache_level_str(int type)
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
-       seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s%s",
+       seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s",
                   &obj->base,
                   get_pin_flag(obj),
                   get_tiling_flag(obj),
-                  obj->base.size,
+                  obj->base.size / 1024,
                   obj->base.read_domains,
                   obj->base.write_domain,
                   obj->last_rendering_seqno,
@@ -653,7 +653,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
        seq_printf(m, "  Size :    %08x\n", ring->size);
        seq_printf(m, "  Active :  %08x\n", intel_ring_get_active_head(ring));
        seq_printf(m, "  NOPID :   %08x\n", I915_READ_NOPID(ring));
-       if (IS_GEN6(dev)) {
+       if (IS_GEN6(dev) || IS_GEN7(dev)) {
                seq_printf(m, "  Sync 0 :   %08x\n", I915_READ_SYNC_0(ring));
                seq_printf(m, "  Sync 1 :   %08x\n", I915_READ_SYNC_1(ring));
        }
@@ -1075,6 +1075,7 @@ static int gen6_drpc_info(struct seq_file *m)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 rpmodectl1, gt_core_status, rcctl1;
+       unsigned forcewake_count;
        int count=0, ret;
 
 
@@ -1082,9 +1083,13 @@ static int gen6_drpc_info(struct seq_file *m)
        if (ret)
                return ret;
 
-       if (atomic_read(&dev_priv->forcewake_count)) {
-               seq_printf(m, "RC information inaccurate because userspace "
-                             "holds a reference \n");
+       spin_lock_irq(&dev_priv->gt_lock);
+       forcewake_count = dev_priv->forcewake_count;
+       spin_unlock_irq(&dev_priv->gt_lock);
+
+       if (forcewake_count) {
+               seq_printf(m, "RC information inaccurate because somebody "
+                             "holds a forcewake reference \n");
        } else {
                /* NB: we cannot use forcewake, else we read the wrong values */
                while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
@@ -1106,7 +1111,7 @@ static int gen6_drpc_info(struct seq_file *m)
        seq_printf(m, "SW control enabled: %s\n",
                   yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) ==
                          GEN6_RP_MEDIA_SW_MODE));
-       seq_printf(m, "RC6 Enabled: %s\n",
+       seq_printf(m, "RC1e Enabled: %s\n",
                   yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
        seq_printf(m, "RC6 Enabled: %s\n",
                   yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
@@ -1398,9 +1403,13 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned forcewake_count;
+
+       spin_lock_irq(&dev_priv->gt_lock);
+       forcewake_count = dev_priv->forcewake_count;
+       spin_unlock_irq(&dev_priv->gt_lock);
 
-       seq_printf(m, "forcewake count = %d\n",
-                  atomic_read(&dev_priv->forcewake_count));
+       seq_printf(m, "forcewake count = %u\n", forcewake_count);
 
        return 0;
 }
@@ -1665,7 +1674,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       if (!IS_GEN6(dev))
+       if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1682,7 +1691,7 @@ int i915_forcewake_release(struct inode *inode, struct file *file)
        struct drm_device *dev = inode->i_private;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (!IS_GEN6(dev))
+       if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
        /*
index 5f4d5893e98356ff8b657a3a3048858d8ba15fab..ddfe3d902b2a3a5d908b0c7664a4348f94ce3988 100644 (file)
@@ -2045,6 +2045,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!IS_I945G(dev) && !IS_I945GM(dev))
                pci_enable_msi(dev->pdev);
 
+       spin_lock_init(&dev_priv->gt_lock);
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->error_lock);
        spin_lock_init(&dev_priv->rps_lock);
index 8f7187915b0dea430f864baef322ac509c8106be..308f819135626c6b9c8d3805c953bd7a9ddf55dc 100644 (file)
@@ -368,11 +368,12 @@ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
  */
 void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
-       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+       unsigned long irqflags;
 
-       /* Forcewake is atomic in case we get in here without the lock */
-       if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+       if (dev_priv->forcewake_count++ == 0)
                dev_priv->display.force_wake_get(dev_priv);
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
 }
 
 void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
@@ -392,10 +393,12 @@ void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
  */
 void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
-       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+       unsigned long irqflags;
 
-       if (atomic_dec_and_test(&dev_priv->forcewake_count))
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+       if (--dev_priv->forcewake_count == 0)
                dev_priv->display.force_wake_put(dev_priv);
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
 }
 
 void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
@@ -597,9 +600,36 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags)
 static int gen6_do_reset(struct drm_device *dev, u8 flags)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int     ret;
+       unsigned long irqflags;
 
-       I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
-       return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+       /* Hold gt_lock across reset to prevent any register access
+        * with forcewake not set correctly
+        */
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+
+       /* Reset the chip */
+
+       /* GEN6_GDRST is not in the gt power well, no need to check
+        * for fifo space for the write or forcewake the chip for
+        * the read
+        */
+       I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
+
+       /* Spin waiting for the device to ack the reset request */
+       ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+
+       /* If reset with a user forcewake, try to restore, otherwise turn it off */
+       if (dev_priv->forcewake_count)
+               dev_priv->display.force_wake_get(dev_priv);
+       else
+               dev_priv->display.force_wake_put(dev_priv);
+
+       /* Restore fifo count */
+       dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
+       return ret;
 }
 
 /**
@@ -643,9 +673,6 @@ int i915_reset(struct drm_device *dev, u8 flags)
        case 7:
        case 6:
                ret = gen6_do_reset(dev, flags);
-               /* If reset with a user forcewake, try to restore */
-               if (atomic_read(&dev_priv->forcewake_count))
-                       __gen6_gt_force_wake_get(dev_priv);
                break;
        case 5:
                ret = ironlake_do_reset(dev, flags);
@@ -927,9 +954,14 @@ MODULE_LICENSE("GPL and additional rights");
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
        u##x val = 0; \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-               gen6_gt_force_wake_get(dev_priv); \
+               unsigned long irqflags; \
+               spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
+               if (dev_priv->forcewake_count == 0) \
+                       dev_priv->display.force_wake_get(dev_priv); \
                val = read##y(dev_priv->regs + reg); \
-               gen6_gt_force_wake_put(dev_priv); \
+               if (dev_priv->forcewake_count == 0) \
+                       dev_priv->display.force_wake_put(dev_priv); \
+               spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
        } else { \
                val = read##y(dev_priv->regs + reg); \
        } \
index 602bc80baabb982814dcce3640e13b53a638f09e..9689ca38b2b333f26c75e95421e773b3331bd81c 100644 (file)
@@ -288,7 +288,13 @@ typedef struct drm_i915_private {
        int relative_constants_mode;
 
        void __iomem *regs;
-       u32 gt_fifo_count;
+       /** gt_fifo_count and the subsequent register write are synchronized
+        * with dev->struct_mutex. */
+       unsigned gt_fifo_count;
+       /** forcewake_count is protected by gt_lock */
+       unsigned forcewake_count;
+       /** gt_lock is also taken in irq contexts. */
+       struct spinlock gt_lock;
 
        struct intel_gmbus {
                struct i2c_adapter adapter;
@@ -741,8 +747,6 @@ typedef struct drm_i915_private {
 
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
-
-       atomic_t forcewake_count;
 } drm_i915_private_t;
 
 enum i915_cache_level {
index 5d433fc11ace138748907b17cbb3a9932732b46b..5bd4361ea84dd2e5e4a0e39a6af249ccd7786573 100644 (file)
@@ -1751,7 +1751,8 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
                INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
        I915_WRITE(HWSTAM, 0xeffe);
-       if (IS_GEN6(dev) || IS_GEN7(dev)) {
+
+       if (IS_GEN6(dev)) {
                /* Workaround stalls observed on Sandy Bridge GPUs by
                 * making the blitter command streamer generate a
                 * write to the Hardware Status Page for
index c3afb783cb9d93bf7c79dd32a18d8627ed6bfd0d..03c53fcf86536ba110033931b8b979f3e4fd35f0 100644 (file)
 #define  DISP_TILE_SURFACE_SWIZZLING   (1<<13)
 #define  DISP_FBC_WM_DIS               (1<<15)
 
+/* GEN7 chicken */
+#define GEN7_COMMON_SLICE_CHICKEN1             0x7010
+# define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC     ((1<<10) | (1<<26))
+
+#define GEN7_L3CNTLREG1                                0xB01C
+#define  GEN7_WA_FOR_GEN7_L3_CONTROL                   0x3C4FFF8C
+
+#define GEN7_L3_CHICKEN_MODE_REGISTER          0xB030
+#define  GEN7_WA_L3_CHICKEN_MODE                               0x20000000
+
+/* WaCatErrorRejectionIssue */
+#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG         0x9030
+#define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB      (1<<11)
+
 /* PCH */
 
 /* south display engine interrupt */
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
 #define GEN6_UCGCTL2                           0x9404
+# define GEN6_RCZUNIT_CLOCK_GATE_DISABLE               (1 << 13)
 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
 # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE               (1 << 11)
 
index 7886e4fb60e3e23fb283461a690dbe43a928fc6e..2b5eb229ff2cc1c443d7f01039a4cc308201d211 100644 (file)
 #include "drm.h"
 #include "i915_drm.h"
 #include "intel_drv.h"
+#include "i915_reg.h"
 
 static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32     dpll_reg;
 
+       /* On IVB, 3rd pipe shares PLL with another one */
+       if (pipe > 1)
+               return false;
+
        if (HAS_PCH_SPLIT(dev))
-               dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
+               dpll_reg = PCH_DPLL(pipe);
        else
                dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
 
@@ -822,7 +827,7 @@ int i915_save_state(struct drm_device *dev)
 
        if (IS_IRONLAKE_M(dev))
                ironlake_disable_drps(dev);
-       if (IS_GEN6(dev))
+       if (INTEL_INFO(dev)->gen >= 6)
                gen6_disable_rps(dev);
 
        /* Cache mode state */
@@ -881,7 +886,7 @@ int i915_restore_state(struct drm_device *dev)
                intel_init_emon(dev);
        }
 
-       if (IS_GEN6(dev)) {
+       if (INTEL_INFO(dev)->gen >= 6) {
                gen6_enable_rps(dev_priv);
                gen6_update_ring_freq(dev_priv);
        }
index 8af3735e27c615506eb94a171bde35e7aebd36ef..dbda6e3bdf076697cee1d87616387c52d47efcdc 100644 (file)
@@ -467,8 +467,12 @@ struct edp_link_params {
 struct bdb_edp {
        struct edp_power_seq power_seqs[16];
        u32 color_depth;
-       u32 sdrrs_msa_timing_delay;
        struct edp_link_params link_params[16];
+       u32 sdrrs_msa_timing_delay;
+
+       /* ith bit indicates enabled/disabled for (i+1)th panel */
+       u16 edp_s3d_feature;
+       u16 edp_t3_optimization;
 } __attribute__ ((packed));
 
 void intel_setup_bios(struct drm_device *dev);
index fee0ad02c6d0f6563bc41a9fd91f6ebfdf076a18..dd729d46a61fb55a3caffb265cce9744cebd2e57 100644 (file)
@@ -24,6 +24,7 @@
  *     Eric Anholt <eric@anholt.net>
  */
 
+#include <linux/dmi.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include "drmP.h"
@@ -540,6 +541,24 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
        .destroy = intel_encoder_destroy,
 };
 
+static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
+{
+       DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident);
+       return 1;
+}
+
+static const struct dmi_system_id intel_no_crt[] = {
+       {
+               .callback = intel_no_crt_dmi_callback,
+               .ident = "ACER ZGB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+               },
+       },
+       { }
+};
+
 void intel_crt_init(struct drm_device *dev)
 {
        struct drm_connector *connector;
@@ -547,6 +566,10 @@ void intel_crt_init(struct drm_device *dev)
        struct intel_connector *intel_connector;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       /* Skip machines without VGA that falsely report hotplug events */
+       if (dmi_check_system(intel_no_crt))
+               return;
+
        crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
        if (!crt)
                return;
index 2a3f707caab8cc39b91e065071b60244da4d8ba6..f425b23e3803317f8088a7e2ffbb377e80cbd3f8 100644 (file)
@@ -1872,7 +1872,7 @@ static void intel_update_fbc(struct drm_device *dev)
        if (enable_fbc < 0) {
                DRM_DEBUG_KMS("fbc set to per-chip default\n");
                enable_fbc = 1;
-               if (INTEL_INFO(dev)->gen <= 5)
+               if (INTEL_INFO(dev)->gen <= 6)
                        enable_fbc = 0;
        }
        if (!enable_fbc) {
@@ -5307,6 +5307,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
+       pipeconf &= ~PIPECONF_INTERLACE_MASK;
        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
                pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
                /* the chip adds 2 halflines automatically */
@@ -5317,7 +5318,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                adjusted_mode->crtc_vsync_end -= 1;
                adjusted_mode->crtc_vsync_start -= 1;
        } else
-               pipeconf &= ~PIPECONF_INTERLACE_MASK; /* progressive */
+               pipeconf |= PIPECONF_PROGRESSIVE;
 
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
@@ -5808,12 +5809,15 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        if (is_lvds) {
                temp = I915_READ(PCH_LVDS);
                temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-               if (HAS_PCH_CPT(dev))
+               if (HAS_PCH_CPT(dev)) {
+                       temp &= ~PORT_TRANS_SEL_MASK;
                        temp |= PORT_TRANS_SEL_CPT(pipe);
-               else if (pipe == 1)
-                       temp |= LVDS_PIPEB_SELECT;
-               else
-                       temp &= ~LVDS_PIPEB_SELECT;
+               } else {
+                       if (pipe == 1)
+                               temp |= LVDS_PIPEB_SELECT;
+                       else
+                               temp &= ~LVDS_PIPEB_SELECT;
+               }
 
                /* set the corresponsding LVDS_BORDER bit */
                temp |= dev_priv->lvds_border_bits;
@@ -5899,6 +5903,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
+       pipeconf &= ~PIPECONF_INTERLACE_MASK;
        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
                pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
                /* the chip adds 2 halflines automatically */
@@ -5909,7 +5914,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                adjusted_mode->crtc_vsync_end -= 1;
                adjusted_mode->crtc_vsync_start -= 1;
        } else
-               pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
+               pipeconf |= PIPECONF_PROGRESSIVE;
 
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
@@ -8179,8 +8184,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
        I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
 
        if (intel_enable_rc6(dev_priv->dev))
-               rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
-                       GEN6_RC_CTL_RC6_ENABLE;
+               rc6_mask = GEN6_RC_CTL_RC6_ENABLE |
+                       (IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0;
 
        I915_WRITE(GEN6_RC_CONTROL,
                   rc6_mask |
@@ -8458,12 +8463,32 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
+       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        */
+       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
+
        I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
 
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
+       /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
+       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
+                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+       /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
+       I915_WRITE(GEN7_L3CNTLREG1,
+                       GEN7_WA_FOR_GEN7_L3_CONTROL);
+       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
+                       GEN7_WA_L3_CHICKEN_MODE);
+
+       /* This is required by WaCatErrorRejectionIssue */
+       I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+
        for_each_pipe(pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
@@ -9025,12 +9050,9 @@ void intel_modeset_init(struct drm_device *dev)
 
        for (i = 0; i < dev_priv->num_pipe; i++) {
                intel_crtc_init(dev, i);
-               if (HAS_PCH_SPLIT(dev)) {
-                       ret = intel_plane_init(dev, i);
-                       if (ret)
-                               DRM_ERROR("plane %d init failed: %d\n",
-                                         i, ret);
-               }
+               ret = intel_plane_init(dev, i);
+               if (ret)
+                       DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
        }
 
        /* Just disable it once at startup */
index db3b461ad4124babfa70f931a584cd433fb788ab..94f860cce3f748f4c89a080cc32b561cfd0fae40 100644 (file)
@@ -208,17 +208,8 @@ intel_dp_link_clock(uint8_t link_bw)
  */
 
 static int
-intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp)
+intel_dp_link_required(int pixel_clock, int bpp)
 {
-       struct drm_crtc *crtc = intel_dp->base.base.crtc;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int bpp = 24;
-
-       if (check_bpp)
-               bpp = check_bpp;
-       else if (intel_crtc)
-               bpp = intel_crtc->bpp;
-
        return (pixel_clock * bpp + 9) / 10;
 }
 
@@ -245,12 +236,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
                        return MODE_PANEL;
        }
 
-       mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0);
+       mode_rate = intel_dp_link_required(mode->clock, 24);
        max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
 
        if (mode_rate > max_rate) {
-                       mode_rate = intel_dp_link_required(intel_dp,
-                                                          mode->clock, 18);
+                       mode_rate = intel_dp_link_required(mode->clock, 18);
                        if (mode_rate > max_rate)
                                return MODE_CLOCK_HIGH;
                        else
@@ -683,7 +673,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
        int lane_count, clock;
        int max_lane_count = intel_dp_max_lane_count(intel_dp);
        int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
-       int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0;
+       int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
        static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
        if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
@@ -701,7 +691,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                for (clock = 0; clock <= max_clock; clock++) {
                        int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-                       if (intel_dp_link_required(intel_dp, mode->clock, bpp)
+                       if (intel_dp_link_required(mode->clock, bpp)
                                        <= link_avail) {
                                intel_dp->link_bw = bws[clock];
                                intel_dp->lane_count = lane_count;
index e44191132ac4e97307029e44a50d65e7a96be53a..aa84832b0e1ad1a06c2ded9766fff0e261278272 100644 (file)
@@ -692,6 +692,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+                .ident = "AOpen i45GMx-I",
+                .matches = {
+                        DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+                        DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
+                },
+        },
        {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Aopen i945GTt-VFA",
@@ -708,6 +716,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                },
        },
        {
+                .callback = intel_no_lvds_dmi_callback,
+                .ident = "Clientron E830",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
+                },
+        },
+        {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Asus EeeBox PC EB1007",
                .matches = {
index 77e729d4e4f02476b289aed344d344411c0eb2c1..1ab842c6032e949a37855a3995aa161d9f276977 100644 (file)
@@ -635,6 +635,19 @@ render_ring_add_request(struct intel_ring_buffer *ring,
        return 0;
 }
 
+static u32
+gen6_ring_get_seqno(struct intel_ring_buffer *ring)
+{
+       struct drm_device *dev = ring->dev;
+
+       /* Workaround to force correct ordering between irq and seqno writes on
+        * ivb (and maybe also on snb) by reading from a CS register (like
+        * ACTHD) before reading the status page. */
+       if (IS_GEN7(dev))
+               intel_ring_get_active_head(ring);
+       return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
 static u32
 ring_get_seqno(struct intel_ring_buffer *ring)
 {
@@ -791,17 +804,6 @@ ring_add_request(struct intel_ring_buffer *ring,
        return 0;
 }
 
-static bool
-gen7_blt_ring_get_irq(struct intel_ring_buffer *ring)
-{
-       /* The BLT ring on IVB appears to have broken synchronization
-        * between the seqno write and the interrupt, so that the
-        * interrupt appears first.  Returning false here makes
-        * i915_wait_request() do a polling loop, instead.
-        */
-       return false;
-}
-
 static bool
 gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
 {
@@ -811,6 +813,12 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
        if (!dev->irq_enabled)
               return false;
 
+       /* It looks like we need to prevent the gt from suspending while waiting
+        * for an notifiy irq, otherwise irqs seem to get lost on at least the
+        * blt/bsd rings on ivb. */
+       if (IS_GEN7(dev))
+               gen6_gt_force_wake_get(dev_priv);
+
        spin_lock(&ring->irq_lock);
        if (ring->irq_refcount++ == 0) {
                ring->irq_mask &= ~rflag;
@@ -835,6 +843,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
                ironlake_disable_irq(dev_priv, gflag);
        }
        spin_unlock(&ring->irq_lock);
+
+       if (IS_GEN7(dev))
+               gen6_gt_force_wake_put(dev_priv);
 }
 
 static bool
@@ -1341,7 +1352,7 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
        .write_tail             = gen6_bsd_ring_write_tail,
        .flush                  = gen6_ring_flush,
        .add_request            = gen6_add_request,
-       .get_seqno              = ring_get_seqno,
+       .get_seqno              = gen6_ring_get_seqno,
        .irq_get                = gen6_bsd_ring_get_irq,
        .irq_put                = gen6_bsd_ring_put_irq,
        .dispatch_execbuffer    = gen6_ring_dispatch_execbuffer,
@@ -1476,7 +1487,7 @@ static const struct intel_ring_buffer gen6_blt_ring = {
        .write_tail             = ring_write_tail,
        .flush                  = blt_ring_flush,
        .add_request            = gen6_add_request,
-       .get_seqno              = ring_get_seqno,
+       .get_seqno              = gen6_ring_get_seqno,
        .irq_get                = blt_ring_get_irq,
        .irq_put                = blt_ring_put_irq,
        .dispatch_execbuffer    = gen6_ring_dispatch_execbuffer,
@@ -1499,6 +1510,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
                ring->flush = gen6_render_ring_flush;
                ring->irq_get = gen6_render_ring_get_irq;
                ring->irq_put = gen6_render_ring_put_irq;
+               ring->get_seqno = gen6_ring_get_seqno;
        } else if (IS_GEN5(dev)) {
                ring->add_request = pc_render_add_request;
                ring->get_seqno = pc_render_get_seqno;
@@ -1577,8 +1589,5 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 
        *ring = gen6_blt_ring;
 
-       if (IS_GEN7(dev))
-               ring->irq_get = gen7_blt_ring_get_irq;
-
        return intel_init_ring_buffer(dev, ring);
 }
index f7b9268df2666831795835c1f378a93cf1340379..e334ec33a47d4eb0cbd731c0c834de6c2102c458 100644 (file)
@@ -1066,15 +1066,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 
        /* Set the SDVO control regs. */
        if (INTEL_INFO(dev)->gen >= 4) {
-               sdvox = 0;
+               /* The real mode polarity is set by the SDVO commands, using
+                * struct intel_sdvo_dtd. */
+               sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
                if (intel_sdvo->is_hdmi)
                        sdvox |= intel_sdvo->color_range;
                if (INTEL_INFO(dev)->gen < 5)
                        sdvox |= SDVO_BORDER_ENABLE;
-               if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-                       sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
-               if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-                       sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
        } else {
                sdvox = I915_READ(intel_sdvo->sdvo_reg);
                switch (intel_sdvo->sdvo_reg) {
index d13989fda50101f99c72cd00b23268b91027081c..2288abf88cce4e3420bbedc379747480aa8843e8 100644 (file)
@@ -466,10 +466,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        mutex_lock(&dev->struct_mutex);
 
        ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
-       if (ret) {
-               DRM_ERROR("failed to pin object\n");
+       if (ret)
                goto out_unlock;
-       }
 
        intel_plane->obj = obj;
 
@@ -632,10 +630,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
        unsigned long possible_crtcs;
        int ret;
 
-       if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
-               DRM_ERROR("new plane code only for SNB+\n");
+       if (!(IS_GEN6(dev) || IS_GEN7(dev)))
                return -ENODEV;
-       }
 
        intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
        if (!intel_plane)
index f3c6a9a8b081ae8f06734af32535433db67f5d12..1571be37ce3e36b1089994a3454c4a23f8a733e6 100644 (file)
@@ -417,7 +417,7 @@ static const struct tv_mode tv_modes[] = {
        {
                .name           = "NTSC-M",
                .clock          = 108000,
-               .refresh        = 29970,
+               .refresh        = 59940,
                .oversample     = TV_OVERSAMPLE_8X,
                .component_only = 0,
                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
@@ -460,7 +460,7 @@ static const struct tv_mode tv_modes[] = {
        {
                .name           = "NTSC-443",
                .clock          = 108000,
-               .refresh        = 29970,
+               .refresh        = 59940,
                .oversample     = TV_OVERSAMPLE_8X,
                .component_only = 0,
                /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
@@ -502,7 +502,7 @@ static const struct tv_mode tv_modes[] = {
        {
                .name           = "NTSC-J",
                .clock          = 108000,
-               .refresh        = 29970,
+               .refresh        = 59940,
                .oversample     = TV_OVERSAMPLE_8X,
                .component_only = 0,
 
@@ -545,7 +545,7 @@ static const struct tv_mode tv_modes[] = {
        {
                .name           = "PAL-M",
                .clock          = 108000,
-               .refresh        = 29970,
+               .refresh        = 59940,
                .oversample     = TV_OVERSAMPLE_8X,
                .component_only = 0,
 
@@ -589,7 +589,7 @@ static const struct tv_mode tv_modes[] = {
                /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
                .name       = "PAL-N",
                .clock          = 108000,
-               .refresh        = 25000,
+               .refresh        = 50000,
                .oversample     = TV_OVERSAMPLE_8X,
                .component_only = 0,
 
@@ -634,7 +634,7 @@ static const struct tv_mode tv_modes[] = {
                /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
                .name       = "PAL",
                .clock          = 108000,
-               .refresh        = 25000,
+               .refresh        = 50000,
                .oversample     = TV_OVERSAMPLE_8X,
                .component_only = 0,
 
@@ -673,78 +673,6 @@ static const struct tv_mode tv_modes[] = {
 
                .filter_table = filter_table,
        },
-       {
-               .name       = "480p@59.94Hz",
-               .clock          = 107520,
-               .refresh        = 59940,
-               .oversample     = TV_OVERSAMPLE_4X,
-               .component_only = 1,
-
-               .hsync_end      = 64,               .hblank_end         = 122,
-               .hblank_start   = 842,              .htotal             = 857,
-
-               .progressive    = true,             .trilevel_sync = false,
-
-               .vsync_start_f1 = 12,               .vsync_start_f2     = 12,
-               .vsync_len      = 12,
-
-               .veq_ena        = false,
-
-               .vi_end_f1      = 44,               .vi_end_f2          = 44,
-               .nbr_end        = 479,
-
-               .burst_ena      = false,
-
-               .filter_table = filter_table,
-       },
-       {
-               .name       = "480p@60Hz",
-               .clock          = 107520,
-               .refresh        = 60000,
-               .oversample     = TV_OVERSAMPLE_4X,
-               .component_only = 1,
-
-               .hsync_end      = 64,               .hblank_end         = 122,
-               .hblank_start   = 842,              .htotal             = 856,
-
-               .progressive    = true,             .trilevel_sync = false,
-
-               .vsync_start_f1 = 12,               .vsync_start_f2     = 12,
-               .vsync_len      = 12,
-
-               .veq_ena        = false,
-
-               .vi_end_f1      = 44,               .vi_end_f2          = 44,
-               .nbr_end        = 479,
-
-               .burst_ena      = false,
-
-               .filter_table = filter_table,
-       },
-       {
-               .name       = "576p",
-               .clock          = 107520,
-               .refresh        = 50000,
-               .oversample     = TV_OVERSAMPLE_4X,
-               .component_only = 1,
-
-               .hsync_end      = 64,               .hblank_end         = 139,
-               .hblank_start   = 859,              .htotal             = 863,
-
-               .progressive    = true,         .trilevel_sync = false,
-
-               .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
-               .vsync_len      = 10,
-
-               .veq_ena        = false,
-
-               .vi_end_f1      = 48,               .vi_end_f2          = 48,
-               .nbr_end        = 575,
-
-               .burst_ena      = false,
-
-               .filter_table = filter_table,
-       },
        {
                .name       = "720p@60Hz",
                .clock          = 148800,
@@ -769,30 +697,6 @@ static const struct tv_mode tv_modes[] = {
 
                .filter_table = filter_table,
        },
-       {
-               .name       = "720p@59.94Hz",
-               .clock          = 148800,
-               .refresh        = 59940,
-               .oversample     = TV_OVERSAMPLE_2X,
-               .component_only = 1,
-
-               .hsync_end      = 80,               .hblank_end         = 300,
-               .hblank_start   = 1580,             .htotal             = 1651,
-
-               .progressive    = true,             .trilevel_sync = true,
-
-               .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
-               .vsync_len      = 10,
-
-               .veq_ena        = false,
-
-               .vi_end_f1      = 29,               .vi_end_f2          = 29,
-               .nbr_end        = 719,
-
-               .burst_ena      = false,
-
-               .filter_table = filter_table,
-       },
        {
                .name       = "720p@50Hz",
                .clock          = 148800,
@@ -821,7 +725,7 @@ static const struct tv_mode tv_modes[] = {
        {
                .name       = "1080i@50Hz",
                .clock          = 148800,
-               .refresh        = 25000,
+               .refresh        = 50000,
                .oversample     = TV_OVERSAMPLE_2X,
                .component_only = 1,
 
@@ -847,7 +751,7 @@ static const struct tv_mode tv_modes[] = {
        {
                .name       = "1080i@60Hz",
                .clock          = 148800,
-               .refresh        = 30000,
+               .refresh        = 60000,
                .oversample     = TV_OVERSAMPLE_2X,
                .component_only = 1,
 
@@ -868,32 +772,6 @@ static const struct tv_mode tv_modes[] = {
 
                .burst_ena      = false,
 
-               .filter_table = filter_table,
-       },
-       {
-               .name       = "1080i@59.94Hz",
-               .clock          = 148800,
-               .refresh        = 29970,
-               .oversample     = TV_OVERSAMPLE_2X,
-               .component_only = 1,
-
-               .hsync_end      = 88,               .hblank_end         = 235,
-               .hblank_start   = 2155,             .htotal             = 2201,
-
-               .progressive    = false,            .trilevel_sync = true,
-
-               .vsync_start_f1 = 4,            .vsync_start_f2    = 5,
-               .vsync_len      = 10,
-
-               .veq_ena        = true,             .veq_start_f1       = 4,
-               .veq_start_f2   = 4,            .veq_len          = 10,
-
-
-               .vi_end_f1      = 21,           .vi_end_f2        = 22,
-               .nbr_end        = 539,
-
-               .burst_ena      = false,
-
                .filter_table = filter_table,
        },
 };
index 1e382ad5a2b85b04fb6f8b0953fe793eee44f615..a37c31e358aa40eb9a6e618c9c59459b8233329b 100644 (file)
@@ -54,9 +54,10 @@ struct bit_entry {
 int bit_table(struct drm_device *, u8 id, struct bit_entry *);
 
 enum dcb_gpio_tag {
-       DCB_GPIO_TVDAC0 = 0xc,
+       DCB_GPIO_PANEL_POWER = 0x01,
+       DCB_GPIO_TVDAC0 = 0x0c,
        DCB_GPIO_TVDAC1 = 0x2d,
-       DCB_GPIO_PWM_FAN = 0x9,
+       DCB_GPIO_PWM_FAN = 0x09,
        DCB_GPIO_FAN_SENSE = 0x3d,
        DCB_GPIO_UNUSED = 0xff
 };
index 724b41a2b9e9414b27ef6c4ea347a116657c9026..ec54364ac828f1bd69c13e42cf50507db5e913f6 100644 (file)
@@ -812,6 +812,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct nouveau_vma *vma;
 
+       /* ttm can now (stupidly) pass the driver bos it didn't create... */
+       if (bo->destroy != nouveau_bo_del_ttm)
+               return;
+
        list_for_each_entry(vma, &nvbo->vma_list, head) {
                if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
                        nouveau_vm_map(vma, new_mem->mm_node);
index 3cb52bc52b21101bbdf0a136b1cd4c2a639fb79e..795a9e3c990a0cba3599b5c754f33adf8e15da93 100644 (file)
@@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev)
        if (ret)
                return ret;
 
+       /* power on internal panel if it's not already.  the init tables of
+        * some vbios default this to off for some reason, causing the
+        * panel to not work after resume
+        */
+       if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) {
+               nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true);
+               msleep(300);
+       }
+
+       /* enable polling for external displays */
        drm_kms_helper_poll_enable(dev);
 
        /* enable hotplug interrupts */
index e4a7cfe7898dc455fa4e423828a73ff162ee4ecc..81d7962e7252cd8f8a819e881fd5430e3f495ff1 100644 (file)
@@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
 int nouveau_ctxfw;
 module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
 
-MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n");
+MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n");
 int nouveau_mxmdcb = 1;
 module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
 
index 5f0bc57fdaab5e14f1c3bc9f6e049f02c43a5069..7ce3fde4074312948e39c902fb4ca239c8e5a733 100644 (file)
@@ -379,6 +379,25 @@ retry:
        return 0;
 }
 
+static int
+validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
+{
+       struct nouveau_fence *fence = NULL;
+       int ret = 0;
+
+       spin_lock(&nvbo->bo.bdev->fence_lock);
+       if (nvbo->bo.sync_obj)
+               fence = nouveau_fence_ref(nvbo->bo.sync_obj);
+       spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+       if (fence) {
+               ret = nouveau_fence_sync(fence, chan);
+               nouveau_fence_unref(&fence);
+       }
+
+       return ret;
+}
+
 static int
 validate_list(struct nouveau_channel *chan, struct list_head *list,
              struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
@@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
        list_for_each_entry(nvbo, list, entry) {
                struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
 
-               ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+               ret = validate_sync(chan, nvbo);
                if (unlikely(ret)) {
                        NV_ERROR(dev, "fail pre-validate sync\n");
                        return ret;
@@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
                        return ret;
                }
 
-               ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+               ret = validate_sync(chan, nvbo);
                if (unlikely(ret)) {
                        NV_ERROR(dev, "fail post-validate sync\n");
                        return ret;
index 8bccddf4eff0011e9ad2e330b0ae8163270c2470..e5a64f0f4cb74538f41e121d19b459395be4ce05 100644 (file)
@@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev)
 
        if (mxm_shadow(dev, mxm[0])) {
                MXM_MSG(dev, "failed to locate valid SIS\n");
+#if 0
+               /* we should, perhaps, fall back to some kind of limited
+                * mode here if the x86 vbios hasn't already done the
+                * work for us (so we prevent loading with completely
+                * whacked vbios tables).
+                */
                return -EINVAL;
+#else
+               return 0;
+#endif
        }
 
        MXM_MSG(dev, "MXMS Version %d.%d\n",
index 03937212e9d81c97a3595e269cadc13c0f4eea97..ec5481dfcd82ed9ce3aaca764ac0471bfb9eb52f 100644 (file)
@@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nv50_pm_state *info;
        struct pll_lims pll;
-       int ret = -EINVAL;
+       int clk, ret = -EINVAL;
        int N, M, P1, P2;
-       u32 clk, out;
+       u32 out;
 
        if (dev_priv->chipset == 0xaa ||
            dev_priv->chipset == 0xac)
index 0fda830ef806eb6e5c9b346586a852e818609dd1..742f17f009a966868179d046dd17390950778b81 100644 (file)
@@ -355,15 +355,12 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-static void atombios_disable_ss(struct drm_crtc *crtc)
+static void atombios_disable_ss(struct radeon_device *rdev, int pll_id)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
        u32 ss_cntl;
 
        if (ASIC_IS_DCE4(rdev)) {
-               switch (radeon_crtc->pll_id) {
+               switch (pll_id) {
                case ATOM_PPLL1:
                        ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);
                        ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
@@ -379,7 +376,7 @@ static void atombios_disable_ss(struct drm_crtc *crtc)
                        return;
                }
        } else if (ASIC_IS_AVIVO(rdev)) {
-               switch (radeon_crtc->pll_id) {
+               switch (pll_id) {
                case ATOM_PPLL1:
                        ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
                        ss_cntl &= ~1;
@@ -406,13 +403,11 @@ union atom_enable_ss {
        ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;
 };
 
-static void atombios_crtc_program_ss(struct drm_crtc *crtc,
+static void atombios_crtc_program_ss(struct radeon_device *rdev,
                                     int enable,
                                     int pll_id,
                                     struct radeon_atom_ss *ss)
 {
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
        int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
        union atom_enable_ss args;
 
@@ -479,7 +474,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
        } else if (ASIC_IS_AVIVO(rdev)) {
                if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
                    (ss->type & ATOM_EXTERNAL_SS_MASK)) {
-                       atombios_disable_ss(crtc);
+                       atombios_disable_ss(rdev, pll_id);
                        return;
                }
                args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
@@ -491,7 +486,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
        } else {
                if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
                    (ss->type & ATOM_EXTERNAL_SS_MASK)) {
-                       atombios_disable_ss(crtc);
+                       atombios_disable_ss(rdev, pll_id);
                        return;
                }
                args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
@@ -523,6 +518,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
        int encoder_mode = 0;
        u32 dp_clock = mode->clock;
        int bpc = 8;
+       bool is_duallink = false;
 
        /* reset the pll flags */
        pll->flags = 0;
@@ -557,6 +553,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                        if (connector && connector->display_info.bpc)
                                bpc = connector->display_info.bpc;
                        encoder_mode = atombios_get_encoder_mode(encoder);
+                       is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
                        if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
                            (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
                                if (connector) {
@@ -652,7 +649,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        if (dig->coherent_mode)
                                                args.v3.sInput.ucDispPllConfig |=
                                                        DISPPLL_CONFIG_COHERENT_MODE;
-                                       if (mode->clock > 165000)
+                                       if (is_duallink)
                                                args.v3.sInput.ucDispPllConfig |=
                                                        DISPPLL_CONFIG_DUAL_LINK;
                                }
@@ -702,11 +699,9 @@ union set_pixel_clock {
 /* on DCE5, make sure the voltage is high enough to support the
  * required disp clk.
  */
-static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
+static void atombios_crtc_set_dcpll(struct radeon_device *rdev,
                                    u32 dispclk)
 {
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
        u8 frev, crev;
        int index;
        union set_pixel_clock args;
@@ -996,7 +991,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
                                          &ref_div, &post_div);
 
-       atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
+       atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
 
        atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
                                  encoder_mode, radeon_encoder->encoder_id, mode->clock,
@@ -1019,7 +1014,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                        ss.step = step_size;
                }
 
-               atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
+               atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
        }
 }
 
@@ -1189,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
        WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
-              crtc->mode.vdisplay);
+              target_fb->height);
        x &= ~3;
        y &= ~1;
        WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1358,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
        WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
-              crtc->mode.vdisplay);
+              target_fb->height);
        x &= ~3;
        y &= ~1;
        WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1494,6 +1489,24 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
 
 }
 
+void radeon_atom_dcpll_init(struct radeon_device *rdev)
+{
+       /* always set DCPLL */
+       if (ASIC_IS_DCE4(rdev)) {
+               struct radeon_atom_ss ss;
+               bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
+                                                                  ASIC_INTERNAL_SS_ON_DCPLL,
+                                                                  rdev->clock.default_dispclk);
+               if (ss_enabled)
+                       atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss);
+               /* XXX: DCE5, make sure voltage, dispclk is high enough */
+               atombios_crtc_set_dcpll(rdev, rdev->clock.default_dispclk);
+               if (ss_enabled)
+                       atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss);
+       }
+
+}
+
 int atombios_crtc_mode_set(struct drm_crtc *crtc,
                           struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode,
@@ -1515,19 +1528,6 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
-       /* always set DCPLL */
-       if (ASIC_IS_DCE4(rdev)) {
-               struct radeon_atom_ss ss;
-               bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
-                                                                  ASIC_INTERNAL_SS_ON_DCPLL,
-                                                                  rdev->clock.default_dispclk);
-               if (ss_enabled)
-                       atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss);
-               /* XXX: DCE5, make sure voltage, dispclk is high enough */
-               atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk);
-               if (ss_enabled)
-                       atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss);
-       }
        atombios_crtc_set_pll(crtc, adjusted_mode);
 
        if (ASIC_IS_DCE4(rdev))
index 6fb335a4fddafee8bdf3bfc0bbe48e54df265106..552b436451fd49d54df3edb412a63734debad250 100644 (file)
@@ -549,8 +549,8 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
        return false;
 }
 
-static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
-                                    struct drm_connector *connector)
+int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
+                            struct drm_connector *connector)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
@@ -558,28 +558,33 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
        int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
 
        if (!ASIC_IS_DCE4(rdev))
-               return;
+               return panel_mode;
 
        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) {
+                ENCODER_OBJECT_ID_TRAVIS) {
+               u8 id[6];
+               int i;
+               for (i = 0; i < 6; i++)
+                       id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
+               if (id[0] == 0x73 &&
+                   id[1] == 0x69 &&
+                   id[2] == 0x76 &&
+                   id[3] == 0x61 &&
+                   id[4] == 0x72 &&
+                   id[5] == 0x54)
+                       panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+               else
+                       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);
-       }
+       return panel_mode;
 }
 
 void radeon_dp_set_link_config(struct drm_connector *connector,
@@ -717,6 +722,8 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
 
 static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
 {
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder);
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        u8 tmp;
 
        /* power up the sink */
@@ -732,7 +739,10 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
                radeon_write_dpcd_reg(dp_info->radeon_connector,
                                      DP_DOWNSPREAD_CTRL, 0);
 
-       radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector);
+       if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
+           (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
+               radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+       }
 
        /* set the lane count on the sink */
        tmp = dp_info->dp_lane_count;
index f1f06ca9f1f533fc89179c5109a60ca9af4f5ebb..b88c4608731becef4b196d706960c84e3a58917c 100644 (file)
@@ -57,22 +57,6 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
        }
 }
 
-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)
@@ -253,7 +237,7 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action)
                        /* R4xx, R5xx */
                        args.ext_tmds.sXTmdsEncoder.ucEnable = action;
 
-                       if (radeon_encoder->pixel_clock > 165000)
+                       if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
 
                        args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
@@ -265,7 +249,7 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action)
                        /* DFP1, CRT1, TV1 depending on the type of port */
                        args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
 
-                       if (radeon_encoder->pixel_clock > 165000)
+                       if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
                        break;
                case 3:
@@ -349,7 +333,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                        } else {
                                if (dig->linkb)
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-                               if (radeon_encoder->pixel_clock > 165000)
+                               if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
                                /*if (pScrn->rgbBits == 8) */
                                args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
@@ -388,7 +372,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                        } else {
                                if (dig->linkb)
                                        args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-                               if (radeon_encoder->pixel_clock > 165000)
+                               if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
                        }
                        break;
@@ -432,7 +416,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        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) &&
+               if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
                    radeon_audio)
                        return ATOM_ENCODER_MODE_HDMI;
                else if (radeon_connector->use_digital)
@@ -443,7 +427,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_DVID:
        case DRM_MODE_CONNECTOR_HDMIA:
        default:
-               if (drm_detect_monitor_audio(radeon_connector->edid) &&
+               if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
                    radeon_audio)
                        return ATOM_ENCODER_MODE_HDMI;
                else
@@ -457,7 +441,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                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) &&
+               else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
                         radeon_audio)
                        return ATOM_ENCODER_MODE_HDMI;
                else
@@ -587,7 +571,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
 
                        if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
                                args.v1.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v1.ucLaneNum = 8;
                        else
                                args.v1.ucLaneNum = 4;
@@ -622,7 +606,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
 
                        if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
                                args.v3.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v3.ucLaneNum = 8;
                        else
                                args.v3.ucLaneNum = 4;
@@ -662,7 +646,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
 
                        if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
                                args.v4.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v4.ucLaneNum = 8;
                        else
                                args.v4.ucLaneNum = 4;
@@ -806,7 +790,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                                if (is_dp)
                                        args.v1.usPixelClock =
                                                cpu_to_le16(dp_clock / 10);
-                               else if (radeon_encoder->pixel_clock > 165000)
+                               else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
                                else
                                        args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -821,7 +805,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
 
                        if ((rdev->flags & RADEON_IS_IGP) &&
                            (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
-                               if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+                               if (is_dp ||
+                                   !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
                                        if (igp_lane_info & 0x1)
                                                args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
                                        else if (igp_lane_info & 0x2)
@@ -848,7 +833,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        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)
+                               if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
                        }
                        break;
@@ -863,7 +848,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                                if (is_dp)
                                        args.v2.usPixelClock =
                                                cpu_to_le16(dp_clock / 10);
-                               else if (radeon_encoder->pixel_clock > 165000)
+                               else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
                                else
                                        args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -891,7 +876,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                                if (dig->coherent_mode)
                                        args.v2.acConfig.fCoherentMode = 1;
-                               if (radeon_encoder->pixel_clock > 165000)
+                               if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v2.acConfig.fDualLinkConnector = 1;
                        }
                        break;
@@ -906,7 +891,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                                if (is_dp)
                                        args.v3.usPixelClock =
                                                cpu_to_le16(dp_clock / 10);
-                               else if (radeon_encoder->pixel_clock > 165000)
+                               else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
                                else
                                        args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -914,7 +899,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
 
                        if (is_dp)
                                args.v3.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v3.ucLaneNum = 8;
                        else
                                args.v3.ucLaneNum = 4;
@@ -951,7 +936,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                                if (dig->coherent_mode)
                                        args.v3.acConfig.fCoherentMode = 1;
-                               if (radeon_encoder->pixel_clock > 165000)
+                               if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v3.acConfig.fDualLinkConnector = 1;
                        }
                        break;
@@ -966,7 +951,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                                if (is_dp)
                                        args.v4.usPixelClock =
                                                cpu_to_le16(dp_clock / 10);
-                               else if (radeon_encoder->pixel_clock > 165000)
+                               else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
                                else
                                        args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -974,7 +959,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
 
                        if (is_dp)
                                args.v4.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v4.ucLaneNum = 8;
                        else
                                args.v4.ucLaneNum = 4;
@@ -1014,7 +999,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                                if (dig->coherent_mode)
                                        args.v4.acConfig.fCoherentMode = 1;
-                               if (radeon_encoder->pixel_clock > 165000)
+                               if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                        args.v4.acConfig.fDualLinkConnector = 1;
                        }
                        break;
@@ -1137,7 +1122,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
                                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)
+                       } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v1.sDigEncoder.ucLaneNum = 8;
                        else
                                args.v1.sDigEncoder.ucLaneNum = 4;
@@ -1156,7 +1141,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
                                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)
+                       } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v3.sExtEncoder.ucLaneNum = 8;
                        else
                                args.v3.sExtEncoder.ucLaneNum = 4;
@@ -1341,7 +1326,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        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))
+               if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) ||
+                   ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                else
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
@@ -1351,8 +1337,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                                             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);
@@ -1363,7 +1347,10 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        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 (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+               else
+                       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);
@@ -1810,7 +1797,21 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               if (ASIC_IS_DCE4(rdev)) {
+               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+                       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+                       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+                       if (!connector)
+                               dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+                       else
+                               dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
+
+                       /* setup and enable the encoder */
+                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+                       atombios_dig_encoder_setup(encoder,
+                                                  ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
+                                                  dig->panel_mode);
+               } else if (ASIC_IS_DCE4(rdev)) {
                        /* disable the transmitter */
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
                        /* setup and enable the encoder */
index 636660fca8c246f9e65205fcae1ca379e180131c..f58254a3fb01cd23e5ec6c86d7eb09a11cf3bf15 100644 (file)
@@ -1455,6 +1455,7 @@ int evergreen_cp_resume(struct radeon_device *rdev)
 #endif
        WREG32(CP_RB_CNTL, tmp);
        WREG32(CP_SEM_WAIT_TIMER, 0x0);
+       WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
 
        /* Set the write pointer delay */
        WREG32(CP_RB_WPTR_DELAY, 0);
@@ -3190,6 +3191,7 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r) {
                DRM_ERROR("radeon: failed testing IB (%d).\n", r);
                rdev->accel_working = false;
+               return r;
        }
 
        r = r600_audio_init(rdev);
@@ -3221,6 +3223,7 @@ int evergreen_resume(struct radeon_device *rdev)
        r = evergreen_startup(rdev);
        if (r) {
                DRM_ERROR("evergreen startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
 
index b502216d42afdc4638362bceec578adfdf998720..74713d42df296d32db965c7398d47bc8edc566c4 100644 (file)
 #define        CP_RB_WPTR_ADDR_HI                              0xC11C
 #define        CP_RB_WPTR_DELAY                                0x8704
 #define        CP_SEM_WAIT_TIMER                               0x85BC
+#define        CP_SEM_INCOMPLETE_TIMER_CNTL                    0x85C8
 #define        CP_DEBUG                                        0xC1FC
 
 
index 32113729540069f22ce31ffa18e23c7ccc290159..2509c505acb896a51e370f3078ee660b61cabe1d 100644 (file)
@@ -1219,6 +1219,7 @@ int cayman_cp_resume(struct radeon_device *rdev)
        RREG32(GRBM_SOFT_RESET);
 
        WREG32(CP_SEM_WAIT_TIMER, 0x0);
+       WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
 
        /* Set the write pointer delay */
        WREG32(CP_RB_WPTR_DELAY, 0);
@@ -1546,6 +1547,7 @@ int cayman_resume(struct radeon_device *rdev)
        r = cayman_startup(rdev);
        if (r) {
                DRM_ERROR("cayman startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
        return r;
index f9df2a645e79caeeab62396e71222b89026e6f8e..9a7f3b6e02de38acc1655b9e74fae3d5dac91448 100644 (file)
 #define        SCRATCH_UMSK                                    0x8540
 #define        SCRATCH_ADDR                                    0x8544
 #define        CP_SEM_WAIT_TIMER                               0x85BC
+#define        CP_SEM_INCOMPLETE_TIMER_CNTL                    0x85C8
 #define        CP_COHER_CNTL2                                  0x85E8
 #define CP_ME_CNTL                                     0x86D8
 #define                CP_ME_HALT                                      (1 << 28)
index bfd36ab643a68a5dea2b43d24283d08a0a2eb703..333cde9d4e7b7621ab1713ee54e1a418017d7786 100644 (file)
@@ -789,9 +789,7 @@ int r100_irq_process(struct radeon_device *rdev)
                        WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM);
                        break;
                default:
-                       msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
-                       WREG32(RADEON_MSI_REARM_EN, msi_rearm);
-                       WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+                       WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
                        break;
                }
        }
@@ -3930,6 +3928,8 @@ static int r100_startup(struct radeon_device *rdev)
 
 int r100_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCI)
                r100_pci_gart_disable(rdev);
@@ -3949,7 +3949,11 @@ int r100_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return r100_startup(rdev);
+       r = r100_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int r100_suspend(struct radeon_device *rdev)
index 3fc0d29a5f39e439e398a0f1e693a0e19b705c73..6829638cca4032810822d5eb766d61f0f7658ee3 100644 (file)
@@ -1431,6 +1431,8 @@ static int r300_startup(struct radeon_device *rdev)
 
 int r300_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
@@ -1452,7 +1454,11 @@ int r300_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return r300_startup(rdev);
+       r = r300_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int r300_suspend(struct radeon_device *rdev)
index 666e28fe509c4fb44293af49555a29ab974f9098..b14323053badc282696834413b0f521ff3d84445 100644 (file)
@@ -291,6 +291,8 @@ static int r420_startup(struct radeon_device *rdev)
 
 int r420_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
@@ -316,7 +318,11 @@ int r420_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return r420_startup(rdev);
+       r = r420_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int r420_suspend(struct radeon_device *rdev)
index 4ae1615e752ff8f6c5ecbfdc5eb83e3dbd120934..25084e824dbc3c95873fb3b297c9a257b0985bee 100644 (file)
@@ -218,6 +218,8 @@ static int r520_startup(struct radeon_device *rdev)
 
 int r520_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
@@ -237,7 +239,11 @@ int r520_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return r520_startup(rdev);
+       r = r520_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int r520_init(struct radeon_device *rdev)
index 4f08e5e6ee9d346c2b432cbf5349b0df07ff05fb..fbcd84803b60375b74c87b8e88df4caabf92b333 100644 (file)
@@ -2529,6 +2529,7 @@ int r600_resume(struct radeon_device *rdev)
        r = r600_startup(rdev);
        if (r) {
                DRM_ERROR("r600 startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
 
index d996f43811302fedd6f6a48169d1858b61d11df2..accc032c103fd3f846f2b57e6da4de8c693c5d1e 100644 (file)
@@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev)
        radeon_ring_write(ring, sq_stack_resource_mgmt_2);
 }
 
+#define I2F_MAX_BITS 15
+#define I2F_MAX_INPUT  ((1 << I2F_MAX_BITS) - 1)
+#define I2F_SHIFT (24 - I2F_MAX_BITS)
+
+/*
+ * Converts unsigned integer into 32-bit IEEE floating point representation.
+ * Conversion is not universal and only works for the range from 0
+ * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between
+ * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary,
+ * I2F_MAX_BITS can be increased, but that will add to the loop iterations
+ * and slow us down. Conversion is done by shifting the input and counting
+ * down until the first 1 reaches bit position 23. The resulting counter
+ * and the shifted input are, respectively, the exponent and the fraction.
+ * The sign is always zero.
+ */
 static uint32_t i2f(uint32_t input)
 {
        u32 result, i, exponent, fraction;
 
-       if ((input & 0x3fff) == 0)
-               result = 0; /* 0 is a special case */
+       WARN_ON_ONCE(input > I2F_MAX_INPUT);
+
+       if ((input & I2F_MAX_INPUT) == 0)
+               result = 0;
        else {
-               exponent = 140; /* exponent biased by 127; */
-               fraction = (input & 0x3fff) << 10; /* cheat and only
-                                                     handle numbers below 2^^15 */
-               for (i = 0; i < 14; i++) {
+               exponent = 126 + I2F_MAX_BITS;
+               fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT;
+
+               for (i = 0; i < I2F_MAX_BITS; i++) {
                        if (fraction & 0x800000)
                                break;
                        else {
-                               fraction = fraction << 1; /* keep
-                                                            shifting left until top bit = 1 */
+                               fraction = fraction << 1;
                                exponent = exponent - 1;
                        }
                }
-               result = exponent << 23 | (fraction & 0x7fffff); /* mask
-                                                                   off top bit; assumed 1 */
+               result = exponent << 23 | (fraction & 0x7fffff);
        }
        return result;
 }
index 73e05cb85eca03cd2c65461ce1af7ca3f82e0bfc..1668ec1ee77047d945bb8cb952a523d51f8bd452 100644 (file)
@@ -156,6 +156,47 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len)
 bool radeon_get_bios(struct radeon_device *rdev);
 
 
+/*
+ * 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);
+}
+
+
 /*
  * Dummy page
  */
@@ -598,7 +639,7 @@ struct radeon_ib {
  * mutex protects scheduled_ibs, ready, alloc_bm
  */
 struct radeon_ib_pool {
-       struct mutex                    mutex;
+       struct radeon_mutex             mutex;
        struct radeon_sa_manager        sa_manager;
        struct radeon_ib                ibs[RADEON_IB_POOL_SIZE];
        bool                            ready;
@@ -1354,47 +1395,6 @@ struct r600_vram_scratch {
 };
 
 
-/*
- * 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.
  */
index 5082d17d14dcda9733ca6d79b8d70513a7bd9944..1f53ae74ada1c7ea4e527060fb9b71a368461418 100644 (file)
@@ -2931,6 +2931,20 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
                        bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
                }
        }
+       if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) &&
+           (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) {
+               if (connected) {
+                       DRM_DEBUG_KMS("DFP6 connected\n");
+                       bios_0_scratch |= ATOM_S0_DFP6;
+                       bios_3_scratch |= ATOM_S3_DFP6_ACTIVE;
+                       bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6;
+               } else {
+                       DRM_DEBUG_KMS("DFP6 disconnected\n");
+                       bios_0_scratch &= ~ATOM_S0_DFP6;
+                       bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE;
+                       bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6;
+               }
+       }
 
        if (rdev->family >= CHIP_R600) {
                WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
@@ -2951,6 +2965,9 @@ radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        uint32_t bios_3_scratch;
 
+       if (ASIC_IS_DCE4(rdev))
+               return;
+
        if (rdev->family >= CHIP_R600)
                bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
        else
@@ -3003,6 +3020,9 @@ radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        uint32_t bios_2_scratch;
 
+       if (ASIC_IS_DCE4(rdev))
+               return;
+
        if (rdev->family >= CHIP_R600)
                bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
        else
index 9d95792bea3eab3c961b1221918beb1e4378d2f9..98724fcb00885e8a6ba3e8e88937b209e545a8e8 100644 (file)
@@ -58,7 +58,8 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
        }
 
        obj = (union acpi_object *)buffer.pointer;
-       memcpy(bios+offset, obj->buffer.pointer, len);
+       memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+       len = obj->buffer.length;
        kfree(buffer.pointer);
        return len;
 }
index 229a20f10e2b0c548b02cd5df527b9b72d6fe31a..501f4881e5aab4d1f1dcb9b57b4ba1a61743d9a7 100644 (file)
@@ -120,7 +120,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
                ret = radeon_atrm_get_bios_chunk(rdev->bios,
                                                 (i * ATRM_BIOS_PAGE),
                                                 ATRM_BIOS_PAGE);
-               if (ret <= 0)
+               if (ret < ATRM_BIOS_PAGE)
                        break;
        }
 
index 435a3d970ab8b0ef39c45f45ea8c22bdec05abf4..e64bec488ed8eb7479d9ff07efb8f0e213f62b80 100644 (file)
@@ -453,6 +453,10 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        int r;
 
        radeon_mutex_lock(&rdev->cs_mutex);
+       if (!rdev->accel_working) {
+               radeon_mutex_unlock(&rdev->cs_mutex);
+               return -EBUSY;
+       }
        /* initialize parser */
        memset(&parser, 0, sizeof(struct radeon_cs_parser));
        parser.filp = filp;
index 0afb13bd8dcad47ef5572991fec27e126185416d..49f7cb7e226b893a4a95a068b25179a30f93c892 100644 (file)
@@ -720,7 +720,7 @@ int radeon_device_init(struct radeon_device *rdev,
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
        radeon_mutex_init(&rdev->cs_mutex);
-       mutex_init(&rdev->ib_pool.mutex);
+       radeon_mutex_init(&rdev->ib_pool.mutex);
        for (i = 0; i < RADEON_NUM_RINGS; ++i)
                mutex_init(&rdev->ring[i].mutex);
        mutex_init(&rdev->dc_hw_i2c_mutex);
@@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
        if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
 
+       drm_kms_helper_poll_disable(dev);
+
        /* turn off display hw */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
@@ -959,9 +961,11 @@ int radeon_resume_kms(struct drm_device *dev)
        radeon_fbdev_set_suspend(rdev, 0);
        console_unlock();
 
-       /* init dig PHYs */
-       if (rdev->is_atom_bios)
+       /* init dig PHYs, disp eng pll */
+       if (rdev->is_atom_bios) {
                radeon_atom_encoder_init(rdev);
+               radeon_atom_dcpll_init(rdev);
+       }
        /* reset hpd state */
        radeon_hpd_init(rdev);
        /* blat the mode back in */
@@ -970,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
        }
+
+       drm_kms_helper_poll_enable(dev);
        return 0;
 }
 
index d3ffc18774a611df74a66ea136fbd12906eeaa63..8c49fef1ce78d01765f0565b517f1f9bc23a5a1c 100644 (file)
@@ -1305,9 +1305,11 @@ int radeon_modeset_init(struct radeon_device *rdev)
                return ret;
        }
 
-       /* init dig PHYs */
-       if (rdev->is_atom_bios)
+       /* init dig PHYs, disp eng pll */
+       if (rdev->is_atom_bios) {
                radeon_atom_encoder_init(rdev);
+               radeon_atom_dcpll_init(rdev);
+       }
 
        /* initialize hpd */
        radeon_hpd_init(rdev);
index 4b27efa4405b94b63011b2e8948d678c35ccfd62..9419c51bcf50f0f98f86cfd8122730ceea70a4d6 100644 (file)
@@ -202,6 +202,22 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
        return NULL;
 }
 
+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_get_external_encoder(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
@@ -288,3 +304,64 @@ void radeon_panel_mode_fixup(struct drm_encoder *encoder,
 
 }
 
+bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
+                                   u32 pixel_clock)
+{
+       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;
+
+       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:
+               if (radeon_connector->use_digital) {
+                       /* HDMI 1.3 supports up to 340 Mhz over single link */
+                       if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                               if (pixel_clock > 340000)
+                                       return true;
+                               else
+                                       return false;
+                       } else {
+                               if (pixel_clock > 165000)
+                                       return true;
+                               else
+                                       return false;
+                       }
+               } else
+                       return false;
+       case DRM_MODE_CONNECTOR_DVID:
+       case DRM_MODE_CONNECTOR_HDMIA:
+       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 false;
+               else {
+                       /* HDMI 1.3 supports up to 340 Mhz over single link */
+                       if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                               if (pixel_clock > 340000)
+                                       return true;
+                               else
+                                       return false;
+                       } else {
+                               if (pixel_clock > 165000)
+                                       return true;
+                               else
+                                       return false;
+                       }
+               }
+       default:
+               return false;
+       }
+}
+
index 64ea3dd9e6ff2ab58ed36476693a9dde4cff6f5a..4bd36a354fbef7d473dd321d92c96f828611d815 100644 (file)
@@ -364,8 +364,10 @@ int radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
        int not_processed = 0;
 
        read_lock_irqsave(&rdev->fence_lock, irq_flags);
-       if (!rdev->fence_drv[ring].initialized)
+       if (!rdev->fence_drv[ring].initialized) {
+               read_unlock_irqrestore(&rdev->fence_lock, irq_flags);
                return 0;
+       }
 
        if (!list_empty(&rdev->fence_drv[ring].emitted)) {
                struct list_head *ptr;
index 7bb1b079f4806f6d70414809e43e060c1bd1cec2..98a8ad680109efc5fdb7b246d4a79a68839f383d 100644 (file)
@@ -897,6 +897,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
        i2c->rec = *rec;
        i2c->adapter.owner = THIS_MODULE;
        i2c->adapter.class = I2C_CLASS_DDC;
+       i2c->adapter.dev.parent = &dev->pdev->dev;
        i2c->dev = dev;
        i2c_set_adapdata(&i2c->adapter, i2c);
        if (rec->mm_i2c ||
@@ -957,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
        i2c->rec = *rec;
        i2c->adapter.owner = THIS_MODULE;
        i2c->adapter.class = I2C_CLASS_DDC;
+       i2c->adapter.dev.parent = &dev->pdev->dev;
        i2c->dev = dev;
        snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
                 "Radeon aux bus %s", name);
index be38921bf761a570229afad2109b5aeb32127f29..66d5fe1c81747cfa73da445d1f2099d36e9e4261 100644 (file)
@@ -135,6 +135,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
            (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 == 0x01fc))
+               return true;
+
        /* Dell RS690 only seems to work with MSIs. */
        if ((rdev->pdev->device == 0x791f) &&
            (rdev->pdev->subsystem_vendor == 0x1028) &&
index 08ff857c8fd6609e9530b742470c743bde1e5c73..4330e3253573ffeb92a5dab9f39223e074fc65ca 100644 (file)
@@ -362,6 +362,7 @@ struct radeon_encoder_atom_dig {
        struct backlight_device *bl_dev;
        int dpms_mode;
        uint8_t backlight_level;
+       int panel_mode;
 };
 
 struct radeon_encoder_atom_dac {
@@ -466,6 +467,10 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev);
 
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
+extern struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder);
+extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
+                                   u32 pixel_clock);
 
 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);
@@ -482,8 +487,11 @@ extern void radeon_dp_link_train(struct drm_encoder *encoder,
 extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
 extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
+extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
+                                   struct drm_connector *connector);
 extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
 extern void radeon_atom_encoder_init(struct radeon_device *rdev);
+extern void radeon_atom_dcpll_init(struct radeon_device *rdev);
 extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
                                           int action, uint8_t lane_num,
                                           uint8_t lane_set);
index e8bc70933d1b342a9bd3b9d04bbcbfc14c5438dc..92c9ea4751fbd7b409a6b88437bc16ed547734f6 100644 (file)
@@ -109,12 +109,12 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
                return r;
        }
 
-       mutex_lock(&rdev->ib_pool.mutex);
+       radeon_mutex_lock(&rdev->ib_pool.mutex);
        idx = rdev->ib_pool.head_id;
 retry:
        if (cretry > 5) {
                dev_err(rdev->dev, "failed to get an ib after 5 retry\n");
-               mutex_unlock(&rdev->ib_pool.mutex);
+               radeon_mutex_unlock(&rdev->ib_pool.mutex);
                radeon_fence_unref(&fence);
                return -ENOMEM;
        }
@@ -139,7 +139,7 @@ retry:
                                 */
                                rdev->ib_pool.head_id = (1 + idx);
                                rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1);
-                               mutex_unlock(&rdev->ib_pool.mutex);
+                               radeon_mutex_unlock(&rdev->ib_pool.mutex);
                                return 0;
                        }
                }
@@ -158,7 +158,7 @@ retry:
                }
                idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
        }
-       mutex_unlock(&rdev->ib_pool.mutex);
+       radeon_mutex_unlock(&rdev->ib_pool.mutex);
        radeon_fence_unref(&fence);
        return r;
 }
@@ -171,12 +171,12 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
        if (tmp == NULL) {
                return;
        }
-       mutex_lock(&rdev->ib_pool.mutex);
+       radeon_mutex_lock(&rdev->ib_pool.mutex);
        if (tmp->fence && !tmp->fence->emitted) {
                radeon_sa_bo_free(rdev, &tmp->sa_bo);
                radeon_fence_unref(&tmp->fence);
        }
-       mutex_unlock(&rdev->ib_pool.mutex);
+       radeon_mutex_unlock(&rdev->ib_pool.mutex);
 }
 
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
@@ -204,22 +204,25 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
 
 int radeon_ib_pool_init(struct radeon_device *rdev)
 {
+       struct radeon_sa_manager tmp;
        int i, r;
 
-       mutex_lock(&rdev->ib_pool.mutex);
-       if (rdev->ib_pool.ready) {
-               mutex_unlock(&rdev->ib_pool.mutex);
-               return 0;
-       }
-
-       r = radeon_sa_bo_manager_init(rdev, &rdev->ib_pool.sa_manager,
+       r = radeon_sa_bo_manager_init(rdev, &tmp,
                                      RADEON_IB_POOL_SIZE*64*1024,
                                      RADEON_GEM_DOMAIN_GTT);
        if (r) {
-               mutex_unlock(&rdev->ib_pool.mutex);
                return r;
        }
 
+       radeon_mutex_lock(&rdev->ib_pool.mutex);
+       if (rdev->ib_pool.ready) {
+               radeon_mutex_unlock(&rdev->ib_pool.mutex);
+               radeon_sa_bo_manager_fini(rdev, &tmp);
+               return 0;
+       }
+
+       rdev->ib_pool.sa_manager = tmp;
+       INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo);
        for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
                rdev->ib_pool.ibs[i].fence = NULL;
                rdev->ib_pool.ibs[i].idx = i;
@@ -236,7 +239,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
        if (radeon_debugfs_ring_init(rdev)) {
                DRM_ERROR("Failed to register debugfs file for rings !\n");
        }
-       mutex_unlock(&rdev->ib_pool.mutex);
+       radeon_mutex_unlock(&rdev->ib_pool.mutex);
        return 0;
 }
 
@@ -244,7 +247,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
 {
        unsigned i;
 
-       mutex_lock(&rdev->ib_pool.mutex);
+       radeon_mutex_lock(&rdev->ib_pool.mutex);
        if (rdev->ib_pool.ready) {
                for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
                        radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo);
@@ -253,7 +256,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
                radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager);
                rdev->ib_pool.ready = false;
        }
-       mutex_unlock(&rdev->ib_pool.mutex);
+       radeon_mutex_unlock(&rdev->ib_pool.mutex);
 }
 
 int radeon_ib_pool_start(struct radeon_device *rdev)
@@ -497,8 +500,11 @@ static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
 int radeon_debugfs_ring_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-       return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list,
-                                       ARRAY_SIZE(radeon_debugfs_ring_info_list));
+       if (rdev->family >= CHIP_CAYMAN)
+               return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list,
+                                               ARRAY_SIZE(radeon_debugfs_ring_info_list));
+       else
+               return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, 1);
 #else
        return 0;
 #endif
index b0ce84a20a68faf628ea3b72171a41b38e78dfaf..866a05be75f2b104a6a91385087ec9c700bd503c 100644 (file)
@@ -442,6 +442,8 @@ static int rs400_startup(struct radeon_device *rdev)
 
 int rs400_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        rs400_gart_disable(rdev);
        /* Resume clock before doing reset */
@@ -462,7 +464,11 @@ int rs400_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return rs400_startup(rdev);
+       r = rs400_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int rs400_suspend(struct radeon_device *rdev)
index ec46eb45e34cd8b7534deb5f75353496424756f7..4fc700684dcd0dfd1fae0362bf3b2307d5e2cab7 100644 (file)
@@ -684,9 +684,7 @@ int rs600_irq_process(struct radeon_device *rdev)
                        WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM);
                        break;
                default:
-                       msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
-                       WREG32(RADEON_MSI_REARM_EN, msi_rearm);
-                       WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+                       WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
                        break;
                }
        }
@@ -878,6 +876,8 @@ static int rs600_startup(struct radeon_device *rdev)
 
 int rs600_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        rs600_gart_disable(rdev);
        /* Resume clock before doing reset */
@@ -896,7 +896,11 @@ int rs600_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return rs600_startup(rdev);
+       r = rs600_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int rs600_suspend(struct radeon_device *rdev)
index 4f24a0fa8c82f1c4b9ac790073be0a3e69fb00eb..f68dff2fadcb4e97dbafc8b6ff588ceaf831ac4f 100644 (file)
@@ -659,6 +659,8 @@ static int rs690_startup(struct radeon_device *rdev)
 
 int rs690_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        rs400_gart_disable(rdev);
        /* Resume clock before doing reset */
@@ -677,7 +679,11 @@ int rs690_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return rs690_startup(rdev);
+       r = rs690_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int rs690_suspend(struct radeon_device *rdev)
index 880637fd1946c5b7f717487fca8dad37eddb0b42..959bf4483beab43766d795ba75002f40c3d04558 100644 (file)
@@ -424,6 +424,8 @@ static int rv515_startup(struct radeon_device *rdev)
 
 int rv515_resume(struct radeon_device *rdev)
 {
+       int r;
+
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
@@ -443,7 +445,11 @@ int rv515_resume(struct radeon_device *rdev)
        radeon_surface_init(rdev);
 
        rdev->accel_working = true;
-       return rv515_startup(rdev);
+       r =  rv515_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
 }
 
 int rv515_suspend(struct radeon_device *rdev)
index a1668b659ddd3e3f8ee94c97de6474468c71d3dd..c049c0c51841f865d578e384ab61d568c6c288f4 100644 (file)
@@ -1139,6 +1139,7 @@ int rv770_resume(struct radeon_device *rdev)
        r = rv770_startup(rdev);
        if (r) {
                DRM_ERROR("r600 startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
 
index 06da063ece2e59681f3c51110006e13e7e58ae0f..573220cc5269fe48d6f0a5fb972c33c5731bb1af 100644 (file)
@@ -40,7 +40,6 @@ static struct pci_device_id pciidlist[] = {
 static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
 {
        drm_sis_private_t *dev_priv;
-       int ret;
 
        dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
        if (dev_priv == NULL)
@@ -50,7 +49,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
        dev_priv->chipset = chipset;
        idr_init(&dev->object_name_idr);
 
-       return ret;
+       return 0;
 }
 
 static int sis_driver_unload(struct drm_device *dev)
index 2f0eab66ece6c1eb9eeffaae72a517727a0257ee..7c3a57de8187c603628758c8650448f889de550f 100644 (file)
@@ -404,6 +404,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
                }
        }
 
+       if (bdev->driver->move_notify)
+               bdev->driver->move_notify(bo, mem);
+
        if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
            !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
                ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem);
@@ -413,11 +416,17 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
        else
                ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem);
 
-       if (ret)
-               goto out_err;
+       if (ret) {
+               if (bdev->driver->move_notify) {
+                       struct ttm_mem_reg tmp_mem = *mem;
+                       *mem = bo->mem;
+                       bo->mem = tmp_mem;
+                       bdev->driver->move_notify(bo, mem);
+                       bo->mem = *mem;
+               }
 
-       if (bdev->driver->move_notify)
-               bdev->driver->move_notify(bo, mem);
+               goto out_err;
+       }
 
 moved:
        if (bo->evicted) {
index 0af6ebdf205d821c6b68c825ea7db1ada77dff42..b66ef0e3cde14a2f98fa8d2a1245f41ca83c3268 100644 (file)
@@ -378,7 +378,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
                                  unsigned int *handle)
 {
        if (handle)
-               handle = 0;
+               *handle = 0;
 
        return 0;
 }
index 0c33ae9cf0f0e27549f3fd505e242dbb98b18be2..406632472c1bb038cdf06dae37c7f115f479e94a 100644 (file)
@@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev)
        struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 
        vmbus_close(dev->channel);
+       hid_hw_stop(input_dev->hid_device);
        hid_destroy_device(input_dev->hid_device);
        mousevsc_free_device(input_dev);
 
index b47e58b52d9fbd1a28ef00d2d9392f8e44fe4d0f..acab74cde72730dd8660c6d7a8d64a8d7ba75451 100644 (file)
@@ -531,7 +531,6 @@ static int wacom_probe(struct hid_device *hdev,
        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
        wdata->battery.use_for_apm = 0;
 
-       power_supply_powers(&wdata->battery, &hdev->dev);
 
        ret = power_supply_register(&hdev->dev, &wdata->battery);
        if (ret) {
@@ -540,6 +539,8 @@ static int wacom_probe(struct hid_device *hdev,
                goto err_battery;
        }
 
+       power_supply_powers(&wdata->battery, &hdev->dev);
+
        wdata->ac.properties = wacom_ac_props;
        wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
        wdata->ac.get_property = wacom_ac_get_property;
@@ -547,14 +548,14 @@ static int wacom_probe(struct hid_device *hdev,
        wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
        wdata->ac.use_for_apm = 0;
 
-       power_supply_powers(&wdata->battery, &hdev->dev);
-
        ret = power_supply_register(&hdev->dev, &wdata->ac);
        if (ret) {
                hid_warn(hdev,
                         "can't create ac battery attribute, err: %d\n", ret);
                goto err_ac;
        }
+
+       power_supply_powers(&wdata->ac, &hdev->dev);
 #endif
        return 0;
 
index fc253b472f9d4033922693aa980d947210b1d4c2..cac3589b1ed5ac192455b804db0ea321d603ec8a 100644 (file)
@@ -1226,14 +1226,14 @@ static int wiimote_hid_probe(struct hid_device *hdev,
        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
        wdata->battery.use_for_apm = 0;
 
-       power_supply_powers(&wdata->battery, &hdev->dev);
-
        ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
        if (ret) {
                hid_err(hdev, "Cannot register battery device\n");
                goto err_battery;
        }
 
+       power_supply_powers(&wdata->battery, &hdev->dev);
+
        ret = wiimote_leds_create(wdata);
        if (ret)
                goto err_free;
index 7c297d305d5dd42f7399eadb33e624fd9a6a0a69..b1ec0e2aeb57b0b26a66e17b067192cfc30689c1 100644 (file)
@@ -922,11 +922,11 @@ void hiddev_disconnect(struct hid_device *hid)
        struct hiddev *hiddev = hid->hiddev;
        struct usbhid_device *usbhid = hid->driver_data;
 
+       usb_deregister_dev(usbhid->intf, &hiddev_class);
+
        mutex_lock(&hiddev->existancelock);
        hiddev->exist = 0;
 
-       usb_deregister_dev(usbhid->intf, &hiddev_class);
-
        if (hiddev->open) {
                mutex_unlock(&hiddev->existancelock);
                usbhid_close(hiddev->hid);
index 92f949767ece5ccd6878896893177e34be63da2e..6dbfd3e516e4820ef182ce2fca2ad3e787ab1c59 100644 (file)
@@ -283,11 +283,11 @@ static inline long temp_from_reg(u8 reg)
 
 static inline u8 temp_to_reg(long val)
 {
-       if (val < 0)
-               val = 0;
-       else if (val > 1000 * 0xff)
-               val = 0xff;
-       return ((val + 500) / 1000);
+       if (val <= 0)
+               return 0;
+       if (val >= 1000 * 0xff)
+               return 0xff;
+       return (val + 500) / 1000;
 }
 
 /*
index eedf574ab539c9108c7dec18e16e57994f9cee12..f609b5727ba9047f8ba0f4eb96bfdbae4183b7c4 100644 (file)
@@ -172,7 +172,7 @@ static inline void f75375_write8(struct i2c_client *client, u8 reg,
 static inline void f75375_write16(struct i2c_client *client, u8 reg,
                u16 value)
 {
-       int err = i2c_smbus_write_byte_data(client, reg, (value << 8));
+       int err = i2c_smbus_write_byte_data(client, reg, (value >> 8));
        if (err)
                return;
        i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF));
@@ -200,9 +200,6 @@ static struct f75375_data *f75375_update_device(struct device *dev)
                                f75375_read16(client, F75375_REG_FAN_MIN(nr));
                        data->fan_target[nr] =
                                f75375_read16(client, F75375_REG_FAN_EXP(nr));
-                       data->pwm[nr] = f75375_read8(client,
-                               F75375_REG_FAN_PWM_DUTY(nr));
-
                }
                for (nr = 0; nr < 4; nr++) {
                        data->in_max[nr] =
@@ -218,6 +215,8 @@ static struct f75375_data *f75375_update_device(struct device *dev)
        if (time_after(jiffies, data->last_updated + 2 * HZ)
                || !data->valid) {
                for (nr = 0; nr < 2; nr++) {
+                       data->pwm[nr] = f75375_read8(client,
+                               F75375_REG_FAN_PWM_DUTY(nr));
                        /* assign MSB, therefore shift it by 8 bits */
                        data->temp11[nr] =
                                f75375_read8(client, F75375_REG_TEMP(nr)) << 8;
@@ -369,7 +368,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
                        fanmode  |= (3 << FAN_CTRL_MODE(nr));
                        break;
                case 2: /* AUTOMATIC*/
-                       fanmode  |= (2 << FAN_CTRL_MODE(nr));
+                       fanmode  |= (1 << FAN_CTRL_MODE(nr));
                        break;
                case 3: /* fan speed */
                        break;
@@ -723,7 +722,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
                        if (data->kind == f75387) {
                                bool manu, duty;
 
-                               if (!(conf & (1 << F75387_FAN_CTRL_LINEAR(nr))))
+                               if (!(mode & (1 << F75387_FAN_CTRL_LINEAR(nr))))
                                        data->pwm_mode[nr] = 1;
 
                                manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1);
index 6ddeae049058e377562c3382b5d06095a9e39beb..91fdd1fe18b0a8e5c4bfe54659f5811e939b49d4 100644 (file)
@@ -883,7 +883,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
 
 static int __devinit sht15_probe(struct platform_device *pdev)
 {
-       int ret = 0;
+       int ret;
        struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
        u8 status = 0;
 
@@ -901,6 +901,7 @@ static int __devinit sht15_probe(struct platform_device *pdev)
        init_waitqueue_head(&data->wait_queue);
 
        if (pdev->dev.platform_data == NULL) {
+               ret = -EINVAL;
                dev_err(&pdev->dev, "no platform data supplied\n");
                goto err_free_data;
        }
index 0e0af0445222c4346af8fef879831831e49caffa..5276d1933dbcad8ee3acf29fb5d0f2f3e17b7d4d 100644 (file)
@@ -1319,6 +1319,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 {
        struct w83627ehf_data *data = dev_get_drvdata(dev);
        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       struct w83627ehf_sio_data *sio_data = dev->platform_data;
        int nr = sensor_attr->index;
        unsigned long val;
        int err;
@@ -1330,6 +1331,11 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 
        if (val > 1)
                return -EINVAL;
+
+       /* On NCT67766F, DC mode is only supported for pwm1 */
+       if (sio_data->kind == nct6776 && nr && val != 1)
+               return -EINVAL;
+
        mutex_lock(&data->update_lock);
        reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
        data->pwm_mode[nr] = val;
@@ -1914,9 +1920,26 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
                fan4min = 0;
                fan5pin = 0;
        } else if (sio_data->kind == nct6776) {
-               fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
-               fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
-               fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+               bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+
+               superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+               regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+               if (regval & 0x80)
+                       fan3pin = gpok;
+               else
+                       fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+               if (regval & 0x40)
+                       fan4pin = gpok;
+               else
+                       fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+
+               if (regval & 0x20)
+                       fan5pin = gpok;
+               else
+                       fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+
                fan4min = fan4pin;
        } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
                fan3pin = 1;
@@ -2326,11 +2349,6 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
        /* Read fan clock dividers immediately */
        w83627ehf_update_fan_div_common(dev, data);
 
-       /* Read pwm data to save original values */
-       w83627ehf_update_pwm_common(dev, data);
-       for (i = 0; i < data->pwm_num; i++)
-               data->pwm_enable_orig[i] = data->pwm_enable[i];
-
        /* Read pwm data to save original values */
        w83627ehf_update_pwm_common(dev, data);
        for (i = 0; i < data->pwm_num; i++)
index cbe7a2fb779f4036798c0231ef2dddb349f6fc41..3101dd59e3794c6d2d34c2ff4df65f1cece29a28 100644 (file)
@@ -682,19 +682,19 @@ config I2C_XILINX
          will be called xilinx_i2c.
 
 config I2C_EG20T
-       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223)"
+       tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
        depends on PCI
        help
          This driver is for PCH(Platform controller Hub) I2C of EG20T which
          is an IOH(Input/Output Hub) for x86 embedded processor.
          This driver can access PCH I2C bus device.
 
-         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.
 
 comment "External I2C/SMBus adapter drivers"
 
index 3ef3557b6e32d5d03b1b048bdae39988d0524a4e..ca8877641040284e4eb7964c9abe63a7e2d4a11d 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
 /*
 Set the number of I2C instance max
 Intel EG20T PCH :              1ch
-OKI SEMICONDUCTOR ML7213 IOH : 2ch
+LAPIS Semiconductor ML7213 IOH :       2ch
+LAPIS Semiconductor ML7831 IOH :       1ch
 */
 #define PCH_I2C_MAX_DEV                        2
 
@@ -180,15 +181,17 @@ static int pch_clk = 50000;       /* specifies I2C clock speed in KHz */
 static wait_queue_head_t pch_event;
 static DEFINE_MUTEX(pch_mutex);
 
-/* Definition for ML7213 by OKI SEMICONDUCTOR */
+/* Definition for ML7213 by LAPIS Semiconductor */
 #define PCI_VENDOR_ID_ROHM             0x10DB
 #define PCI_DEVICE_ID_ML7213_I2C       0x802D
 #define PCI_DEVICE_ID_ML7223_I2C       0x8010
+#define PCI_DEVICE_ID_ML7831_I2C       0x8817
 
 static DEFINE_PCI_DEVICE_TABLE(pch_pcidev_id) = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C),   1, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_I2C), 1, },
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, },
        {0,}
 };
 
@@ -243,7 +246,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
        if (pch_clk > PCH_MAX_CLK)
                pch_clk = 62500;
 
-       pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8;
+       pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
        /* Set transfer speed in I2CBC */
        iowrite32(pch_i2cbc, p + PCH_I2CBC);
 
@@ -918,7 +921,9 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
                pch_adap->dev.parent = &pdev->dev;
 
                pch_i2c_init(&adap_info->pch_data[i]);
-               ret = i2c_add_adapter(pch_adap);
+
+               pch_adap->nr = i;
+               ret = i2c_add_numbered_adapter(pch_adap);
                if (ret) {
                        pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
                        goto err_add_adapter;
@@ -1058,8 +1063,8 @@ static void __exit pch_pci_exit(void)
 }
 module_exit(pch_pci_exit);
 
-MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
+MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.lapis-semi.com>");
 module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
 module_param(pch_clk, int, (S_IRUSR | S_IWUSR));
index fa23faa20f0e34435881e24abc6d5e4c9545a259..801df6000e9b2042ce6bc6453b38e49bf41fd031 100644 (file)
@@ -37,6 +37,9 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
@@ -182,7 +185,9 @@ struct omap_i2c_dev {
        u32                     latency;        /* maximum mpu wkup latency */
        void                    (*set_mpu_wkup_lat)(struct device *dev,
                                                    long latency);
-       u32                     speed;          /* Speed of bus in Khz */
+       u32                     speed;          /* Speed of bus in kHz */
+       u32                     dtrev;          /* extra revision from DT */
+       u32                     flags;
        u16                     cmd_err;
        u8                      *buf;
        u8                      *regs;
@@ -235,7 +240,7 @@ static const u8 reg_map_ip_v2[] = {
        [OMAP_I2C_BUF_REG] = 0x94,
        [OMAP_I2C_CNT_REG] = 0x98,
        [OMAP_I2C_DATA_REG] = 0x9c,
-       [OMAP_I2C_SYSC_REG] = 0x20,
+       [OMAP_I2C_SYSC_REG] = 0x10,
        [OMAP_I2C_CON_REG] = 0xa4,
        [OMAP_I2C_OA_REG] = 0xa8,
        [OMAP_I2C_SA_REG] = 0xac,
@@ -266,11 +271,7 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
 
 static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
-       struct omap_i2c_bus_platform_data *pdata;
-
-       pdata = dev->dev->platform_data;
-
-       if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
+       if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
                omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
                omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
                omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -291,13 +292,10 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
 {
-       struct omap_i2c_bus_platform_data *pdata;
        u16 iv;
 
-       pdata = dev->dev->platform_data;
-
        dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-       if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+       if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
                omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
        else
                omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
@@ -320,9 +318,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
        unsigned long timeout;
        unsigned long internal_clk = 0;
        struct clk *fclk;
-       struct omap_i2c_bus_platform_data *pdata;
-
-       pdata = dev->dev->platform_data;
 
        if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
                /* Disable I2C controller before soft reset */
@@ -373,7 +368,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
        }
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 
-       if (pdata->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
+       if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
                /*
                 * The I2C functional clock is the armxor_ck, so there's
                 * no need to get "armxor_ck" separately.  Now, if OMAP2420
@@ -397,7 +392,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
                        psc = fclk_rate / 12000000;
        }
 
-       if (!(pdata->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
+       if (!(dev->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
 
                /*
                 * HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -406,7 +401,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
                 * The filter is iclk (fclk for HS) period.
                 */
                if (dev->speed > 400 ||
-                              pdata->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
+                              dev->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
                        internal_clk = 19200;
                else if (dev->speed > 100)
                        internal_clk = 9600;
@@ -475,7 +470,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 
        dev->errata = 0;
 
-       if (pdata->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
+       if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
                dev->errata |= I2C_OMAP_ERRATA_I207;
 
        /* Enable interrupts */
@@ -484,7 +479,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
                        OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
                                (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
        omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
-       if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
+       if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
                dev->pscstate = psc;
                dev->scllstate = scll;
                dev->sclhstate = sclh;
@@ -804,9 +799,6 @@ omap_i2c_isr(int this_irq, void *dev_id)
        u16 bits;
        u16 stat, w;
        int err, count = 0;
-       struct omap_i2c_bus_platform_data *pdata;
-
-       pdata = dev->dev->platform_data;
 
        if (pm_runtime_suspended(dev->dev))
                return IRQ_NONE;
@@ -830,11 +822,9 @@ complete:
                                ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
                                OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
 
-               if (stat & OMAP_I2C_STAT_NACK) {
+               if (stat & OMAP_I2C_STAT_NACK)
                        err |= OMAP_I2C_STAT_NACK;
-                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
-                                          OMAP_I2C_CON_STP);
-               }
+
                if (stat & OMAP_I2C_STAT_AL) {
                        dev_err(dev->dev, "Arbitration lost\n");
                        err |= OMAP_I2C_STAT_AL;
@@ -875,7 +865,7 @@ complete:
                                         * Data reg in 2430, omap3 and
                                         * omap4 is 8 bit wide
                                         */
-                                       if (pdata->flags &
+                                       if (dev->flags &
                                                 OMAP_I2C_FLAG_16BIT_DATA_REG) {
                                                if (dev->buf_len) {
                                                        *dev->buf++ = w >> 8;
@@ -918,7 +908,7 @@ complete:
                                         * Data reg in 2430, omap3 and
                                         * omap4 is 8 bit wide
                                         */
-                                       if (pdata->flags &
+                                       if (dev->flags &
                                                 OMAP_I2C_FLAG_16BIT_DATA_REG) {
                                                if (dev->buf_len) {
                                                        w |= *dev->buf++ << 8;
@@ -965,6 +955,32 @@ static const struct i2c_algorithm omap_i2c_algo = {
        .functionality  = omap_i2c_func,
 };
 
+#ifdef CONFIG_OF
+static struct omap_i2c_bus_platform_data omap3_pdata = {
+       .rev = OMAP_I2C_IP_VERSION_1,
+       .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+                OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+                OMAP_I2C_FLAG_BUS_SHIFT_2,
+};
+
+static struct omap_i2c_bus_platform_data omap4_pdata = {
+       .rev = OMAP_I2C_IP_VERSION_2,
+};
+
+static const struct of_device_id omap_i2c_of_match[] = {
+       {
+               .compatible = "ti,omap4-i2c",
+               .data = &omap4_pdata,
+       },
+       {
+               .compatible = "ti,omap3-i2c",
+               .data = &omap3_pdata,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
+#endif
+
 static int __devinit
 omap_i2c_probe(struct platform_device *pdev)
 {
@@ -972,9 +988,10 @@ omap_i2c_probe(struct platform_device *pdev)
        struct i2c_adapter      *adap;
        struct resource         *mem, *irq, *ioarea;
        struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
+       struct device_node      *node = pdev->dev.of_node;
+       const struct of_device_id *match;
        irq_handler_t isr;
        int r;
-       u32 speed = 0;
 
        /* NOTE: driver uses the static register mapping */
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1001,15 +1018,24 @@ omap_i2c_probe(struct platform_device *pdev)
                goto err_release_region;
        }
 
-       if (pdata != NULL) {
-               speed = pdata->clkrate;
+       match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
+       if (match) {
+               u32 freq = 100000; /* default to 100000 Hz */
+
+               pdata = match->data;
+               dev->dtrev = pdata->rev;
+               dev->flags = pdata->flags;
+
+               of_property_read_u32(node, "clock-frequency", &freq);
+               /* convert DT freq value in Hz into kHz for speed */
+               dev->speed = freq / 1000;
+       } else if (pdata != NULL) {
+               dev->speed = pdata->clkrate;
+               dev->flags = pdata->flags;
                dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
-       } else {
-               speed = 100;    /* Default speed */
-               dev->set_mpu_wkup_lat = NULL;
+               dev->dtrev = pdata->rev;
        }
 
-       dev->speed = speed;
        dev->dev = &pdev->dev;
        dev->irq = irq->start;
        dev->base = ioremap(mem->start, resource_size(mem));
@@ -1020,9 +1046,9 @@ omap_i2c_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dev);
 
-       dev->reg_shift = (pdata->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
+       dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
 
-       if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+       if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
                dev->regs = (u8 *)reg_map_ip_v2;
        else
                dev->regs = (u8 *)reg_map_ip_v1;
@@ -1035,7 +1061,7 @@ omap_i2c_probe(struct platform_device *pdev)
        if (dev->rev <= OMAP_I2C_REV_ON_3430)
                dev->errata |= I2C_OMAP3_1P153;
 
-       if (!(pdata->flags & OMAP_I2C_FLAG_NO_FIFO)) {
+       if (!(dev->flags & OMAP_I2C_FLAG_NO_FIFO)) {
                u16 s;
 
                /* Set up the fifo size - Get total size */
@@ -1058,7 +1084,7 @@ omap_i2c_probe(struct platform_device *pdev)
                /* calculate wakeup latency constraint for MPU */
                if (dev->set_mpu_wkup_lat != NULL)
                        dev->latency = (1000000 * dev->fifo_size) /
-                                      (1000 * speed / 8);
+                                      (1000 * dev->speed / 8);
        }
 
        /* reset ASAP, clearing any IRQs */
@@ -1074,7 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
        }
 
        dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
-                pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+                dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
 
        pm_runtime_put(dev->dev);
 
@@ -1085,6 +1111,7 @@ omap_i2c_probe(struct platform_device *pdev)
        strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
        adap->algo = &omap_i2c_algo;
        adap->dev.parent = &pdev->dev;
+       adap->dev.of_node = pdev->dev.of_node;
 
        /* i2c device drivers may be active on return from add_adapter() */
        adap->nr = pdev->id;
@@ -1094,6 +1121,8 @@ omap_i2c_probe(struct platform_device *pdev)
                goto err_free_irq;
        }
 
+       of_i2c_register_devices(adap);
+
        return 0;
 
 err_free_irq:
@@ -1166,6 +1195,7 @@ static struct platform_driver omap_i2c_driver = {
                .name   = "omap_i2c",
                .owner  = THIS_MODULE,
                .pm     = OMAP_I2C_PM_OPS,
+               .of_match_table = of_match_ptr(omap_i2c_of_match),
        },
 };
 
index 6381604696d304a0508b23778ac04fe7ee05ef08..0ab4a9548745015cfae6633376527663e6a79708 100644 (file)
@@ -755,7 +755,7 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 
 static struct platform_driver tegra_i2c_driver = {
        .probe   = tegra_i2c_probe,
-       .remove  = tegra_i2c_remove,
+       .remove  = __devexit_p(tegra_i2c_remove),
 #ifdef CONFIG_PM
        .suspend = tegra_i2c_suspend,
        .resume  = tegra_i2c_resume,
index 7f879b2397b0e35a535449a3e0dcca8b36f48f10..af8d016c37eaae0dc4f5c97b9aecce840d6fec57 100644 (file)
@@ -116,4 +116,3 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)    += au1xxx-ide.o
 
 obj-$(CONFIG_BLK_DEV_IDE_TX4938)       += tx4938ide.o
 obj-$(CONFIG_BLK_DEV_IDE_TX4939)       += tx4939ide.o
-obj-$(CONFIG_BLK_DEV_IDE_AT91)         += at91_ide.o
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
deleted file mode 100644 (file)
index 41d4155..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller
- * with Compact Flash True IDE logic
- *
- * Copyright (c) 2008, 2009 Kelvatek Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/ide.h>
-#include <linux/platform_device.h>
-
-#include <mach/board.h>
-#include <asm/gpio.h>
-#include <mach/at91sam9_smc.h>
-
-#define DRV_NAME "at91_ide"
-
-#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args)
-#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args)
-
-/*
- * Access to IDE device is possible through EBI Static Memory Controller
- * with Compact Flash logic. For details see EBI and SMC datasheet sections
- * of any microcontroller from AT91SAM9 family.
- *
- * Within SMC chip select address space, lines A[23:21] distinguish Compact
- * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are:
- *   0x00c0000 - True IDE
- *   0x00e0000 - Alternate True IDE (Alt Status Register)
- *
- * On True IDE mode Task File and Data Register are mapped at the same address.
- * To distinguish access between these two different bus data width is used:
- * 8Bit for Task File, 16Bit for Data I/O.
- *
- * After initialization we do 8/16 bit flipping (changes in SMC MODE register)
- * only inside IDE callback routines which are serialized by IDE layer,
- * so no additional locking needed.
- */
-
-#define TASK_FILE      0x00c00000
-#define ALT_MODE       0x00e00000
-#define REGS_SIZE      8
-
-#define enter_16bit(cs, mode) do {                                     \
-       mode = at91_sys_read(AT91_SMC_MODE(cs));                        \
-       at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16);      \
-} while (0)
-
-#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode);
-
-static void set_smc_timings(const u8 chipselect, const u16 cycle,
-                           const u16 setup, const u16 pulse,
-                           const u16 data_float, int use_iordy)
-{
-       unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
-                            AT91_SMC_BAT_SELECT;
-
-       /* disable or enable waiting for IORDY signal */
-       if (use_iordy)
-               mode |= AT91_SMC_EXNWMODE_READY;
-
-       /* add data float cycles if needed */
-       if (data_float)
-               mode |= AT91_SMC_TDF_(data_float);
-
-       at91_sys_write(AT91_SMC_MODE(chipselect), mode);
-
-       /* setup timings in SMC */
-       at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) |
-                                                  AT91_SMC_NCS_WRSETUP_(0) |
-                                                  AT91_SMC_NRDSETUP_(setup) |
-                                                  AT91_SMC_NCS_RDSETUP_(0));
-       at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) |
-                                                  AT91_SMC_NCS_WRPULSE_(cycle) |
-                                                  AT91_SMC_NRDPULSE_(pulse) |
-                                                  AT91_SMC_NCS_RDPULSE_(cycle));
-       at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) |
-                                                  AT91_SMC_NRDCYCLE_(cycle));
-}
-
-static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz)
-{
-       u64 tmp = ns;
-
-       tmp *= mck_hz;
-       tmp += 1000*1000*1000 - 1; /* round up */
-       do_div(tmp, 1000*1000*1000);
-       return (unsigned int) tmp;
-}
-
-static void apply_timings(const u8 chipselect, const u8 pio,
-                         const struct ide_timing *timing, int use_iordy)
-{
-       unsigned int t0, t1, t2, t6z;
-       unsigned int cycle, setup, pulse, data_float;
-       unsigned int mck_hz;
-       struct clk *mck;
-
-       /* see table 22 of Compact Flash standard 4.1 for the meaning,
-        * we do not stretch active (t2) time, so setup (t1) + hold time (th)
-        * assure at least minimal recovery (t2i) time */
-       t0 = timing->cyc8b;
-       t1 = timing->setup;
-       t2 = timing->act8b;
-       t6z = (pio < 5) ? 30 : 20;
-
-       pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z);
-
-       mck = clk_get(NULL, "mck");
-       BUG_ON(IS_ERR(mck));
-       mck_hz = clk_get_rate(mck);
-       pdbg("mck_hz=%u\n", mck_hz);
-
-       cycle = calc_mck_cycles(t0, mck_hz);
-       setup = calc_mck_cycles(t1, mck_hz);
-       pulse = calc_mck_cycles(t2, mck_hz);
-       data_float = calc_mck_cycles(t6z, mck_hz);
-
-       pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n",
-            cycle, setup, pulse, data_float);
-
-       set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy);
-}
-
-static void at91_ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
-                               void *buf, unsigned int len)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-       u8 chipselect = hwif->select_data;
-       unsigned long mode;
-
-       pdbg("cs %u buf %p len %d\n", chipselect, buf, len);
-
-       len++;
-
-       enter_16bit(chipselect, mode);
-       readsw((void __iomem *)io_ports->data_addr, buf, len / 2);
-       leave_16bit(chipselect, mode);
-}
-
-static void at91_ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
-                                void *buf, unsigned int len)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-       u8 chipselect = hwif->select_data;
-       unsigned long mode;
-
-       pdbg("cs %u buf %p len %d\n", chipselect,  buf, len);
-
-       enter_16bit(chipselect, mode);
-       writesw((void __iomem *)io_ports->data_addr, buf, len / 2);
-       leave_16bit(chipselect, mode);
-}
-
-static void at91_ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
-{
-       struct ide_timing *timing;
-       u8 chipselect = hwif->select_data;
-       int use_iordy = 0;
-       const u8 pio = drive->pio_mode - XFER_PIO_0;
-
-       pdbg("chipselect %u pio %u\n", chipselect, pio);
-
-       timing = ide_timing_find_mode(XFER_PIO_0 + pio);
-       BUG_ON(!timing);
-
-       if (ide_pio_need_iordy(drive, pio))
-               use_iordy = 1;
-
-       apply_timings(chipselect, pio, timing, use_iordy);
-}
-
-static const struct ide_tp_ops at91_ide_tp_ops = {
-       .exec_command   = ide_exec_command,
-       .read_status    = ide_read_status,
-       .read_altstatus = ide_read_altstatus,
-       .write_devctl   = ide_write_devctl,
-
-       .dev_select     = ide_dev_select,
-       .tf_load        = ide_tf_load,
-       .tf_read        = ide_tf_read,
-
-       .input_data     = at91_ide_input_data,
-       .output_data    = at91_ide_output_data,
-};
-
-static const struct ide_port_ops at91_ide_port_ops = {
-       .set_pio_mode   = at91_ide_set_pio_mode,
-};
-
-static const struct ide_port_info at91_ide_port_info __initdata = {
-       .port_ops       = &at91_ide_port_ops,
-       .tp_ops         = &at91_ide_tp_ops,
-       .host_flags     = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE |
-                         IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS,
-       .pio_mask       = ATA_PIO6,
-       .chipset        = ide_generic,
-};
-
-/*
- * If interrupt is delivered through GPIO, IRQ are triggered on falling
- * and rising edge of signal. Whereas IDE device request interrupt on high
- * level (rising edge in our case). This mean we have fake interrupts, so
- * we need to check interrupt pin and exit instantly from ISR when line
- * is on low level.
- */
-
-irqreturn_t at91_irq_handler(int irq, void *dev_id)
-{
-       int ntries = 8;
-       int pin_val1, pin_val2;
-
-       /* additional deglitch, line can be noisy in badly designed PCB */
-       do {
-               pin_val1 = at91_get_gpio_value(irq);
-               pin_val2 = at91_get_gpio_value(irq);
-       } while (pin_val1 != pin_val2 && --ntries > 0);
-
-       if (pin_val1 == 0 || ntries <= 0)
-               return IRQ_HANDLED;
-
-       return ide_intr(irq, dev_id);
-}
-
-static int __init at91_ide_probe(struct platform_device *pdev)
-{
-       int ret;
-       struct ide_hw hw, *hws[] = { &hw };
-       struct ide_host *host;
-       struct resource *res;
-       unsigned long tf_base = 0, ctl_base = 0;
-       struct at91_cf_data *board = pdev->dev.platform_data;
-
-       if (!board)
-               return -ENODEV;
-
-       if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) {
-               perr("no device detected\n");
-               return -ENODEV;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               perr("can't get memory resource\n");
-               return -ENODEV;
-       }
-
-       if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE,
-                                    REGS_SIZE, "ide") ||
-           !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE,
-                                    REGS_SIZE, "alt")) {
-               perr("memory resources in use\n");
-               return -EBUSY;
-       }
-
-       pdbg("chipselect %u irq %u res %08lx\n", board->chipselect,
-            board->irq_pin, (unsigned long) res->start);
-
-       tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE,
-                                              REGS_SIZE);
-       ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE,
-                                               REGS_SIZE);
-       if (!tf_base || !ctl_base) {
-               perr("can't map memory regions\n");
-               return -EBUSY;
-       }
-
-       memset(&hw, 0, sizeof(hw));
-
-       if (board->flags & AT91_IDE_SWAP_A0_A2) {
-               /* workaround for stupid hardware bug */
-               hw.io_ports.data_addr   = tf_base + 0;
-               hw.io_ports.error_addr  = tf_base + 4;
-               hw.io_ports.nsect_addr  = tf_base + 2;
-               hw.io_ports.lbal_addr   = tf_base + 6;
-               hw.io_ports.lbam_addr   = tf_base + 1;
-               hw.io_ports.lbah_addr   = tf_base + 5;
-               hw.io_ports.device_addr = tf_base + 3;
-               hw.io_ports.command_addr = tf_base + 7;
-               hw.io_ports.ctl_addr    = ctl_base + 3;
-       } else
-               ide_std_init_ports(&hw, tf_base, ctl_base + 6);
-
-       hw.irq = board->irq_pin;
-       hw.dev = &pdev->dev;
-
-       host = ide_host_alloc(&at91_ide_port_info, hws, 1);
-       if (!host) {
-               perr("failed to allocate ide host\n");
-               return -ENOMEM;
-       }
-
-       /* setup Static Memory Controller - PIO 0 as default */
-       apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0);
-
-       /* with GPIO interrupt we have to do quirks in handler */
-       if (gpio_is_valid(board->irq_pin))
-               host->irq_handler = at91_irq_handler;
-
-       host->ports[0]->select_data = board->chipselect;
-
-       ret = ide_host_register(host, &at91_ide_port_info, hws);
-       if (ret) {
-               perr("failed to register ide host\n");
-               goto err_free_host;
-       }
-       platform_set_drvdata(pdev, host);
-       return 0;
-
-err_free_host:
-       ide_host_free(host);
-       return ret;
-}
-
-static int __exit at91_ide_remove(struct platform_device *pdev)
-{
-       struct ide_host *host = platform_get_drvdata(pdev);
-
-       ide_host_remove(host);
-       return 0;
-}
-
-static struct platform_driver at91_ide_driver = {
-       .driver = {
-               .name = DRV_NAME,
-               .owner = THIS_MODULE,
-       },
-       .remove = __exit_p(at91_ide_remove),
-};
-
-static int __init at91_ide_init(void)
-{
-       return platform_driver_probe(&at91_ide_driver, at91_ide_probe);
-}
-
-static void __exit at91_ide_exit(void)
-{
-       platform_driver_unregister(&at91_ide_driver);
-}
-
-module_init(at91_ide_init);
-module_exit(at91_ide_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Stanislaw Gruszka <stf_xl@wp.pl>");
-
index 5d2f8e13cf0e670e83b48b6dc243402d781b9758..54ab97bae0425f85f1a7df4982f56c3d74643694 100644 (file)
@@ -197,7 +197,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .enter = &intel_idle },
 };
 
-static int get_driver_data(int cstate)
+static long get_driver_data(int cstate)
 {
        int driver_data;
        switch (cstate) {
@@ -232,6 +232,7 @@ static int get_driver_data(int cstate)
  * @drv: cpuidle driver
  * @index: index of cpuidle state
  *
+ * Must be called under local_irq_disable().
  */
 static int intel_idle(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
@@ -247,8 +248,6 @@ static int intel_idle(struct cpuidle_device *dev,
 
        cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
 
-       local_irq_disable();
-
        /*
         * leave_mm() to avoid costly and often unnecessary wakeups
         * for flushing the user TLB's associated with the active mm.
@@ -348,7 +347,8 @@ static int intel_idle_probe(void)
        cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
 
        if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
-               !(ecx & CPUID5_ECX_INTERRUPT_BREAK))
+           !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
+           !mwait_substates)
                        return -ENODEV;
 
        pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
@@ -394,7 +394,7 @@ static int intel_idle_probe(void)
        if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
                lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
        else {
-               smp_call_function(__setup_broadcast_timer, (void *)true, 1);
+               on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
                register_cpu_notifier(&setup_broadcast_notifier);
        }
 
@@ -471,71 +471,67 @@ static int intel_idle_cpuidle_driver_init(void)
        }
 
        if (auto_demotion_disable_flags)
-               smp_call_function(auto_demotion_disable, NULL, 1);
+               on_each_cpu(auto_demotion_disable, NULL, 1);
 
        return 0;
 }
 
 
 /*
- * intel_idle_cpuidle_devices_init()
+ * intel_idle_cpu_init()
  * allocate, initialize, register cpuidle_devices
+ * @cpu: cpu/core to initialize
  */
-static int intel_idle_cpuidle_devices_init(void)
+int intel_idle_cpu_init(int cpu)
 {
-       int i, cstate;
+       int cstate;
        struct cpuidle_device *dev;
 
-       intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
-       if (intel_idle_cpuidle_devices == NULL)
-               return -ENOMEM;
-
-       for_each_online_cpu(i) {
-               dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
+       dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
 
-               dev->state_count = 1;
+       dev->state_count = 1;
 
-               for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
-                       int num_substates;
+       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;
-                       }
+               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) {
-                               continue;
-                       }
+               /* 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)
+                       continue;
 
-                       dev->states_usage[dev->state_count].driver_data =
-                               (void *)get_driver_data(cstate);
+               dev->states_usage[dev->state_count].driver_data =
+                       (void *)get_driver_data(cstate);
 
                        dev->state_count += 1;
                }
+       dev->cpu = cpu;
 
-               dev->cpu = i;
-               if (cpuidle_register_device(dev)) {
-                       pr_debug(PREFIX "cpuidle_register_device %d failed!\n",
-                                i);
-                       intel_idle_cpuidle_devices_uninit();
-                       return -EIO;
-               }
+       if (cpuidle_register_device(dev)) {
+               pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
+               intel_idle_cpuidle_devices_uninit();
+               return -EIO;
        }
 
+       if (auto_demotion_disable_flags)
+               smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
+
        return 0;
 }
-
+EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
 
 static int __init intel_idle_init(void)
 {
-       int retval;
+       int retval, i;
 
        /* Do not load intel_idle at all for now if idle= is passed */
        if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -553,10 +549,16 @@ static int __init intel_idle_init(void)
                return retval;
        }
 
-       retval = intel_idle_cpuidle_devices_init();
-       if (retval) {
-               cpuidle_unregister_driver(&intel_idle_driver);
-               return retval;
+       intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+       if (intel_idle_cpuidle_devices == NULL)
+               return -ENOMEM;
+
+       for_each_online_cpu(i) {
+               retval = intel_idle_cpu_init(i);
+               if (retval) {
+                       cpuidle_unregister_driver(&intel_idle_driver);
+                       return retval;
+               }
        }
 
        return 0;
@@ -568,7 +570,7 @@ static void __exit intel_idle_exit(void)
        cpuidle_unregister_driver(&intel_idle_driver);
 
        if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
-               smp_call_function(__setup_broadcast_timer, (void *)false, 1);
+               on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
                unregister_cpu_notifier(&setup_broadcast_notifier);
        }
 
index 0f9a84c1046ab38776abe891ef0ff98ea0c19c98..eb0add311dc8be40ff8876f8b1bcd7d3f2e0b161 100644 (file)
@@ -55,6 +55,7 @@ source "drivers/infiniband/hw/nes/Kconfig"
 source "drivers/infiniband/ulp/ipoib/Kconfig"
 
 source "drivers/infiniband/ulp/srp/Kconfig"
+source "drivers/infiniband/ulp/srpt/Kconfig"
 
 source "drivers/infiniband/ulp/iser/Kconfig"
 
index 9cc7a47d3e6737f22379384ac60366ea183d65dc..a3b2d8eac86ef0089a41dff9686c4dd752b0ca4a 100644 (file)
@@ -10,4 +10,5 @@ obj-$(CONFIG_MLX4_INFINIBAND)         += hw/mlx4/
 obj-$(CONFIG_INFINIBAND_NES)           += hw/nes/
 obj-$(CONFIG_INFINIBAND_IPOIB)         += ulp/ipoib/
 obj-$(CONFIG_INFINIBAND_SRP)           += ulp/srp/
+obj-$(CONFIG_INFINIBAND_SRPT)          += ulp/srpt/
 obj-$(CONFIG_INFINIBAND_ISER)          += ulp/iser/
index b37b0c02a7b9d7d81cd5a55471e28d2780080377..5034a87cc72dc887553fdfb503e42d8f2e0005aa 100644 (file)
@@ -808,9 +808,12 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
                return PTR_ERR(ctx);
 
        if (cmd.conn_param.valid) {
-               ctx->uid = cmd.uid;
                ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+               mutex_lock(&file->mut);
                ret = rdma_accept(ctx->cm_id, &conn_param);
+               if (!ret)
+                       ctx->uid = cmd.uid;
+               mutex_unlock(&file->mut);
        } else
                ret = rdma_accept(ctx->cm_id, NULL);
 
index b930da4c0c632e64019c38b0ebcab9562e15bf65..4d27e4c3fe34badbe941e735edaf9d8fb33b61f2 100644 (file)
@@ -1485,6 +1485,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
                qp->event_handler = attr.event_handler;
                qp->qp_context    = attr.qp_context;
                qp->qp_type       = attr.qp_type;
+               atomic_set(&qp->usecnt, 0);
                atomic_inc(&pd->usecnt);
                atomic_inc(&attr.send_cq->usecnt);
                if (attr.recv_cq)
index 602b1bd723a963aa49904fc0a907d12d965b009e..575b78045aafd1b5a861f9fad753f0108dd7e5d0 100644 (file)
@@ -421,6 +421,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
                qp->uobject    = NULL;
                qp->qp_type    = qp_init_attr->qp_type;
 
+               atomic_set(&qp->usecnt, 0);
                if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
                        qp->event_handler = __ib_shared_qp_event_handler;
                        qp->qp_context = qp;
@@ -430,7 +431,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
                        qp->xrcd = qp_init_attr->xrcd;
                        atomic_inc(&qp_init_attr->xrcd->usecnt);
                        INIT_LIST_HEAD(&qp->open_list);
-                       atomic_set(&qp->usecnt, 0);
 
                        real_qp = qp;
                        qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
index b7d4216db3c35636ff91734e33d3ad0bcef357b1..a4de9d58e9b4749edda15575ed4c8a4e254678c1 100644 (file)
@@ -89,7 +89,7 @@ static int create_file(const char *name, umode_t mode,
                error = ipathfs_mknod(parent->d_inode, *dentry,
                                      mode, fops, data);
        else
-               error = PTR_ERR(dentry);
+               error = PTR_ERR(*dentry);
        mutex_unlock(&parent->d_inode->i_mutex);
 
        return error;
index 95c94d8f02543ed89631f424a3c39c31c74cfa13..259b0670b51cd6cb430c859f9012796a9c2af954 100644 (file)
@@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
                        return IB_MAD_RESULT_SUCCESS;
 
                /*
-                * Don't process SMInfo queries or vendor-specific
-                * MADs -- the SMA can't handle them.
+                * Don't process SMInfo queries -- the SMA can't handle them.
                 */
-               if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
-                   ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
-                    IB_SMP_ATTR_VENDOR_MASK))
+               if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
                        return IB_MAD_RESULT_SUCCESS;
        } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
                   in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1   ||
index 7013da5e9eda8e9df0b8511568b4b2dd18ea177b..7140199f562ead43fb9062d0c89a1faa2568dc04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 568b4f11380ae545d264a48e6fae51784ddf5533..c438e4691b3cde3ec4c3874a41c07f73ec4c59b9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 425065b36b8c4b68c160c3c7e5bcf1a6c6127081..a4972abedef1e967acafc123cfe3fe14bbbabecb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -233,6 +233,7 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
        u8 *start_ptr = &start_addr;
        u8 **start_buff = &start_ptr;
        u16 buff_len = 0;
+       struct ietf_mpa_v1 *mpa_frame;
 
        skb = dev_alloc_skb(MAX_CM_BUFFER);
        if (!skb) {
@@ -242,6 +243,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
 
        /* send an MPA reject frame */
        cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+       mpa_frame = (struct ietf_mpa_v1 *)*start_buff;
+       mpa_frame->flags |= IETF_MPA_FLAGS_REJECT;
        form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
 
        cm_node->state = NES_CM_STATE_FIN_WAIT1;
@@ -1360,8 +1363,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                                if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
                                            neigh->ha, ETH_ALEN)) {
                                        /* Mac address same as in nes_arp_table */
-                                       ip_rt_put(rt);
-                                       return rc;
+                                       goto out;
                                }
 
                                nes_manage_arp_cache(nesvnic->netdev,
@@ -1377,6 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                        neigh_event_send(neigh, NULL);
                }
        }
+
+out:
        rcu_read_unlock();
        ip_rt_put(rt);
        return rc;
index bdfa1fbb35fcea66d1190cc94b237554c029006b..4646e66660874c4a6b2a5b9a4290c0132096e9f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index b4393a16099dc69df36fa5f9f2f19d42e2b33d4f..a69eef16d72d035023813c3b5af0c1174266c986 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 055f4b545df00a73069da6978a0164895e17754c..d42c9f435b1b7a62ad55a331c1f6bc76c84fdbab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 0b590e152c6abeeb84e78130a68d62ab742eca5f..d748e4b31b8ddf2de875fbd57e7e3277ed0171f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+* Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
index b3b2a240c6e9471410ea3b4a6286849186744c92..3ba7be36945207bce1448d2edb24cab2783bfa88 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel-NE, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 8c8af254555a2282642a6cc3bacf3597d5628044..4f7f701c4a817c6829646338edbeaedcd5e68410 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2010 Intel-NE, Inc.  All rights reserved.
+* Copyright (c) 2006 - 2011 Intel-NE, Inc.  All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
index 4b3fa711a2470edc4485f286a3ae4ced7adec74b..f3a3ecf8d09ebfbff9bcc37b1a4beac97d60ebeb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 71e133ab209b3c30522681eb10ba163d112f0190..4926de744488e71b4ec6e618825ed43218b2f519 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
index 8b4c2ff548887e967c567a600e50c828aa7946d8..e98f4fc0b7683230136490c5fdf0f3567c01901d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 5095bc41c6ccdd9203f6259a3a1be294aca9b563..0927b5cc65d33ac36850a1396c23e1b046b54f6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -3427,6 +3427,8 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
                        set_wqe_32bit_value(wqe->wqe_words,
                                            NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
                                            ib_wr->wr.fast_reg.length);
+                       set_wqe_32bit_value(wqe->wqe_words,
+                                           NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
                        set_wqe_32bit_value(wqe->wqe_words,
                                            NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
                                            ib_wr->wr.fast_reg.rkey);
@@ -3724,7 +3726,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
                                                entry->opcode = IB_WC_SEND;
                                                break;
                                        case NES_IWARP_SQ_OP_LOCINV:
-                                               entry->opcode = IB_WR_LOCAL_INV;
+                                               entry->opcode = IB_WC_LOCAL_INV;
                                                break;
                                        case NES_IWARP_SQ_OP_FAST_REG:
                                                entry->opcode = IB_WC_FAST_REG_MR;
index fe6b6e92fa901de9d4354de95783610cc271d571..0eff7c44d76b00bbcb1bbe06602dd54606d390ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 4f18e2d332dfd79ba8dcfc66a6c9251347a562c1..d0c64d514813909c7a863a0f29939e64123b7cba 100644 (file)
@@ -2105,7 +2105,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd)
        dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,
                                        dd->rcd[0]->rcvhdrq_size,
                                        &dd->cspec->dummy_hdrq_phys,
-                                       GFP_KERNEL | __GFP_COMP);
+                                       GFP_ATOMIC | __GFP_COMP);
        if (!dd->cspec->dummy_hdrq) {
                qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");
                /* fallback to just 0'ing */
index f695061d688e06ce026c312c79415f04a51aac70..0fde788e110087fefa825d6f7b9353fbbb572bd2 100644 (file)
@@ -560,7 +560,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
  * BIOS may not set PCIe bus-utilization parameters for best performance.
  * Check and optionally adjust them to maximize our throughput.
  */
-static int qib_pcie_caps = 0x51;
+static int qib_pcie_caps;
 module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);
 MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)");
 
index b3cc1e062b174a583933572621acb8d5ca4ac7d7..86df632ea6121f94382071de8e0a17258a361a7c 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/mutex.h>
 
 #include <net/neighbour.h>
+#include <net/sch_generic.h>
 
 #include <linux/atomic.h>
 
@@ -117,8 +118,9 @@ struct ipoib_header {
        u16     reserved;
 };
 
-struct ipoib_pseudoheader {
-       u8  hwaddr[INFINIBAND_ALEN];
+struct ipoib_cb {
+       struct qdisc_skb_cb     qdisc_cb;
+       u8                      hwaddr[INFINIBAND_ALEN];
 };
 
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
index 3514ca05deea34439f8b1ecc992a50c5e66d5d06..3974c290b667514ba8b2ea03d71367bc1650795a 100644 (file)
@@ -653,7 +653,7 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct neighbour *n, struct n
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
-                            struct ipoib_pseudoheader *phdr)
+                            struct ipoib_cb *cb)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_path *path;
@@ -661,17 +661,15 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       path = __path_find(dev, phdr->hwaddr + 4);
+       path = __path_find(dev, cb->hwaddr + 4);
        if (!path || !path->valid) {
                int new_path = 0;
 
                if (!path) {
-                       path = path_rec_create(dev, phdr->hwaddr + 4);
+                       path = path_rec_create(dev, cb->hwaddr + 4);
                        new_path = 1;
                }
                if (path) {
-                       /* put pseudoheader back on for next time */
-                       skb_push(skb, sizeof *phdr);
                        __skb_queue_tail(&path->queue, skb);
 
                        if (!path->query && path_rec_start(dev, path)) {
@@ -695,12 +693,10 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
                          be16_to_cpu(path->pathrec.dlid));
 
                spin_unlock_irqrestore(&priv->lock, flags);
-               ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
+               ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));
                return;
        } else if ((path->query || !path_rec_start(dev, path)) &&
                   skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
-               /* put pseudoheader back on for next time */
-               skb_push(skb, sizeof *phdr);
                __skb_queue_tail(&path->queue, skb);
        } else {
                ++dev->stats.tx_dropped;
@@ -774,16 +770,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        dev_kfree_skb_any(skb);
                }
        } else {
-               struct ipoib_pseudoheader *phdr =
-                       (struct ipoib_pseudoheader *) skb->data;
-               skb_pull(skb, sizeof *phdr);
+               struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
 
-               if (phdr->hwaddr[4] == 0xff) {
+               if (cb->hwaddr[4] == 0xff) {
                        /* Add in the P_Key for multicast*/
-                       phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
-                       phdr->hwaddr[9] = priv->pkey & 0xff;
+                       cb->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+                       cb->hwaddr[9] = priv->pkey & 0xff;
 
-                       ipoib_mcast_send(dev, phdr->hwaddr + 4, skb);
+                       ipoib_mcast_send(dev, cb->hwaddr + 4, skb);
                } else {
                        /* unicast GID -- should be ARP or RARP reply */
 
@@ -792,14 +786,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
                                           skb_dst(skb) ? "neigh" : "dst",
                                           be16_to_cpup((__be16 *) skb->data),
-                                          IPOIB_QPN(phdr->hwaddr),
-                                          phdr->hwaddr + 4);
+                                          IPOIB_QPN(cb->hwaddr),
+                                          cb->hwaddr + 4);
                                dev_kfree_skb_any(skb);
                                ++dev->stats.tx_dropped;
                                goto unlock;
                        }
 
-                       unicast_arp_send(skb, dev, phdr);
+                       unicast_arp_send(skb, dev, cb);
                }
        }
 unlock:
@@ -825,8 +819,6 @@ static int ipoib_hard_header(struct sk_buff *skb,
                             const void *daddr, const void *saddr, unsigned len)
 {
        struct ipoib_header *header;
-       struct dst_entry *dst;
-       struct neighbour *n;
 
        header = (struct ipoib_header *) skb_push(skb, sizeof *header);
 
@@ -834,18 +826,13 @@ static int ipoib_hard_header(struct sk_buff *skb,
        header->reserved = 0;
 
        /*
-        * If we don't have a neighbour structure, stuff the
-        * destination address onto the front of the skb so we can
-        * figure out where to send the packet later.
+        * If we don't have a dst_entry structure, stuff the
+        * destination address into skb->cb so we can figure out where
+        * to send the packet later.
         */
-       dst = skb_dst(skb);
-       n = NULL;
-       if (dst)
-               n = dst_get_neighbour_noref_raw(dst);
-       if ((!dst || !n) && daddr) {
-               struct ipoib_pseudoheader *phdr =
-                       (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
-               memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
+       if (!skb_dst(skb)) {
+               struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
+               memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
        }
 
        return 0;
@@ -1021,11 +1008,7 @@ static void ipoib_setup(struct net_device *dev)
 
        dev->flags              |= IFF_BROADCAST | IFF_MULTICAST;
 
-       /*
-        * We add in INFINIBAND_ALEN to allow for the destination
-        * address "pseudoheader" for skbs without neighbour struct.
-        */
-       dev->hard_header_len     = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
+       dev->hard_header_len     = IPOIB_ENCAP_LEN;
        dev->addr_len            = INFINIBAND_ALEN;
        dev->type                = ARPHRD_INFINIBAND;
        dev->tx_queue_len        = ipoib_sendq_size * 2;
index f7ff9dd66cda319bdbde38e0e6ce92cab6fe3216..20ebc6fd1bb9e0dc16f7bf954a16eb9a149d1dd9 100644 (file)
@@ -262,21 +262,13 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
        netif_tx_lock_bh(dev);
        while (!skb_queue_empty(&mcast->pkt_queue)) {
                struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
-               struct dst_entry *dst = skb_dst(skb);
-               struct neighbour *n = NULL;
 
                netif_tx_unlock_bh(dev);
 
                skb->dev = dev;
-               if (dst)
-                       n = dst_get_neighbour_noref_raw(dst);
-               if (!dst || !n) {
-                       /* put pseudoheader back on for next time */
-                       skb_push(skb, sizeof (struct ipoib_pseudoheader));
-               }
-
                if (dev_queue_xmit(skb))
                        ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
+
                netif_tx_lock_bh(dev);
        }
        netif_tx_unlock_bh(dev);
diff --git a/drivers/infiniband/ulp/srpt/Kconfig b/drivers/infiniband/ulp/srpt/Kconfig
new file mode 100644 (file)
index 0000000..31ee83d
--- /dev/null
@@ -0,0 +1,12 @@
+config INFINIBAND_SRPT
+       tristate "InfiniBand SCSI RDMA Protocol target support"
+       depends on INFINIBAND && TARGET_CORE
+       ---help---
+
+         Support for the SCSI RDMA Protocol (SRP) Target driver. The
+         SRP protocol is a protocol that allows an initiator to access
+         a block storage device on another host (target) over a network
+         that supports the RDMA protocol. Currently the RDMA protocol is
+         supported by InfiniBand and by iWarp network hardware. More
+         information about the SRP protocol can be found on the website
+         of the INCITS T10 technical committee (http://www.t10.org/).
diff --git a/drivers/infiniband/ulp/srpt/Makefile b/drivers/infiniband/ulp/srpt/Makefile
new file mode 100644 (file)
index 0000000..e3ee4bd
--- /dev/null
@@ -0,0 +1,2 @@
+ccflags-y                      := -Idrivers/target
+obj-$(CONFIG_INFINIBAND_SRPT)  += ib_srpt.o
diff --git a/drivers/infiniband/ulp/srpt/ib_dm_mad.h b/drivers/infiniband/ulp/srpt/ib_dm_mad.h
new file mode 100644 (file)
index 0000000..fb1de1f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef IB_DM_MAD_H
+#define IB_DM_MAD_H
+
+#include <linux/types.h>
+
+#include <rdma/ib_mad.h>
+
+enum {
+       /*
+        * See also section 13.4.7 Status Field, table 115 MAD Common Status
+        * Field Bit Values and also section 16.3.1.1 Status Field in the
+        * InfiniBand Architecture Specification.
+        */
+       DM_MAD_STATUS_UNSUP_METHOD = 0x0008,
+       DM_MAD_STATUS_UNSUP_METHOD_ATTR = 0x000c,
+       DM_MAD_STATUS_INVALID_FIELD = 0x001c,
+       DM_MAD_STATUS_NO_IOC = 0x0100,
+
+       /*
+        * See also the Device Management chapter, section 16.3.3 Attributes,
+        * table 279 Device Management Attributes in the InfiniBand
+        * Architecture Specification.
+        */
+       DM_ATTR_CLASS_PORT_INFO = 0x01,
+       DM_ATTR_IOU_INFO = 0x10,
+       DM_ATTR_IOC_PROFILE = 0x11,
+       DM_ATTR_SVC_ENTRIES = 0x12
+};
+
+struct ib_dm_hdr {
+       u8 reserved[28];
+};
+
+/*
+ * Structure of management datagram sent by the SRP target implementation.
+ * Contains a management datagram header, reliable multi-packet transaction
+ * protocol (RMPP) header and ib_dm_hdr. Notes:
+ * - The SRP target implementation does not use RMPP or ib_dm_hdr when sending
+ *   management datagrams.
+ * - The header size must be exactly 64 bytes (IB_MGMT_DEVICE_HDR), since this
+ *   is the header size that is passed to ib_create_send_mad() in ib_srpt.c.
+ * - The maximum supported size for a management datagram when not using RMPP
+ *   is 256 bytes -- 64 bytes header and 192 (IB_MGMT_DEVICE_DATA) bytes data.
+ */
+struct ib_dm_mad {
+       struct ib_mad_hdr mad_hdr;
+       struct ib_rmpp_hdr rmpp_hdr;
+       struct ib_dm_hdr dm_hdr;
+       u8 data[IB_MGMT_DEVICE_DATA];
+};
+
+/*
+ * IOUnitInfo as defined in section 16.3.3.3 IOUnitInfo of the InfiniBand
+ * Architecture Specification.
+ */
+struct ib_dm_iou_info {
+       __be16 change_id;
+       u8 max_controllers;
+       u8 op_rom;
+       u8 controller_list[128];
+};
+
+/*
+ * IOControllerprofile as defined in section 16.3.3.4 IOControllerProfile of
+ * the InfiniBand Architecture Specification.
+ */
+struct ib_dm_ioc_profile {
+       __be64 guid;
+       __be32 vendor_id;
+       __be32 device_id;
+       __be16 device_version;
+       __be16 reserved1;
+       __be32 subsys_vendor_id;
+       __be32 subsys_device_id;
+       __be16 io_class;
+       __be16 io_subclass;
+       __be16 protocol;
+       __be16 protocol_version;
+       __be16 service_conn;
+       __be16 initiators_supported;
+       __be16 send_queue_depth;
+       u8 reserved2;
+       u8 rdma_read_depth;
+       __be32 send_size;
+       __be32 rdma_size;
+       u8 op_cap_mask;
+       u8 svc_cap_mask;
+       u8 num_svc_entries;
+       u8 reserved3[9];
+       u8 id_string[64];
+};
+
+struct ib_dm_svc_entry {
+       u8 name[40];
+       __be64 id;
+};
+
+/*
+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
+ * Specification. See also section B.7, table B.8 in the T10 SRP r16a document.
+ */
+struct ib_dm_svc_entries {
+       struct ib_dm_svc_entry service_entries[4];
+};
+
+#endif
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
new file mode 100644 (file)
index 0000000..2b73d43
--- /dev/null
@@ -0,0 +1,4070 @@
+/*
+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc.  All rights reserved.
+ * Copyright (C) 2008 - 2011 Bart Van Assche <bvanassche@acm.org>.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/kthread.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/atomic.h>
+#include <scsi/scsi_tcq.h>
+#include <target/configfs_macros.h>
+#include <target/target_core_base.h>
+#include <target/target_core_fabric_configfs.h>
+#include <target/target_core_fabric.h>
+#include <target/target_core_configfs.h>
+#include "ib_srpt.h"
+
+/* Name of this kernel module. */
+#define DRV_NAME               "ib_srpt"
+#define DRV_VERSION            "2.0.0"
+#define DRV_RELDATE            "2011-02-14"
+
+#define SRPT_ID_STRING "Linux SRP target"
+
+#undef pr_fmt
+#define pr_fmt(fmt) DRV_NAME " " fmt
+
+MODULE_AUTHOR("Vu Pham and Bart Van Assche");
+MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target "
+                  "v" DRV_VERSION " (" DRV_RELDATE ")");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/*
+ * Global Variables
+ */
+
+static u64 srpt_service_guid;
+static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */
+static LIST_HEAD(srpt_dev_list);       /* List of srpt_device structures. */
+
+static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
+module_param(srp_max_req_size, int, 0444);
+MODULE_PARM_DESC(srp_max_req_size,
+                "Maximum size of SRP request messages in bytes.");
+
+static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
+module_param(srpt_srq_size, int, 0444);
+MODULE_PARM_DESC(srpt_srq_size,
+                "Shared receive queue (SRQ) size.");
+
+static int srpt_get_u64_x(char *buffer, struct kernel_param *kp)
+{
+       return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg);
+}
+module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
+                 0444);
+MODULE_PARM_DESC(srpt_service_guid,
+                "Using this value for ioc_guid, id_ext, and cm_listen_id"
+                " instead of using the node_guid of the first HCA.");
+
+static struct ib_client srpt_client;
+static struct target_fabric_configfs *srpt_target;
+static void srpt_release_channel(struct srpt_rdma_ch *ch);
+static int srpt_queue_status(struct se_cmd *cmd);
+
+/**
+ * opposite_dma_dir() - Swap DMA_TO_DEVICE and DMA_FROM_DEVICE.
+ */
+static inline
+enum dma_data_direction opposite_dma_dir(enum dma_data_direction dir)
+{
+       switch (dir) {
+       case DMA_TO_DEVICE:     return DMA_FROM_DEVICE;
+       case DMA_FROM_DEVICE:   return DMA_TO_DEVICE;
+       default:                return dir;
+       }
+}
+
+/**
+ * srpt_sdev_name() - Return the name associated with the HCA.
+ *
+ * Examples are ib0, ib1, ...
+ */
+static inline const char *srpt_sdev_name(struct srpt_device *sdev)
+{
+       return sdev->device->name;
+}
+
+static enum rdma_ch_state srpt_get_ch_state(struct srpt_rdma_ch *ch)
+{
+       unsigned long flags;
+       enum rdma_ch_state state;
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       state = ch->state;
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+       return state;
+}
+
+static enum rdma_ch_state
+srpt_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state new_state)
+{
+       unsigned long flags;
+       enum rdma_ch_state prev;
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       prev = ch->state;
+       ch->state = new_state;
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+       return prev;
+}
+
+/**
+ * srpt_test_and_set_ch_state() - Test and set the channel state.
+ *
+ * Returns true if and only if the channel state has been set to the new state.
+ */
+static bool
+srpt_test_and_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state old,
+                          enum rdma_ch_state new)
+{
+       unsigned long flags;
+       enum rdma_ch_state prev;
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       prev = ch->state;
+       if (prev == old)
+               ch->state = new;
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+       return prev == old;
+}
+
+/**
+ * srpt_event_handler() - Asynchronous IB event callback function.
+ *
+ * Callback function called by the InfiniBand core when an asynchronous IB
+ * event occurs. This callback may occur in interrupt context. See also
+ * section 11.5.2, Set Asynchronous Event Handler in the InfiniBand
+ * Architecture Specification.
+ */
+static void srpt_event_handler(struct ib_event_handler *handler,
+                              struct ib_event *event)
+{
+       struct srpt_device *sdev;
+       struct srpt_port *sport;
+
+       sdev = ib_get_client_data(event->device, &srpt_client);
+       if (!sdev || sdev->device != event->device)
+               return;
+
+       pr_debug("ASYNC event= %d on device= %s\n", event->event,
+                srpt_sdev_name(sdev));
+
+       switch (event->event) {
+       case IB_EVENT_PORT_ERR:
+               if (event->element.port_num <= sdev->device->phys_port_cnt) {
+                       sport = &sdev->port[event->element.port_num - 1];
+                       sport->lid = 0;
+                       sport->sm_lid = 0;
+               }
+               break;
+       case IB_EVENT_PORT_ACTIVE:
+       case IB_EVENT_LID_CHANGE:
+       case IB_EVENT_PKEY_CHANGE:
+       case IB_EVENT_SM_CHANGE:
+       case IB_EVENT_CLIENT_REREGISTER:
+               /* Refresh port data asynchronously. */
+               if (event->element.port_num <= sdev->device->phys_port_cnt) {
+                       sport = &sdev->port[event->element.port_num - 1];
+                       if (!sport->lid && !sport->sm_lid)
+                               schedule_work(&sport->work);
+               }
+               break;
+       default:
+               printk(KERN_ERR "received unrecognized IB event %d\n",
+                      event->event);
+               break;
+       }
+}
+
+/**
+ * srpt_srq_event() - SRQ event callback function.
+ */
+static void srpt_srq_event(struct ib_event *event, void *ctx)
+{
+       printk(KERN_INFO "SRQ event %d\n", event->event);
+}
+
+/**
+ * srpt_qp_event() - QP event callback function.
+ */
+static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
+{
+       pr_debug("QP event %d on cm_id=%p sess_name=%s state=%d\n",
+                event->event, ch->cm_id, ch->sess_name, srpt_get_ch_state(ch));
+
+       switch (event->event) {
+       case IB_EVENT_COMM_EST:
+               ib_cm_notify(ch->cm_id, event->event);
+               break;
+       case IB_EVENT_QP_LAST_WQE_REACHED:
+               if (srpt_test_and_set_ch_state(ch, CH_DRAINING,
+                                              CH_RELEASING))
+                       srpt_release_channel(ch);
+               else
+                       pr_debug("%s: state %d - ignored LAST_WQE.\n",
+                                ch->sess_name, srpt_get_ch_state(ch));
+               break;
+       default:
+               printk(KERN_ERR "received unrecognized IB QP event %d\n",
+                      event->event);
+               break;
+       }
+}
+
+/**
+ * srpt_set_ioc() - Helper function for initializing an IOUnitInfo structure.
+ *
+ * @slot: one-based slot number.
+ * @value: four-bit value.
+ *
+ * Copies the lowest four bits of value in element slot of the array of four
+ * bit elements called c_list (controller list). The index slot is one-based.
+ */
+static void srpt_set_ioc(u8 *c_list, u32 slot, u8 value)
+{
+       u16 id;
+       u8 tmp;
+
+       id = (slot - 1) / 2;
+       if (slot & 0x1) {
+               tmp = c_list[id] & 0xf;
+               c_list[id] = (value << 4) | tmp;
+       } else {
+               tmp = c_list[id] & 0xf0;
+               c_list[id] = (value & 0xf) | tmp;
+       }
+}
+
+/**
+ * srpt_get_class_port_info() - Copy ClassPortInfo to a management datagram.
+ *
+ * See also section 16.3.3.1 ClassPortInfo in the InfiniBand Architecture
+ * Specification.
+ */
+static void srpt_get_class_port_info(struct ib_dm_mad *mad)
+{
+       struct ib_class_port_info *cif;
+
+       cif = (struct ib_class_port_info *)mad->data;
+       memset(cif, 0, sizeof *cif);
+       cif->base_version = 1;
+       cif->class_version = 1;
+       cif->resp_time_value = 20;
+
+       mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_get_iou() - Write IOUnitInfo to a management datagram.
+ *
+ * See also section 16.3.3.3 IOUnitInfo in the InfiniBand Architecture
+ * Specification. See also section B.7, table B.6 in the SRP r16a document.
+ */
+static void srpt_get_iou(struct ib_dm_mad *mad)
+{
+       struct ib_dm_iou_info *ioui;
+       u8 slot;
+       int i;
+
+       ioui = (struct ib_dm_iou_info *)mad->data;
+       ioui->change_id = __constant_cpu_to_be16(1);
+       ioui->max_controllers = 16;
+
+       /* set present for slot 1 and empty for the rest */
+       srpt_set_ioc(ioui->controller_list, 1, 1);
+       for (i = 1, slot = 2; i < 16; i++, slot++)
+               srpt_set_ioc(ioui->controller_list, slot, 0);
+
+       mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_get_ioc() - Write IOControllerprofile to a management datagram.
+ *
+ * See also section 16.3.3.4 IOControllerProfile in the InfiniBand
+ * Architecture Specification. See also section B.7, table B.7 in the SRP
+ * r16a document.
+ */
+static void srpt_get_ioc(struct srpt_port *sport, u32 slot,
+                        struct ib_dm_mad *mad)
+{
+       struct srpt_device *sdev = sport->sdev;
+       struct ib_dm_ioc_profile *iocp;
+
+       iocp = (struct ib_dm_ioc_profile *)mad->data;
+
+       if (!slot || slot > 16) {
+               mad->mad_hdr.status
+                       = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
+               return;
+       }
+
+       if (slot > 2) {
+               mad->mad_hdr.status
+                       = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
+               return;
+       }
+
+       memset(iocp, 0, sizeof *iocp);
+       strcpy(iocp->id_string, SRPT_ID_STRING);
+       iocp->guid = cpu_to_be64(srpt_service_guid);
+       iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
+       iocp->device_id = cpu_to_be32(sdev->dev_attr.vendor_part_id);
+       iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver);
+       iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
+       iocp->subsys_device_id = 0x0;
+       iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS);
+       iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS);
+       iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL);
+       iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION);
+       iocp->send_queue_depth = cpu_to_be16(sdev->srq_size);
+       iocp->rdma_read_depth = 4;
+       iocp->send_size = cpu_to_be32(srp_max_req_size);
+       iocp->rdma_size = cpu_to_be32(min(sport->port_attrib.srp_max_rdma_size,
+                                         1U << 24));
+       iocp->num_svc_entries = 1;
+       iocp->op_cap_mask = SRP_SEND_TO_IOC | SRP_SEND_FROM_IOC |
+               SRP_RDMA_READ_FROM_IOC | SRP_RDMA_WRITE_FROM_IOC;
+
+       mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_get_svc_entries() - Write ServiceEntries to a management datagram.
+ *
+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
+ * Specification. See also section B.7, table B.8 in the SRP r16a document.
+ */
+static void srpt_get_svc_entries(u64 ioc_guid,
+                                u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad)
+{
+       struct ib_dm_svc_entries *svc_entries;
+
+       WARN_ON(!ioc_guid);
+
+       if (!slot || slot > 16) {
+               mad->mad_hdr.status
+                       = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
+               return;
+       }
+
+       if (slot > 2 || lo > hi || hi > 1) {
+               mad->mad_hdr.status
+                       = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
+               return;
+       }
+
+       svc_entries = (struct ib_dm_svc_entries *)mad->data;
+       memset(svc_entries, 0, sizeof *svc_entries);
+       svc_entries->service_entries[0].id = cpu_to_be64(ioc_guid);
+       snprintf(svc_entries->service_entries[0].name,
+                sizeof(svc_entries->service_entries[0].name),
+                "%s%016llx",
+                SRP_SERVICE_NAME_PREFIX,
+                ioc_guid);
+
+       mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_mgmt_method_get() - Process a received management datagram.
+ * @sp:      source port through which the MAD has been received.
+ * @rq_mad:  received MAD.
+ * @rsp_mad: response MAD.
+ */
+static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad,
+                                struct ib_dm_mad *rsp_mad)
+{
+       u16 attr_id;
+       u32 slot;
+       u8 hi, lo;
+
+       attr_id = be16_to_cpu(rq_mad->mad_hdr.attr_id);
+       switch (attr_id) {
+       case DM_ATTR_CLASS_PORT_INFO:
+               srpt_get_class_port_info(rsp_mad);
+               break;
+       case DM_ATTR_IOU_INFO:
+               srpt_get_iou(rsp_mad);
+               break;
+       case DM_ATTR_IOC_PROFILE:
+               slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
+               srpt_get_ioc(sp, slot, rsp_mad);
+               break;
+       case DM_ATTR_SVC_ENTRIES:
+               slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
+               hi = (u8) ((slot >> 8) & 0xff);
+               lo = (u8) (slot & 0xff);
+               slot = (u16) ((slot >> 16) & 0xffff);
+               srpt_get_svc_entries(srpt_service_guid,
+                                    slot, hi, lo, rsp_mad);
+               break;
+       default:
+               rsp_mad->mad_hdr.status =
+                   __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
+               break;
+       }
+}
+
+/**
+ * srpt_mad_send_handler() - Post MAD-send callback function.
+ */
+static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent,
+                                 struct ib_mad_send_wc *mad_wc)
+{
+       ib_destroy_ah(mad_wc->send_buf->ah);
+       ib_free_send_mad(mad_wc->send_buf);
+}
+
+/**
+ * srpt_mad_recv_handler() - MAD reception callback function.
+ */
+static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,
+                                 struct ib_mad_recv_wc *mad_wc)
+{
+       struct srpt_port *sport = (struct srpt_port *)mad_agent->context;
+       struct ib_ah *ah;
+       struct ib_mad_send_buf *rsp;
+       struct ib_dm_mad *dm_mad;
+
+       if (!mad_wc || !mad_wc->recv_buf.mad)
+               return;
+
+       ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
+                                 mad_wc->recv_buf.grh, mad_agent->port_num);
+       if (IS_ERR(ah))
+               goto err;
+
+       BUILD_BUG_ON(offsetof(struct ib_dm_mad, data) != IB_MGMT_DEVICE_HDR);
+
+       rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
+                                mad_wc->wc->pkey_index, 0,
+                                IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA,
+                                GFP_KERNEL);
+       if (IS_ERR(rsp))
+               goto err_rsp;
+
+       rsp->ah = ah;
+
+       dm_mad = rsp->mad;
+       memcpy(dm_mad, mad_wc->recv_buf.mad, sizeof *dm_mad);
+       dm_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
+       dm_mad->mad_hdr.status = 0;
+
+       switch (mad_wc->recv_buf.mad->mad_hdr.method) {
+       case IB_MGMT_METHOD_GET:
+               srpt_mgmt_method_get(sport, mad_wc->recv_buf.mad, dm_mad);
+               break;
+       case IB_MGMT_METHOD_SET:
+               dm_mad->mad_hdr.status =
+                   __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
+               break;
+       default:
+               dm_mad->mad_hdr.status =
+                   __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);
+               break;
+       }
+
+       if (!ib_post_send_mad(rsp, NULL)) {
+               ib_free_recv_mad(mad_wc);
+               /* will destroy_ah & free_send_mad in send completion */
+               return;
+       }
+
+       ib_free_send_mad(rsp);
+
+err_rsp:
+       ib_destroy_ah(ah);
+err:
+       ib_free_recv_mad(mad_wc);
+}
+
+/**
+ * srpt_refresh_port() - Configure a HCA port.
+ *
+ * Enable InfiniBand management datagram processing, update the cached sm_lid,
+ * lid and gid values, and register a callback function for processing MADs
+ * on the specified port.
+ *
+ * Note: It is safe to call this function more than once for the same port.
+ */
+static int srpt_refresh_port(struct srpt_port *sport)
+{
+       struct ib_mad_reg_req reg_req;
+       struct ib_port_modify port_modify;
+       struct ib_port_attr port_attr;
+       int ret;
+
+       memset(&port_modify, 0, sizeof port_modify);
+       port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
+       port_modify.clr_port_cap_mask = 0;
+
+       ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
+       if (ret)
+               goto err_mod_port;
+
+       ret = ib_query_port(sport->sdev->device, sport->port, &port_attr);
+       if (ret)
+               goto err_query_port;
+
+       sport->sm_lid = port_attr.sm_lid;
+       sport->lid = port_attr.lid;
+
+       ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);
+       if (ret)
+               goto err_query_port;
+
+       if (!sport->mad_agent) {
+               memset(&reg_req, 0, sizeof reg_req);
+               reg_req.mgmt_class = IB_MGMT_CLASS_DEVICE_MGMT;
+               reg_req.mgmt_class_version = IB_MGMT_BASE_VERSION;
+               set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
+               set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
+
+               sport->mad_agent = ib_register_mad_agent(sport->sdev->device,
+                                                        sport->port,
+                                                        IB_QPT_GSI,
+                                                        &reg_req, 0,
+                                                        srpt_mad_send_handler,
+                                                        srpt_mad_recv_handler,
+                                                        sport);
+               if (IS_ERR(sport->mad_agent)) {
+                       ret = PTR_ERR(sport->mad_agent);
+                       sport->mad_agent = NULL;
+                       goto err_query_port;
+               }
+       }
+
+       return 0;
+
+err_query_port:
+
+       port_modify.set_port_cap_mask = 0;
+       port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
+       ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
+
+err_mod_port:
+
+       return ret;
+}
+
+/**
+ * srpt_unregister_mad_agent() - Unregister MAD callback functions.
+ *
+ * Note: It is safe to call this function more than once for the same device.
+ */
+static void srpt_unregister_mad_agent(struct srpt_device *sdev)
+{
+       struct ib_port_modify port_modify = {
+               .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP,
+       };
+       struct srpt_port *sport;
+       int i;
+
+       for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
+               sport = &sdev->port[i - 1];
+               WARN_ON(sport->port != i);
+               if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0)
+                       printk(KERN_ERR "disabling MAD processing failed.\n");
+               if (sport->mad_agent) {
+                       ib_unregister_mad_agent(sport->mad_agent);
+                       sport->mad_agent = NULL;
+               }
+       }
+}
+
+/**
+ * srpt_alloc_ioctx() - Allocate an SRPT I/O context structure.
+ */
+static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev,
+                                          int ioctx_size, int dma_size,
+                                          enum dma_data_direction dir)
+{
+       struct srpt_ioctx *ioctx;
+
+       ioctx = kmalloc(ioctx_size, GFP_KERNEL);
+       if (!ioctx)
+               goto err;
+
+       ioctx->buf = kmalloc(dma_size, GFP_KERNEL);
+       if (!ioctx->buf)
+               goto err_free_ioctx;
+
+       ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, dma_size, dir);
+       if (ib_dma_mapping_error(sdev->device, ioctx->dma))
+               goto err_free_buf;
+
+       return ioctx;
+
+err_free_buf:
+       kfree(ioctx->buf);
+err_free_ioctx:
+       kfree(ioctx);
+err:
+       return NULL;
+}
+
+/**
+ * srpt_free_ioctx() - Free an SRPT I/O context structure.
+ */
+static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx,
+                           int dma_size, enum dma_data_direction dir)
+{
+       if (!ioctx)
+               return;
+
+       ib_dma_unmap_single(sdev->device, ioctx->dma, dma_size, dir);
+       kfree(ioctx->buf);
+       kfree(ioctx);
+}
+
+/**
+ * srpt_alloc_ioctx_ring() - Allocate a ring of SRPT I/O context structures.
+ * @sdev:       Device to allocate the I/O context ring for.
+ * @ring_size:  Number of elements in the I/O context ring.
+ * @ioctx_size: I/O context size.
+ * @dma_size:   DMA buffer size.
+ * @dir:        DMA data direction.
+ */
+static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev,
+                               int ring_size, int ioctx_size,
+                               int dma_size, enum dma_data_direction dir)
+{
+       struct srpt_ioctx **ring;
+       int i;
+
+       WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx)
+               && ioctx_size != sizeof(struct srpt_send_ioctx));
+
+       ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL);
+       if (!ring)
+               goto out;
+       for (i = 0; i < ring_size; ++i) {
+               ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, dma_size, dir);
+               if (!ring[i])
+                       goto err;
+               ring[i]->index = i;
+       }
+       goto out;
+
+err:
+       while (--i >= 0)
+               srpt_free_ioctx(sdev, ring[i], dma_size, dir);
+       kfree(ring);
+       ring = NULL;
+out:
+       return ring;
+}
+
+/**
+ * srpt_free_ioctx_ring() - Free the ring of SRPT I/O context structures.
+ */
+static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring,
+                                struct srpt_device *sdev, int ring_size,
+                                int dma_size, enum dma_data_direction dir)
+{
+       int i;
+
+       for (i = 0; i < ring_size; ++i)
+               srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir);
+       kfree(ioctx_ring);
+}
+
+/**
+ * srpt_get_cmd_state() - Get the state of a SCSI command.
+ */
+static enum srpt_command_state srpt_get_cmd_state(struct srpt_send_ioctx *ioctx)
+{
+       enum srpt_command_state state;
+       unsigned long flags;
+
+       BUG_ON(!ioctx);
+
+       spin_lock_irqsave(&ioctx->spinlock, flags);
+       state = ioctx->state;
+       spin_unlock_irqrestore(&ioctx->spinlock, flags);
+       return state;
+}
+
+/**
+ * srpt_set_cmd_state() - Set the state of a SCSI command.
+ *
+ * Does not modify the state of aborted commands. Returns the previous command
+ * state.
+ */
+static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx,
+                                                 enum srpt_command_state new)
+{
+       enum srpt_command_state previous;
+       unsigned long flags;
+
+       BUG_ON(!ioctx);
+
+       spin_lock_irqsave(&ioctx->spinlock, flags);
+       previous = ioctx->state;
+       if (previous != SRPT_STATE_DONE)
+               ioctx->state = new;
+       spin_unlock_irqrestore(&ioctx->spinlock, flags);
+
+       return previous;
+}
+
+/**
+ * srpt_test_and_set_cmd_state() - Test and set the state of a command.
+ *
+ * Returns true if and only if the previous command state was equal to 'old'.
+ */
+static bool srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx,
+                                       enum srpt_command_state old,
+                                       enum srpt_command_state new)
+{
+       enum srpt_command_state previous;
+       unsigned long flags;
+
+       WARN_ON(!ioctx);
+       WARN_ON(old == SRPT_STATE_DONE);
+       WARN_ON(new == SRPT_STATE_NEW);
+
+       spin_lock_irqsave(&ioctx->spinlock, flags);
+       previous = ioctx->state;
+       if (previous == old)
+               ioctx->state = new;
+       spin_unlock_irqrestore(&ioctx->spinlock, flags);
+       return previous == old;
+}
+
+/**
+ * srpt_post_recv() - Post an IB receive request.
+ */
+static int srpt_post_recv(struct srpt_device *sdev,
+                         struct srpt_recv_ioctx *ioctx)
+{
+       struct ib_sge list;
+       struct ib_recv_wr wr, *bad_wr;
+
+       BUG_ON(!sdev);
+       wr.wr_id = encode_wr_id(SRPT_RECV, ioctx->ioctx.index);
+
+       list.addr = ioctx->ioctx.dma;
+       list.length = srp_max_req_size;
+       list.lkey = sdev->mr->lkey;
+
+       wr.next = NULL;
+       wr.sg_list = &list;
+       wr.num_sge = 1;
+
+       return ib_post_srq_recv(sdev->srq, &wr, &bad_wr);
+}
+
+/**
+ * srpt_post_send() - Post an IB send request.
+ *
+ * Returns zero upon success and a non-zero value upon failure.
+ */
+static int srpt_post_send(struct srpt_rdma_ch *ch,
+                         struct srpt_send_ioctx *ioctx, int len)
+{
+       struct ib_sge list;
+       struct ib_send_wr wr, *bad_wr;
+       struct srpt_device *sdev = ch->sport->sdev;
+       int ret;
+
+       atomic_inc(&ch->req_lim);
+
+       ret = -ENOMEM;
+       if (unlikely(atomic_dec_return(&ch->sq_wr_avail) < 0)) {
+               printk(KERN_WARNING "IB send queue full (needed 1)\n");
+               goto out;
+       }
+
+       ib_dma_sync_single_for_device(sdev->device, ioctx->ioctx.dma, len,
+                                     DMA_TO_DEVICE);
+
+       list.addr = ioctx->ioctx.dma;
+       list.length = len;
+       list.lkey = sdev->mr->lkey;
+
+       wr.next = NULL;
+       wr.wr_id = encode_wr_id(SRPT_SEND, ioctx->ioctx.index);
+       wr.sg_list = &list;
+       wr.num_sge = 1;
+       wr.opcode = IB_WR_SEND;
+       wr.send_flags = IB_SEND_SIGNALED;
+
+       ret = ib_post_send(ch->qp, &wr, &bad_wr);
+
+out:
+       if (ret < 0) {
+               atomic_inc(&ch->sq_wr_avail);
+               atomic_dec(&ch->req_lim);
+       }
+       return ret;
+}
+
+/**
+ * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.
+ * @ioctx: Pointer to the I/O context associated with the request.
+ * @srp_cmd: Pointer to the SRP_CMD request data.
+ * @dir: Pointer to the variable to which the transfer direction will be
+ *   written.
+ * @data_len: Pointer to the variable to which the total data length of all
+ *   descriptors in the SRP_CMD request will be written.
+ *
+ * This function initializes ioctx->nrbuf and ioctx->r_bufs.
+ *
+ * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;
+ * -ENOMEM when memory allocation fails and zero upon success.
+ */
+static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx,
+                            struct srp_cmd *srp_cmd,
+                            enum dma_data_direction *dir, u64 *data_len)
+{
+       struct srp_indirect_buf *idb;
+       struct srp_direct_buf *db;
+       unsigned add_cdb_offset;
+       int ret;
+
+       /*
+        * The pointer computations below will only be compiled correctly
+        * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
+        * whether srp_cmd::add_data has been declared as a byte pointer.
+        */
+       BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
+                    && !__same_type(srp_cmd->add_data[0], (u8)0));
+
+       BUG_ON(!dir);
+       BUG_ON(!data_len);
+
+       ret = 0;
+       *data_len = 0;
+
+       /*
+        * The lower four bits of the buffer format field contain the DATA-IN
+        * buffer descriptor format, and the highest four bits contain the
+        * DATA-OUT buffer descriptor format.
+        */
+       *dir = DMA_NONE;
+       if (srp_cmd->buf_fmt & 0xf)
+               /* DATA-IN: transfer data from target to initiator (read). */
+               *dir = DMA_FROM_DEVICE;
+       else if (srp_cmd->buf_fmt >> 4)
+               /* DATA-OUT: transfer data from initiator to target (write). */
+               *dir = DMA_TO_DEVICE;
+
+       /*
+        * According to the SRP spec, the lower two bits of the 'ADDITIONAL
+        * CDB LENGTH' field are reserved and the size in bytes of this field
+        * is four times the value specified in bits 3..7. Hence the "& ~3".
+        */
+       add_cdb_offset = srp_cmd->add_cdb_len & ~3;
+       if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) ||
+           ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) {
+               ioctx->n_rbuf = 1;
+               ioctx->rbufs = &ioctx->single_rbuf;
+
+               db = (struct srp_direct_buf *)(srp_cmd->add_data
+                                              + add_cdb_offset);
+               memcpy(ioctx->rbufs, db, sizeof *db);
+               *data_len = be32_to_cpu(db->len);
+       } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
+                  ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
+               idb = (struct srp_indirect_buf *)(srp_cmd->add_data
+                                                 + add_cdb_offset);
+
+               ioctx->n_rbuf = be32_to_cpu(idb->table_desc.len) / sizeof *db;
+
+               if (ioctx->n_rbuf >
+                   (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {
+                       printk(KERN_ERR "received unsupported SRP_CMD request"
+                              " type (%u out + %u in != %u / %zu)\n",
+                              srp_cmd->data_out_desc_cnt,
+                              srp_cmd->data_in_desc_cnt,
+                              be32_to_cpu(idb->table_desc.len),
+                              sizeof(*db));
+                       ioctx->n_rbuf = 0;
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (ioctx->n_rbuf == 1)
+                       ioctx->rbufs = &ioctx->single_rbuf;
+               else {
+                       ioctx->rbufs =
+                               kmalloc(ioctx->n_rbuf * sizeof *db, GFP_ATOMIC);
+                       if (!ioctx->rbufs) {
+                               ioctx->n_rbuf = 0;
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+               }
+
+               db = idb->desc_list;
+               memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
+               *data_len = be32_to_cpu(idb->len);
+       }
+out:
+       return ret;
+}
+
+/**
+ * srpt_init_ch_qp() - Initialize queue pair attributes.
+ *
+ * Initialized the attributes of queue pair 'qp' by allowing local write,
+ * remote read and remote write. Also transitions 'qp' to state IB_QPS_INIT.
+ */
+static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)
+{
+       struct ib_qp_attr *attr;
+       int ret;
+
+       attr = kzalloc(sizeof *attr, GFP_KERNEL);
+       if (!attr)
+               return -ENOMEM;
+
+       attr->qp_state = IB_QPS_INIT;
+       attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |
+           IB_ACCESS_REMOTE_WRITE;
+       attr->port_num = ch->sport->port;
+       attr->pkey_index = 0;
+
+       ret = ib_modify_qp(qp, attr,
+                          IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PORT |
+                          IB_QP_PKEY_INDEX);
+
+       kfree(attr);
+       return ret;
+}
+
+/**
+ * srpt_ch_qp_rtr() - Change the state of a channel to 'ready to receive' (RTR).
+ * @ch: channel of the queue pair.
+ * @qp: queue pair to change the state of.
+ *
+ * Returns zero upon success and a negative value upon failure.
+ *
+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
+ * If this structure ever becomes larger, it might be necessary to allocate
+ * it dynamically instead of on the stack.
+ */
+static int srpt_ch_qp_rtr(struct srpt_rdma_ch *ch, struct ib_qp *qp)
+{
+       struct ib_qp_attr qp_attr;
+       int attr_mask;
+       int ret;
+
+       qp_attr.qp_state = IB_QPS_RTR;
+       ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
+       if (ret)
+               goto out;
+
+       qp_attr.max_dest_rd_atomic = 4;
+
+       ret = ib_modify_qp(qp, &qp_attr, attr_mask);
+
+out:
+       return ret;
+}
+
+/**
+ * srpt_ch_qp_rts() - Change the state of a channel to 'ready to send' (RTS).
+ * @ch: channel of the queue pair.
+ * @qp: queue pair to change the state of.
+ *
+ * Returns zero upon success and a negative value upon failure.
+ *
+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
+ * If this structure ever becomes larger, it might be necessary to allocate
+ * it dynamically instead of on the stack.
+ */
+static int srpt_ch_qp_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp)
+{
+       struct ib_qp_attr qp_attr;
+       int attr_mask;
+       int ret;
+
+       qp_attr.qp_state = IB_QPS_RTS;
+       ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
+       if (ret)
+               goto out;
+
+       qp_attr.max_rd_atomic = 4;
+
+       ret = ib_modify_qp(qp, &qp_attr, attr_mask);
+
+out:
+       return ret;
+}
+
+/**
+ * srpt_ch_qp_err() - Set the channel queue pair state to 'error'.
+ */
+static int srpt_ch_qp_err(struct srpt_rdma_ch *ch)
+{
+       struct ib_qp_attr qp_attr;
+
+       qp_attr.qp_state = IB_QPS_ERR;
+       return ib_modify_qp(ch->qp, &qp_attr, IB_QP_STATE);
+}
+
+/**
+ * srpt_unmap_sg_to_ib_sge() - Unmap an IB SGE list.
+ */
+static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,
+                                   struct srpt_send_ioctx *ioctx)
+{
+       struct scatterlist *sg;
+       enum dma_data_direction dir;
+
+       BUG_ON(!ch);
+       BUG_ON(!ioctx);
+       BUG_ON(ioctx->n_rdma && !ioctx->rdma_ius);
+
+       while (ioctx->n_rdma)
+               kfree(ioctx->rdma_ius[--ioctx->n_rdma].sge);
+
+       kfree(ioctx->rdma_ius);
+       ioctx->rdma_ius = NULL;
+
+       if (ioctx->mapped_sg_count) {
+               sg = ioctx->sg;
+               WARN_ON(!sg);
+               dir = ioctx->cmd.data_direction;
+               BUG_ON(dir == DMA_NONE);
+               ib_dma_unmap_sg(ch->sport->sdev->device, sg, ioctx->sg_cnt,
+                               opposite_dma_dir(dir));
+               ioctx->mapped_sg_count = 0;
+       }
+}
+
+/**
+ * srpt_map_sg_to_ib_sge() - Map an SG list to an IB SGE list.
+ */
+static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch,
+                                struct srpt_send_ioctx *ioctx)
+{
+       struct se_cmd *cmd;
+       struct scatterlist *sg, *sg_orig;
+       int sg_cnt;
+       enum dma_data_direction dir;
+       struct rdma_iu *riu;
+       struct srp_direct_buf *db;
+       dma_addr_t dma_addr;
+       struct ib_sge *sge;
+       u64 raddr;
+       u32 rsize;
+       u32 tsize;
+       u32 dma_len;
+       int count, nrdma;
+       int i, j, k;
+
+       BUG_ON(!ch);
+       BUG_ON(!ioctx);
+       cmd = &ioctx->cmd;
+       dir = cmd->data_direction;
+       BUG_ON(dir == DMA_NONE);
+
+       transport_do_task_sg_chain(cmd);
+       ioctx->sg = sg = sg_orig = cmd->t_tasks_sg_chained;
+       ioctx->sg_cnt = sg_cnt = cmd->t_tasks_sg_chained_no;
+
+       count = ib_dma_map_sg(ch->sport->sdev->device, sg, sg_cnt,
+                             opposite_dma_dir(dir));
+       if (unlikely(!count))
+               return -EAGAIN;
+
+       ioctx->mapped_sg_count = count;
+
+       if (ioctx->rdma_ius && ioctx->n_rdma_ius)
+               nrdma = ioctx->n_rdma_ius;
+       else {
+               nrdma = (count + SRPT_DEF_SG_PER_WQE - 1) / SRPT_DEF_SG_PER_WQE
+                       + ioctx->n_rbuf;
+
+               ioctx->rdma_ius = kzalloc(nrdma * sizeof *riu, GFP_KERNEL);
+               if (!ioctx->rdma_ius)
+                       goto free_mem;
+
+               ioctx->n_rdma_ius = nrdma;
+       }
+
+       db = ioctx->rbufs;
+       tsize = cmd->data_length;
+       dma_len = sg_dma_len(&sg[0]);
+       riu = ioctx->rdma_ius;
+
+       /*
+        * For each remote desc - calculate the #ib_sge.
+        * If #ib_sge < SRPT_DEF_SG_PER_WQE per rdma operation then
+        *      each remote desc rdma_iu is required a rdma wr;
+        * else
+        *      we need to allocate extra rdma_iu to carry extra #ib_sge in
+        *      another rdma wr
+        */
+       for (i = 0, j = 0;
+            j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
+               rsize = be32_to_cpu(db->len);
+               raddr = be64_to_cpu(db->va);
+               riu->raddr = raddr;
+               riu->rkey = be32_to_cpu(db->key);
+               riu->sge_cnt = 0;
+
+               /* calculate how many sge required for this remote_buf */
+               while (rsize > 0 && tsize > 0) {
+
+                       if (rsize >= dma_len) {
+                               tsize -= dma_len;
+                               rsize -= dma_len;
+                               raddr += dma_len;
+
+                               if (tsize > 0) {
+                                       ++j;
+                                       if (j < count) {
+                                               sg = sg_next(sg);
+                                               dma_len = sg_dma_len(sg);
+                                       }
+                               }
+                       } else {
+                               tsize -= rsize;
+                               dma_len -= rsize;
+                               rsize = 0;
+                       }
+
+                       ++riu->sge_cnt;
+
+                       if (rsize > 0 && riu->sge_cnt == SRPT_DEF_SG_PER_WQE) {
+                               ++ioctx->n_rdma;
+                               riu->sge =
+                                   kmalloc(riu->sge_cnt * sizeof *riu->sge,
+                                           GFP_KERNEL);
+                               if (!riu->sge)
+                                       goto free_mem;
+
+                               ++riu;
+                               riu->sge_cnt = 0;
+                               riu->raddr = raddr;
+                               riu->rkey = be32_to_cpu(db->key);
+                       }
+               }
+
+               ++ioctx->n_rdma;
+               riu->sge = kmalloc(riu->sge_cnt * sizeof *riu->sge,
+                                  GFP_KERNEL);
+               if (!riu->sge)
+                       goto free_mem;
+       }
+
+       db = ioctx->rbufs;
+       tsize = cmd->data_length;
+       riu = ioctx->rdma_ius;
+       sg = sg_orig;
+       dma_len = sg_dma_len(&sg[0]);
+       dma_addr = sg_dma_address(&sg[0]);
+
+       /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */
+       for (i = 0, j = 0;
+            j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
+               rsize = be32_to_cpu(db->len);
+               sge = riu->sge;
+               k = 0;
+
+               while (rsize > 0 && tsize > 0) {
+                       sge->addr = dma_addr;
+                       sge->lkey = ch->sport->sdev->mr->lkey;
+
+                       if (rsize >= dma_len) {
+                               sge->length =
+                                       (tsize < dma_len) ? tsize : dma_len;
+                               tsize -= dma_len;
+                               rsize -= dma_len;
+
+                               if (tsize > 0) {
+                                       ++j;
+                                       if (j < count) {
+                                               sg = sg_next(sg);
+                                               dma_len = sg_dma_len(sg);
+                                               dma_addr = sg_dma_address(sg);
+                                       }
+                               }
+                       } else {
+                               sge->length = (tsize < rsize) ? tsize : rsize;
+                               tsize -= rsize;
+                               dma_len -= rsize;
+                               dma_addr += rsize;
+                               rsize = 0;
+                       }
+
+                       ++k;
+                       if (k == riu->sge_cnt && rsize > 0 && tsize > 0) {
+                               ++riu;
+                               sge = riu->sge;
+                               k = 0;
+                       } else if (rsize > 0 && tsize > 0)
+                               ++sge;
+               }
+       }
+
+       return 0;
+
+free_mem:
+       srpt_unmap_sg_to_ib_sge(ch, ioctx);
+
+       return -ENOMEM;
+}
+
+/**
+ * srpt_get_send_ioctx() - Obtain an I/O context for sending to the initiator.
+ */
+static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
+{
+       struct srpt_send_ioctx *ioctx;
+       unsigned long flags;
+
+       BUG_ON(!ch);
+
+       ioctx = NULL;
+       spin_lock_irqsave(&ch->spinlock, flags);
+       if (!list_empty(&ch->free_list)) {
+               ioctx = list_first_entry(&ch->free_list,
+                                        struct srpt_send_ioctx, free_list);
+               list_del(&ioctx->free_list);
+       }
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+
+       if (!ioctx)
+               return ioctx;
+
+       BUG_ON(ioctx->ch != ch);
+       kref_init(&ioctx->kref);
+       spin_lock_init(&ioctx->spinlock);
+       ioctx->state = SRPT_STATE_NEW;
+       ioctx->n_rbuf = 0;
+       ioctx->rbufs = NULL;
+       ioctx->n_rdma = 0;
+       ioctx->n_rdma_ius = 0;
+       ioctx->rdma_ius = NULL;
+       ioctx->mapped_sg_count = 0;
+       init_completion(&ioctx->tx_done);
+       ioctx->queue_status_only = false;
+       /*
+        * transport_init_se_cmd() does not initialize all fields, so do it
+        * here.
+        */
+       memset(&ioctx->cmd, 0, sizeof(ioctx->cmd));
+       memset(&ioctx->sense_data, 0, sizeof(ioctx->sense_data));
+
+       return ioctx;
+}
+
+/**
+ * srpt_put_send_ioctx() - Free up resources.
+ */
+static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)
+{
+       struct srpt_rdma_ch *ch;
+       unsigned long flags;
+
+       BUG_ON(!ioctx);
+       ch = ioctx->ch;
+       BUG_ON(!ch);
+
+       WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);
+
+       srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
+       transport_generic_free_cmd(&ioctx->cmd, 0);
+
+       if (ioctx->n_rbuf > 1) {
+               kfree(ioctx->rbufs);
+               ioctx->rbufs = NULL;
+               ioctx->n_rbuf = 0;
+       }
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       list_add(&ioctx->free_list, &ch->free_list);
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+}
+
+static void srpt_put_send_ioctx_kref(struct kref *kref)
+{
+       srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref));
+}
+
+/**
+ * srpt_abort_cmd() - Abort a SCSI command.
+ * @ioctx:   I/O context associated with the SCSI command.
+ * @context: Preferred execution context.
+ */
+static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
+{
+       enum srpt_command_state state;
+       unsigned long flags;
+
+       BUG_ON(!ioctx);
+
+       /*
+        * If the command is in a state where the target core is waiting for
+        * the ib_srpt driver, change the state to the next state. Changing
+        * the state of the command from SRPT_STATE_NEED_DATA to
+        * SRPT_STATE_DATA_IN ensures that srpt_xmit_response() will call this
+        * function a second time.
+        */
+
+       spin_lock_irqsave(&ioctx->spinlock, flags);
+       state = ioctx->state;
+       switch (state) {
+       case SRPT_STATE_NEED_DATA:
+               ioctx->state = SRPT_STATE_DATA_IN;
+               break;
+       case SRPT_STATE_DATA_IN:
+       case SRPT_STATE_CMD_RSP_SENT:
+       case SRPT_STATE_MGMT_RSP_SENT:
+               ioctx->state = SRPT_STATE_DONE;
+               break;
+       default:
+               break;
+       }
+       spin_unlock_irqrestore(&ioctx->spinlock, flags);
+
+       if (state == SRPT_STATE_DONE)
+               goto out;
+
+       pr_debug("Aborting cmd with state %d and tag %lld\n", state,
+                ioctx->tag);
+
+       switch (state) {
+       case SRPT_STATE_NEW:
+       case SRPT_STATE_DATA_IN:
+       case SRPT_STATE_MGMT:
+               /*
+                * Do nothing - defer abort processing until
+                * srpt_queue_response() is invoked.
+                */
+               WARN_ON(!transport_check_aborted_status(&ioctx->cmd, false));
+               break;
+       case SRPT_STATE_NEED_DATA:
+               /* DMA_TO_DEVICE (write) - RDMA read error. */
+               atomic_set(&ioctx->cmd.transport_lun_stop, 1);
+               transport_generic_handle_data(&ioctx->cmd);
+               break;
+       case SRPT_STATE_CMD_RSP_SENT:
+               /*
+                * SRP_RSP sending failed or the SRP_RSP send completion has
+                * not been received in time.
+                */
+               srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
+               atomic_set(&ioctx->cmd.transport_lun_stop, 1);
+               kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+               break;
+       case SRPT_STATE_MGMT_RSP_SENT:
+               srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+               kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+               break;
+       default:
+               WARN_ON("ERROR: unexpected command state");
+               break;
+       }
+
+out:
+       return state;
+}
+
+/**
+ * srpt_handle_send_err_comp() - Process an IB_WC_SEND error completion.
+ */
+static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id)
+{
+       struct srpt_send_ioctx *ioctx;
+       enum srpt_command_state state;
+       struct se_cmd *cmd;
+       u32 index;
+
+       atomic_inc(&ch->sq_wr_avail);
+
+       index = idx_from_wr_id(wr_id);
+       ioctx = ch->ioctx_ring[index];
+       state = srpt_get_cmd_state(ioctx);
+       cmd = &ioctx->cmd;
+
+       WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
+               && state != SRPT_STATE_MGMT_RSP_SENT
+               && state != SRPT_STATE_NEED_DATA
+               && state != SRPT_STATE_DONE);
+
+       /* If SRP_RSP sending failed, undo the ch->req_lim change. */
+       if (state == SRPT_STATE_CMD_RSP_SENT
+           || state == SRPT_STATE_MGMT_RSP_SENT)
+               atomic_dec(&ch->req_lim);
+
+       srpt_abort_cmd(ioctx);
+}
+
+/**
+ * srpt_handle_send_comp() - Process an IB send completion notification.
+ */
+static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
+                                 struct srpt_send_ioctx *ioctx)
+{
+       enum srpt_command_state state;
+
+       atomic_inc(&ch->sq_wr_avail);
+
+       state = srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+
+       if (WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
+                   && state != SRPT_STATE_MGMT_RSP_SENT
+                   && state != SRPT_STATE_DONE))
+               pr_debug("state = %d\n", state);
+
+       if (state != SRPT_STATE_DONE)
+               kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+       else
+               printk(KERN_ERR "IB completion has been received too late for"
+                      " wr_id = %u.\n", ioctx->ioctx.index);
+}
+
+/**
+ * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
+ *
+ * Note: transport_generic_handle_data() is asynchronous so unmapping the
+ * data that has been transferred via IB RDMA must be postponed until the
+ * check_stop_free() callback.
+ */
+static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
+                                 struct srpt_send_ioctx *ioctx,
+                                 enum srpt_opcode opcode)
+{
+       WARN_ON(ioctx->n_rdma <= 0);
+       atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
+
+       if (opcode == SRPT_RDMA_READ_LAST) {
+               if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
+                                               SRPT_STATE_DATA_IN))
+                       transport_generic_handle_data(&ioctx->cmd);
+               else
+                       printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
+                              __LINE__, srpt_get_cmd_state(ioctx));
+       } else if (opcode == SRPT_RDMA_ABORT) {
+               ioctx->rdma_aborted = true;
+       } else {
+               WARN(true, "unexpected opcode %d\n", opcode);
+       }
+}
+
+/**
+ * srpt_handle_rdma_err_comp() - Process an IB RDMA error completion.
+ */
+static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
+                                     struct srpt_send_ioctx *ioctx,
+                                     enum srpt_opcode opcode)
+{
+       struct se_cmd *cmd;
+       enum srpt_command_state state;
+
+       cmd = &ioctx->cmd;
+       state = srpt_get_cmd_state(ioctx);
+       switch (opcode) {
+       case SRPT_RDMA_READ_LAST:
+               if (ioctx->n_rdma <= 0) {
+                       printk(KERN_ERR "Received invalid RDMA read"
+                              " error completion with idx %d\n",
+                              ioctx->ioctx.index);
+                       break;
+               }
+               atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
+               if (state == SRPT_STATE_NEED_DATA)
+                       srpt_abort_cmd(ioctx);
+               else
+                       printk(KERN_ERR "%s[%d]: wrong state = %d\n",
+                              __func__, __LINE__, state);
+               break;
+       case SRPT_RDMA_WRITE_LAST:
+               atomic_set(&ioctx->cmd.transport_lun_stop, 1);
+               break;
+       default:
+               printk(KERN_ERR "%s[%d]: opcode = %u\n", __func__,
+                      __LINE__, opcode);
+               break;
+       }
+}
+
+/**
+ * srpt_build_cmd_rsp() - Build an SRP_RSP response.
+ * @ch: RDMA channel through which the request has been received.
+ * @ioctx: I/O context associated with the SRP_CMD request. The response will
+ *   be built in the buffer ioctx->buf points at and hence this function will
+ *   overwrite the request data.
+ * @tag: tag of the request for which this response is being generated.
+ * @status: value for the STATUS field of the SRP_RSP information unit.
+ *
+ * Returns the size in bytes of the SRP_RSP response.
+ *
+ * An SRP_RSP response contains a SCSI status or service response. See also
+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
+ * response. See also SPC-2 for more information about sense data.
+ */
+static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
+                             struct srpt_send_ioctx *ioctx, u64 tag,
+                             int status)
+{
+       struct srp_rsp *srp_rsp;
+       const u8 *sense_data;
+       int sense_data_len, max_sense_len;
+
+       /*
+        * The lowest bit of all SAM-3 status codes is zero (see also
+        * paragraph 5.3 in SAM-3).
+        */
+       WARN_ON(status & 1);
+
+       srp_rsp = ioctx->ioctx.buf;
+       BUG_ON(!srp_rsp);
+
+       sense_data = ioctx->sense_data;
+       sense_data_len = ioctx->cmd.scsi_sense_length;
+       WARN_ON(sense_data_len > sizeof(ioctx->sense_data));
+
+       memset(srp_rsp, 0, sizeof *srp_rsp);
+       srp_rsp->opcode = SRP_RSP;
+       srp_rsp->req_lim_delta =
+               __constant_cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0));
+       srp_rsp->tag = tag;
+       srp_rsp->status = status;
+
+       if (sense_data_len) {
+               BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
+               max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
+               if (sense_data_len > max_sense_len) {
+                       printk(KERN_WARNING "truncated sense data from %d to %d"
+                              " bytes\n", sense_data_len, max_sense_len);
+                       sense_data_len = max_sense_len;
+               }
+
+               srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
+               srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
+               memcpy(srp_rsp + 1, sense_data, sense_data_len);
+       }
+
+       return sizeof(*srp_rsp) + sense_data_len;
+}
+
+/**
+ * srpt_build_tskmgmt_rsp() - Build a task management response.
+ * @ch:       RDMA channel through which the request has been received.
+ * @ioctx:    I/O context in which the SRP_RSP response will be built.
+ * @rsp_code: RSP_CODE that will be stored in the response.
+ * @tag:      Tag of the request for which this response is being generated.
+ *
+ * Returns the size in bytes of the SRP_RSP response.
+ *
+ * An SRP_RSP response contains a SCSI status or service response. See also
+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
+ * response.
+ */
+static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
+                                 struct srpt_send_ioctx *ioctx,
+                                 u8 rsp_code, u64 tag)
+{
+       struct srp_rsp *srp_rsp;
+       int resp_data_len;
+       int resp_len;
+
+       resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
+       resp_len = sizeof(*srp_rsp) + resp_data_len;
+
+       srp_rsp = ioctx->ioctx.buf;
+       BUG_ON(!srp_rsp);
+       memset(srp_rsp, 0, sizeof *srp_rsp);
+
+       srp_rsp->opcode = SRP_RSP;
+       srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
+                                   + atomic_xchg(&ch->req_lim_delta, 0));
+       srp_rsp->tag = tag;
+
+       if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
+               srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
+               srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
+               srp_rsp->data[3] = rsp_code;
+       }
+
+       return resp_len;
+}
+
+#define NO_SUCH_LUN ((uint64_t)-1LL)
+
+/*
+ * SCSI LUN addressing method. See also SAM-2 and the section about
+ * eight byte LUNs.
+ */
+enum scsi_lun_addr_method {
+       SCSI_LUN_ADDR_METHOD_PERIPHERAL   = 0,
+       SCSI_LUN_ADDR_METHOD_FLAT         = 1,
+       SCSI_LUN_ADDR_METHOD_LUN          = 2,
+       SCSI_LUN_ADDR_METHOD_EXTENDED_LUN = 3,
+};
+
+/*
+ * srpt_unpack_lun() - Convert from network LUN to linear LUN.
+ *
+ * Convert an 2-byte, 4-byte, 6-byte or 8-byte LUN structure in network byte
+ * order (big endian) to a linear LUN. Supports three LUN addressing methods:
+ * peripheral, flat and logical unit. See also SAM-2, section 4.9.4 (page 40).
+ */
+static uint64_t srpt_unpack_lun(const uint8_t *lun, int len)
+{
+       uint64_t res = NO_SUCH_LUN;
+       int addressing_method;
+
+       if (unlikely(len < 2)) {
+               printk(KERN_ERR "Illegal LUN length %d, expected 2 bytes or "
+                      "more", len);
+               goto out;
+       }
+
+       switch (len) {
+       case 8:
+               if ((*((__be64 *)lun) &
+                    __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)
+                       goto out_err;
+               break;
+       case 4:
+               if (*((__be16 *)&lun[2]) != 0)
+                       goto out_err;
+               break;
+       case 6:
+               if (*((__be32 *)&lun[2]) != 0)
+                       goto out_err;
+               break;
+       case 2:
+               break;
+       default:
+               goto out_err;
+       }
+
+       addressing_method = (*lun) >> 6; /* highest two bits of byte 0 */
+       switch (addressing_method) {
+       case SCSI_LUN_ADDR_METHOD_PERIPHERAL:
+       case SCSI_LUN_ADDR_METHOD_FLAT:
+       case SCSI_LUN_ADDR_METHOD_LUN:
+               res = *(lun + 1) | (((*lun) & 0x3f) << 8);
+               break;
+
+       case SCSI_LUN_ADDR_METHOD_EXTENDED_LUN:
+       default:
+               printk(KERN_ERR "Unimplemented LUN addressing method %u",
+                      addressing_method);
+               break;
+       }
+
+out:
+       return res;
+
+out_err:
+       printk(KERN_ERR "Support for multi-level LUNs has not yet been"
+              " implemented");
+       goto out;
+}
+
+static int srpt_check_stop_free(struct se_cmd *cmd)
+{
+       struct srpt_send_ioctx *ioctx;
+
+       ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
+       return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+}
+
+/**
+ * srpt_handle_cmd() - Process SRP_CMD.
+ */
+static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
+                          struct srpt_recv_ioctx *recv_ioctx,
+                          struct srpt_send_ioctx *send_ioctx)
+{
+       struct se_cmd *cmd;
+       struct srp_cmd *srp_cmd;
+       uint64_t unpacked_lun;
+       u64 data_len;
+       enum dma_data_direction dir;
+       int ret;
+
+       BUG_ON(!send_ioctx);
+
+       srp_cmd = recv_ioctx->ioctx.buf;
+       kref_get(&send_ioctx->kref);
+       cmd = &send_ioctx->cmd;
+       send_ioctx->tag = srp_cmd->tag;
+
+       switch (srp_cmd->task_attr) {
+       case SRP_CMD_SIMPLE_Q:
+               cmd->sam_task_attr = MSG_SIMPLE_TAG;
+               break;
+       case SRP_CMD_ORDERED_Q:
+       default:
+               cmd->sam_task_attr = MSG_ORDERED_TAG;
+               break;
+       case SRP_CMD_HEAD_OF_Q:
+               cmd->sam_task_attr = MSG_HEAD_TAG;
+               break;
+       case SRP_CMD_ACA:
+               cmd->sam_task_attr = MSG_ACA_TAG;
+               break;
+       }
+
+       ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);
+       if (ret) {
+               printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
+                      srp_cmd->tag);
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               goto send_sense;
+       }
+
+       cmd->data_length = data_len;
+       cmd->data_direction = dir;
+       unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
+                                      sizeof(srp_cmd->lun));
+       if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0)
+               goto send_sense;
+       ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb);
+       if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
+               srpt_queue_status(cmd);
+       else if (cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)
+               goto send_sense;
+       else
+               WARN_ON_ONCE(ret);
+
+       transport_handle_cdb_direct(cmd);
+       return 0;
+
+send_sense:
+       transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason,
+                                                0);
+       return -1;
+}
+
+/**
+ * srpt_rx_mgmt_fn_tag() - Process a task management function by tag.
+ * @ch: RDMA channel of the task management request.
+ * @fn: Task management function to perform.
+ * @req_tag: Tag of the SRP task management request.
+ * @mgmt_ioctx: I/O context of the task management request.
+ *
+ * Returns zero if the target core will process the task management
+ * request asynchronously.
+ *
+ * Note: It is assumed that the initiator serializes tag-based task management
+ * requests.
+ */
+static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag)
+{
+       struct srpt_device *sdev;
+       struct srpt_rdma_ch *ch;
+       struct srpt_send_ioctx *target;
+       int ret, i;
+
+       ret = -EINVAL;
+       ch = ioctx->ch;
+       BUG_ON(!ch);
+       BUG_ON(!ch->sport);
+       sdev = ch->sport->sdev;
+       BUG_ON(!sdev);
+       spin_lock_irq(&sdev->spinlock);
+       for (i = 0; i < ch->rq_size; ++i) {
+               target = ch->ioctx_ring[i];
+               if (target->cmd.se_lun == ioctx->cmd.se_lun &&
+                   target->tag == tag &&
+                   srpt_get_cmd_state(target) != SRPT_STATE_DONE) {
+                       ret = 0;
+                       /* now let the target core abort &target->cmd; */
+                       break;
+               }
+       }
+       spin_unlock_irq(&sdev->spinlock);
+       return ret;
+}
+
+static int srp_tmr_to_tcm(int fn)
+{
+       switch (fn) {
+       case SRP_TSK_ABORT_TASK:
+               return TMR_ABORT_TASK;
+       case SRP_TSK_ABORT_TASK_SET:
+               return TMR_ABORT_TASK_SET;
+       case SRP_TSK_CLEAR_TASK_SET:
+               return TMR_CLEAR_TASK_SET;
+       case SRP_TSK_LUN_RESET:
+               return TMR_LUN_RESET;
+       case SRP_TSK_CLEAR_ACA:
+               return TMR_CLEAR_ACA;
+       default:
+               return -1;
+       }
+}
+
+/**
+ * srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.
+ *
+ * Returns 0 if and only if the request will be processed by the target core.
+ *
+ * For more information about SRP_TSK_MGMT information units, see also section
+ * 6.7 in the SRP r16a document.
+ */
+static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
+                                struct srpt_recv_ioctx *recv_ioctx,
+                                struct srpt_send_ioctx *send_ioctx)
+{
+       struct srp_tsk_mgmt *srp_tsk;
+       struct se_cmd *cmd;
+       uint64_t unpacked_lun;
+       int tcm_tmr;
+       int res;
+
+       BUG_ON(!send_ioctx);
+
+       srp_tsk = recv_ioctx->ioctx.buf;
+       cmd = &send_ioctx->cmd;
+
+       pr_debug("recv tsk_mgmt fn %d for task_tag %lld and cmd tag %lld"
+                " cm_id %p sess %p\n", srp_tsk->tsk_mgmt_func,
+                srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess);
+
+       srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT);
+       send_ioctx->tag = srp_tsk->tag;
+       tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
+       if (tcm_tmr < 0) {
+               send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               send_ioctx->cmd.se_tmr_req->response =
+                       TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
+               goto process_tmr;
+       }
+       cmd->se_tmr_req = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);
+       if (!cmd->se_tmr_req) {
+               send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
+               goto process_tmr;
+       }
+
+       unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
+                                      sizeof(srp_tsk->lun));
+       res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun);
+       if (res) {
+               pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun);
+               send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
+               goto process_tmr;
+       }
+
+       if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)
+               srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
+
+process_tmr:
+       kref_get(&send_ioctx->kref);
+       if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
+               transport_generic_handle_tmr(&send_ioctx->cmd);
+       else
+               transport_send_check_condition_and_sense(cmd,
+                                               cmd->scsi_sense_reason, 0);
+
+}
+
+/**
+ * srpt_handle_new_iu() - Process a newly received information unit.
+ * @ch:    RDMA channel through which the information unit has been received.
+ * @ioctx: SRPT I/O context associated with the information unit.
+ */
+static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
+                              struct srpt_recv_ioctx *recv_ioctx,
+                              struct srpt_send_ioctx *send_ioctx)
+{
+       struct srp_cmd *srp_cmd;
+       enum rdma_ch_state ch_state;
+
+       BUG_ON(!ch);
+       BUG_ON(!recv_ioctx);
+
+       ib_dma_sync_single_for_cpu(ch->sport->sdev->device,
+                                  recv_ioctx->ioctx.dma, srp_max_req_size,
+                                  DMA_FROM_DEVICE);
+
+       ch_state = srpt_get_ch_state(ch);
+       if (unlikely(ch_state == CH_CONNECTING)) {
+               list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);
+               goto out;
+       }
+
+       if (unlikely(ch_state != CH_LIVE))
+               goto out;
+
+       srp_cmd = recv_ioctx->ioctx.buf;
+       if (srp_cmd->opcode == SRP_CMD || srp_cmd->opcode == SRP_TSK_MGMT) {
+               if (!send_ioctx)
+                       send_ioctx = srpt_get_send_ioctx(ch);
+               if (unlikely(!send_ioctx)) {
+                       list_add_tail(&recv_ioctx->wait_list,
+                                     &ch->cmd_wait_list);
+                       goto out;
+               }
+       }
+
+       transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess,
+                             0, DMA_NONE, MSG_SIMPLE_TAG,
+                             send_ioctx->sense_data);
+
+       switch (srp_cmd->opcode) {
+       case SRP_CMD:
+               srpt_handle_cmd(ch, recv_ioctx, send_ioctx);
+               break;
+       case SRP_TSK_MGMT:
+               srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx);
+               break;
+       case SRP_I_LOGOUT:
+               printk(KERN_ERR "Not yet implemented: SRP_I_LOGOUT\n");
+               break;
+       case SRP_CRED_RSP:
+               pr_debug("received SRP_CRED_RSP\n");
+               break;
+       case SRP_AER_RSP:
+               pr_debug("received SRP_AER_RSP\n");
+               break;
+       case SRP_RSP:
+               printk(KERN_ERR "Received SRP_RSP\n");
+               break;
+       default:
+               printk(KERN_ERR "received IU with unknown opcode 0x%x\n",
+                      srp_cmd->opcode);
+               break;
+       }
+
+       srpt_post_recv(ch->sport->sdev, recv_ioctx);
+out:
+       return;
+}
+
+static void srpt_process_rcv_completion(struct ib_cq *cq,
+                                       struct srpt_rdma_ch *ch,
+                                       struct ib_wc *wc)
+{
+       struct srpt_device *sdev = ch->sport->sdev;
+       struct srpt_recv_ioctx *ioctx;
+       u32 index;
+
+       index = idx_from_wr_id(wc->wr_id);
+       if (wc->status == IB_WC_SUCCESS) {
+               int req_lim;
+
+               req_lim = atomic_dec_return(&ch->req_lim);
+               if (unlikely(req_lim < 0))
+                       printk(KERN_ERR "req_lim = %d < 0\n", req_lim);
+               ioctx = sdev->ioctx_ring[index];
+               srpt_handle_new_iu(ch, ioctx, NULL);
+       } else {
+               printk(KERN_INFO "receiving failed for idx %u with status %d\n",
+                      index, wc->status);
+       }
+}
+
+/**
+ * srpt_process_send_completion() - Process an IB send completion.
+ *
+ * Note: Although this has not yet been observed during tests, at least in
+ * theory it is possible that the srpt_get_send_ioctx() call invoked by
+ * srpt_handle_new_iu() fails. This is possible because the req_lim_delta
+ * value in each response is set to one, and it is possible that this response
+ * makes the initiator send a new request before the send completion for that
+ * response has been processed. This could e.g. happen if the call to
+ * srpt_put_send_iotcx() is delayed because of a higher priority interrupt or
+ * if IB retransmission causes generation of the send completion to be
+ * delayed. Incoming information units for which srpt_get_send_ioctx() fails
+ * are queued on cmd_wait_list. The code below processes these delayed
+ * requests one at a time.
+ */
+static void srpt_process_send_completion(struct ib_cq *cq,
+                                        struct srpt_rdma_ch *ch,
+                                        struct ib_wc *wc)
+{
+       struct srpt_send_ioctx *send_ioctx;
+       uint32_t index;
+       enum srpt_opcode opcode;
+
+       index = idx_from_wr_id(wc->wr_id);
+       opcode = opcode_from_wr_id(wc->wr_id);
+       send_ioctx = ch->ioctx_ring[index];
+       if (wc->status == IB_WC_SUCCESS) {
+               if (opcode == SRPT_SEND)
+                       srpt_handle_send_comp(ch, send_ioctx);
+               else {
+                       WARN_ON(opcode != SRPT_RDMA_ABORT &&
+                               wc->opcode != IB_WC_RDMA_READ);
+                       srpt_handle_rdma_comp(ch, send_ioctx, opcode);
+               }
+       } else {
+               if (opcode == SRPT_SEND) {
+                       printk(KERN_INFO "sending response for idx %u failed"
+                              " with status %d\n", index, wc->status);
+                       srpt_handle_send_err_comp(ch, wc->wr_id);
+               } else if (opcode != SRPT_RDMA_MID) {
+                       printk(KERN_INFO "RDMA t %d for idx %u failed with"
+                               " status %d", opcode, index, wc->status);
+                       srpt_handle_rdma_err_comp(ch, send_ioctx, opcode);
+               }
+       }
+
+       while (unlikely(opcode == SRPT_SEND
+                       && !list_empty(&ch->cmd_wait_list)
+                       && srpt_get_ch_state(ch) == CH_LIVE
+                       && (send_ioctx = srpt_get_send_ioctx(ch)) != NULL)) {
+               struct srpt_recv_ioctx *recv_ioctx;
+
+               recv_ioctx = list_first_entry(&ch->cmd_wait_list,
+                                             struct srpt_recv_ioctx,
+                                             wait_list);
+               list_del(&recv_ioctx->wait_list);
+               srpt_handle_new_iu(ch, recv_ioctx, send_ioctx);
+       }
+}
+
+static void srpt_process_completion(struct ib_cq *cq, struct srpt_rdma_ch *ch)
+{
+       struct ib_wc *const wc = ch->wc;
+       int i, n;
+
+       WARN_ON(cq != ch->cq);
+
+       ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+       while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {
+               for (i = 0; i < n; i++) {
+                       if (opcode_from_wr_id(wc[i].wr_id) == SRPT_RECV)
+                               srpt_process_rcv_completion(cq, ch, &wc[i]);
+                       else
+                               srpt_process_send_completion(cq, ch, &wc[i]);
+               }
+       }
+}
+
+/**
+ * srpt_completion() - IB completion queue callback function.
+ *
+ * Notes:
+ * - It is guaranteed that a completion handler will never be invoked
+ *   concurrently on two different CPUs for the same completion queue. See also
+ *   Documentation/infiniband/core_locking.txt and the implementation of
+ *   handle_edge_irq() in kernel/irq/chip.c.
+ * - When threaded IRQs are enabled, completion handlers are invoked in thread
+ *   context instead of interrupt context.
+ */
+static void srpt_completion(struct ib_cq *cq, void *ctx)
+{
+       struct srpt_rdma_ch *ch = ctx;
+
+       wake_up_interruptible(&ch->wait_queue);
+}
+
+static int srpt_compl_thread(void *arg)
+{
+       struct srpt_rdma_ch *ch;
+
+       /* Hibernation / freezing of the SRPT kernel thread is not supported. */
+       current->flags |= PF_NOFREEZE;
+
+       ch = arg;
+       BUG_ON(!ch);
+       printk(KERN_INFO "Session %s: kernel thread %s (PID %d) started\n",
+              ch->sess_name, ch->thread->comm, current->pid);
+       while (!kthread_should_stop()) {
+               wait_event_interruptible(ch->wait_queue,
+                       (srpt_process_completion(ch->cq, ch),
+                        kthread_should_stop()));
+       }
+       printk(KERN_INFO "Session %s: kernel thread %s (PID %d) stopped\n",
+              ch->sess_name, ch->thread->comm, current->pid);
+       return 0;
+}
+
+/**
+ * srpt_create_ch_ib() - Create receive and send completion queues.
+ */
+static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
+{
+       struct ib_qp_init_attr *qp_init;
+       struct srpt_port *sport = ch->sport;
+       struct srpt_device *sdev = sport->sdev;
+       u32 srp_sq_size = sport->port_attrib.srp_sq_size;
+       int ret;
+
+       WARN_ON(ch->rq_size < 1);
+
+       ret = -ENOMEM;
+       qp_init = kzalloc(sizeof *qp_init, GFP_KERNEL);
+       if (!qp_init)
+               goto out;
+
+       ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
+                             ch->rq_size + srp_sq_size, 0);
+       if (IS_ERR(ch->cq)) {
+               ret = PTR_ERR(ch->cq);
+               printk(KERN_ERR "failed to create CQ cqe= %d ret= %d\n",
+                      ch->rq_size + srp_sq_size, ret);
+               goto out;
+       }
+
+       qp_init->qp_context = (void *)ch;
+       qp_init->event_handler
+               = (void(*)(struct ib_event *, void*))srpt_qp_event;
+       qp_init->send_cq = ch->cq;
+       qp_init->recv_cq = ch->cq;
+       qp_init->srq = sdev->srq;
+       qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
+       qp_init->qp_type = IB_QPT_RC;
+       qp_init->cap.max_send_wr = srp_sq_size;
+       qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;
+
+       ch->qp = ib_create_qp(sdev->pd, qp_init);
+       if (IS_ERR(ch->qp)) {
+               ret = PTR_ERR(ch->qp);
+               printk(KERN_ERR "failed to create_qp ret= %d\n", ret);
+               goto err_destroy_cq;
+       }
+
+       atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);
+
+       pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %d cm_id= %p\n",
+                __func__, ch->cq->cqe, qp_init->cap.max_send_sge,
+                qp_init->cap.max_send_wr, ch->cm_id);
+
+       ret = srpt_init_ch_qp(ch, ch->qp);
+       if (ret)
+               goto err_destroy_qp;
+
+       init_waitqueue_head(&ch->wait_queue);
+
+       pr_debug("creating thread for session %s\n", ch->sess_name);
+
+       ch->thread = kthread_run(srpt_compl_thread, ch, "ib_srpt_compl");
+       if (IS_ERR(ch->thread)) {
+               printk(KERN_ERR "failed to create kernel thread %ld\n",
+                      PTR_ERR(ch->thread));
+               ch->thread = NULL;
+               goto err_destroy_qp;
+       }
+
+out:
+       kfree(qp_init);
+       return ret;
+
+err_destroy_qp:
+       ib_destroy_qp(ch->qp);
+err_destroy_cq:
+       ib_destroy_cq(ch->cq);
+       goto out;
+}
+
+static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
+{
+       if (ch->thread)
+               kthread_stop(ch->thread);
+
+       ib_destroy_qp(ch->qp);
+       ib_destroy_cq(ch->cq);
+}
+
+/**
+ * __srpt_close_ch() - Close an RDMA channel by setting the QP error state.
+ *
+ * Reset the QP and make sure all resources associated with the channel will
+ * be deallocated at an appropriate time.
+ *
+ * Note: The caller must hold ch->sport->sdev->spinlock.
+ */
+static void __srpt_close_ch(struct srpt_rdma_ch *ch)
+{
+       struct srpt_device *sdev;
+       enum rdma_ch_state prev_state;
+       unsigned long flags;
+
+       sdev = ch->sport->sdev;
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       prev_state = ch->state;
+       switch (prev_state) {
+       case CH_CONNECTING:
+       case CH_LIVE:
+               ch->state = CH_DISCONNECTING;
+               break;
+       default:
+               break;
+       }
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+
+       switch (prev_state) {
+       case CH_CONNECTING:
+               ib_send_cm_rej(ch->cm_id, IB_CM_REJ_NO_RESOURCES, NULL, 0,
+                              NULL, 0);
+               /* fall through */
+       case CH_LIVE:
+               if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0)
+                       printk(KERN_ERR "sending CM DREQ failed.\n");
+               break;
+       case CH_DISCONNECTING:
+               break;
+       case CH_DRAINING:
+       case CH_RELEASING:
+               break;
+       }
+}
+
+/**
+ * srpt_close_ch() - Close an RDMA channel.
+ */
+static void srpt_close_ch(struct srpt_rdma_ch *ch)
+{
+       struct srpt_device *sdev;
+
+       sdev = ch->sport->sdev;
+       spin_lock_irq(&sdev->spinlock);
+       __srpt_close_ch(ch);
+       spin_unlock_irq(&sdev->spinlock);
+}
+
+/**
+ * srpt_drain_channel() - Drain a channel by resetting the IB queue pair.
+ * @cm_id: Pointer to the CM ID of the channel to be drained.
+ *
+ * Note: Must be called from inside srpt_cm_handler to avoid a race between
+ * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one()
+ * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one()
+ * waits until all target sessions for the associated IB device have been
+ * unregistered and target session registration involves a call to
+ * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until
+ * this function has finished).
+ */
+static void srpt_drain_channel(struct ib_cm_id *cm_id)
+{
+       struct srpt_device *sdev;
+       struct srpt_rdma_ch *ch;
+       int ret;
+       bool do_reset = false;
+
+       WARN_ON_ONCE(irqs_disabled());
+
+       sdev = cm_id->context;
+       BUG_ON(!sdev);
+       spin_lock_irq(&sdev->spinlock);
+       list_for_each_entry(ch, &sdev->rch_list, list) {
+               if (ch->cm_id == cm_id) {
+                       do_reset = srpt_test_and_set_ch_state(ch,
+                                       CH_CONNECTING, CH_DRAINING) ||
+                                  srpt_test_and_set_ch_state(ch,
+                                       CH_LIVE, CH_DRAINING) ||
+                                  srpt_test_and_set_ch_state(ch,
+                                       CH_DISCONNECTING, CH_DRAINING);
+                       break;
+               }
+       }
+       spin_unlock_irq(&sdev->spinlock);
+
+       if (do_reset) {
+               ret = srpt_ch_qp_err(ch);
+               if (ret < 0)
+                       printk(KERN_ERR "Setting queue pair in error state"
+                              " failed: %d\n", ret);
+       }
+}
+
+/**
+ * srpt_find_channel() - Look up an RDMA channel.
+ * @cm_id: Pointer to the CM ID of the channel to be looked up.
+ *
+ * Return NULL if no matching RDMA channel has been found.
+ */
+static struct srpt_rdma_ch *srpt_find_channel(struct srpt_device *sdev,
+                                             struct ib_cm_id *cm_id)
+{
+       struct srpt_rdma_ch *ch;
+       bool found;
+
+       WARN_ON_ONCE(irqs_disabled());
+       BUG_ON(!sdev);
+
+       found = false;
+       spin_lock_irq(&sdev->spinlock);
+       list_for_each_entry(ch, &sdev->rch_list, list) {
+               if (ch->cm_id == cm_id) {
+                       found = true;
+                       break;
+               }
+       }
+       spin_unlock_irq(&sdev->spinlock);
+
+       return found ? ch : NULL;
+}
+
+/**
+ * srpt_release_channel() - Release channel resources.
+ *
+ * Schedules the actual release because:
+ * - Calling the ib_destroy_cm_id() call from inside an IB CM callback would
+ *   trigger a deadlock.
+ * - It is not safe to call TCM transport_* functions from interrupt context.
+ */
+static void srpt_release_channel(struct srpt_rdma_ch *ch)
+{
+       schedule_work(&ch->release_work);
+}
+
+static void srpt_release_channel_work(struct work_struct *w)
+{
+       struct srpt_rdma_ch *ch;
+       struct srpt_device *sdev;
+
+       ch = container_of(w, struct srpt_rdma_ch, release_work);
+       pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess,
+                ch->release_done);
+
+       sdev = ch->sport->sdev;
+       BUG_ON(!sdev);
+
+       transport_deregister_session_configfs(ch->sess);
+       transport_deregister_session(ch->sess);
+       ch->sess = NULL;
+
+       srpt_destroy_ch_ib(ch);
+
+       srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
+                            ch->sport->sdev, ch->rq_size,
+                            ch->rsp_size, DMA_TO_DEVICE);
+
+       spin_lock_irq(&sdev->spinlock);
+       list_del(&ch->list);
+       spin_unlock_irq(&sdev->spinlock);
+
+       ib_destroy_cm_id(ch->cm_id);
+
+       if (ch->release_done)
+               complete(ch->release_done);
+
+       wake_up(&sdev->ch_releaseQ);
+
+       kfree(ch);
+}
+
+static struct srpt_node_acl *__srpt_lookup_acl(struct srpt_port *sport,
+                                              u8 i_port_id[16])
+{
+       struct srpt_node_acl *nacl;
+
+       list_for_each_entry(nacl, &sport->port_acl_list, list)
+               if (memcmp(nacl->i_port_id, i_port_id,
+                          sizeof(nacl->i_port_id)) == 0)
+                       return nacl;
+
+       return NULL;
+}
+
+static struct srpt_node_acl *srpt_lookup_acl(struct srpt_port *sport,
+                                            u8 i_port_id[16])
+{
+       struct srpt_node_acl *nacl;
+
+       spin_lock_irq(&sport->port_acl_lock);
+       nacl = __srpt_lookup_acl(sport, i_port_id);
+       spin_unlock_irq(&sport->port_acl_lock);
+
+       return nacl;
+}
+
+/**
+ * srpt_cm_req_recv() - Process the event IB_CM_REQ_RECEIVED.
+ *
+ * Ownership of the cm_id is transferred to the target session if this
+ * functions returns zero. Otherwise the caller remains the owner of cm_id.
+ */
+static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
+                           struct ib_cm_req_event_param *param,
+                           void *private_data)
+{
+       struct srpt_device *sdev = cm_id->context;
+       struct srpt_port *sport = &sdev->port[param->port - 1];
+       struct srp_login_req *req;
+       struct srp_login_rsp *rsp;
+       struct srp_login_rej *rej;
+       struct ib_cm_rep_param *rep_param;
+       struct srpt_rdma_ch *ch, *tmp_ch;
+       struct srpt_node_acl *nacl;
+       u32 it_iu_len;
+       int i;
+       int ret = 0;
+
+       WARN_ON_ONCE(irqs_disabled());
+
+       if (WARN_ON(!sdev || !private_data))
+               return -EINVAL;
+
+       req = (struct srp_login_req *)private_data;
+
+       it_iu_len = be32_to_cpu(req->req_it_iu_len);
+
+       printk(KERN_INFO "Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx,"
+              " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d"
+              " (guid=0x%llx:0x%llx)\n",
+              be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),
+              be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),
+              be64_to_cpu(*(__be64 *)&req->target_port_id[0]),
+              be64_to_cpu(*(__be64 *)&req->target_port_id[8]),
+              it_iu_len,
+              param->port,
+              be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),
+              be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));
+
+       rsp = kzalloc(sizeof *rsp, GFP_KERNEL);
+       rej = kzalloc(sizeof *rej, GFP_KERNEL);
+       rep_param = kzalloc(sizeof *rep_param, GFP_KERNEL);
+
+       if (!rsp || !rej || !rep_param) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       if (it_iu_len > srp_max_req_size || it_iu_len < 64) {
+               rej->reason = __constant_cpu_to_be32(
+                               SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
+               ret = -EINVAL;
+               printk(KERN_ERR "rejected SRP_LOGIN_REQ because its"
+                      " length (%d bytes) is out of range (%d .. %d)\n",
+                      it_iu_len, 64, srp_max_req_size);
+               goto reject;
+       }
+
+       if (!sport->enabled) {
+               rej->reason = __constant_cpu_to_be32(
+                            SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+               ret = -EINVAL;
+               printk(KERN_ERR "rejected SRP_LOGIN_REQ because the target port"
+                      " has not yet been enabled\n");
+               goto reject;
+       }
+
+       if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
+               rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
+
+               spin_lock_irq(&sdev->spinlock);
+
+               list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {
+                       if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
+                           && !memcmp(ch->t_port_id, req->target_port_id, 16)
+                           && param->port == ch->sport->port
+                           && param->listen_id == ch->sport->sdev->cm_id
+                           && ch->cm_id) {
+                               enum rdma_ch_state ch_state;
+
+                               ch_state = srpt_get_ch_state(ch);
+                               if (ch_state != CH_CONNECTING
+                                   && ch_state != CH_LIVE)
+                                       continue;
+
+                               /* found an existing channel */
+                               pr_debug("Found existing channel %s"
+                                        " cm_id= %p state= %d\n",
+                                        ch->sess_name, ch->cm_id, ch_state);
+
+                               __srpt_close_ch(ch);
+
+                               rsp->rsp_flags =
+                                       SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
+                       }
+               }
+
+               spin_unlock_irq(&sdev->spinlock);
+
+       } else
+               rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
+
+       if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
+           || *(__be64 *)(req->target_port_id + 8) !=
+              cpu_to_be64(srpt_service_guid)) {
+               rej->reason = __constant_cpu_to_be32(
+                               SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
+               ret = -ENOMEM;
+               printk(KERN_ERR "rejected SRP_LOGIN_REQ because it"
+                      " has an invalid target port identifier.\n");
+               goto reject;
+       }
+
+       ch = kzalloc(sizeof *ch, GFP_KERNEL);
+       if (!ch) {
+               rej->reason = __constant_cpu_to_be32(
+                                       SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+               printk(KERN_ERR "rejected SRP_LOGIN_REQ because no memory.\n");
+               ret = -ENOMEM;
+               goto reject;
+       }
+
+       INIT_WORK(&ch->release_work, srpt_release_channel_work);
+       memcpy(ch->i_port_id, req->initiator_port_id, 16);
+       memcpy(ch->t_port_id, req->target_port_id, 16);
+       ch->sport = &sdev->port[param->port - 1];
+       ch->cm_id = cm_id;
+       /*
+        * Avoid QUEUE_FULL conditions by limiting the number of buffers used
+        * for the SRP protocol to the command queue size.
+        */
+       ch->rq_size = SRPT_RQ_SIZE;
+       spin_lock_init(&ch->spinlock);
+       ch->state = CH_CONNECTING;
+       INIT_LIST_HEAD(&ch->cmd_wait_list);
+       ch->rsp_size = ch->sport->port_attrib.srp_max_rsp_size;
+
+       ch->ioctx_ring = (struct srpt_send_ioctx **)
+               srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size,
+                                     sizeof(*ch->ioctx_ring[0]),
+                                     ch->rsp_size, DMA_TO_DEVICE);
+       if (!ch->ioctx_ring)
+               goto free_ch;
+
+       INIT_LIST_HEAD(&ch->free_list);
+       for (i = 0; i < ch->rq_size; i++) {
+               ch->ioctx_ring[i]->ch = ch;
+               list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list);
+       }
+
+       ret = srpt_create_ch_ib(ch);
+       if (ret) {
+               rej->reason = __constant_cpu_to_be32(
+                               SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+               printk(KERN_ERR "rejected SRP_LOGIN_REQ because creating"
+                      " a new RDMA channel failed.\n");
+               goto free_ring;
+       }
+
+       ret = srpt_ch_qp_rtr(ch, ch->qp);
+       if (ret) {
+               rej->reason = __constant_cpu_to_be32(
+                               SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+               printk(KERN_ERR "rejected SRP_LOGIN_REQ because enabling"
+                      " RTR failed (error code = %d)\n", ret);
+               goto destroy_ib;
+       }
+       /*
+        * Use the initator port identifier as the session name.
+        */
+       snprintf(ch->sess_name, sizeof(ch->sess_name), "0x%016llx%016llx",
+                       be64_to_cpu(*(__be64 *)ch->i_port_id),
+                       be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
+
+       pr_debug("registering session %s\n", ch->sess_name);
+
+       nacl = srpt_lookup_acl(sport, ch->i_port_id);
+       if (!nacl) {
+               printk(KERN_INFO "Rejected login because no ACL has been"
+                      " configured yet for initiator %s.\n", ch->sess_name);
+               rej->reason = __constant_cpu_to_be32(
+                               SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
+               goto destroy_ib;
+       }
+
+       ch->sess = transport_init_session();
+       if (IS_ERR(ch->sess)) {
+               rej->reason = __constant_cpu_to_be32(
+                               SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+               pr_debug("Failed to create session\n");
+               goto deregister_session;
+       }
+       ch->sess->se_node_acl = &nacl->nacl;
+       transport_register_session(&sport->port_tpg_1, &nacl->nacl, ch->sess, ch);
+
+       pr_debug("Establish connection sess=%p name=%s cm_id=%p\n", ch->sess,
+                ch->sess_name, ch->cm_id);
+
+       /* create srp_login_response */
+       rsp->opcode = SRP_LOGIN_RSP;
+       rsp->tag = req->tag;
+       rsp->max_it_iu_len = req->req_it_iu_len;
+       rsp->max_ti_iu_len = req->req_it_iu_len;
+       ch->max_ti_iu_len = it_iu_len;
+       rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
+                                             | SRP_BUF_FORMAT_INDIRECT);
+       rsp->req_lim_delta = cpu_to_be32(ch->rq_size);
+       atomic_set(&ch->req_lim, ch->rq_size);
+       atomic_set(&ch->req_lim_delta, 0);
+
+       /* create cm reply */
+       rep_param->qp_num = ch->qp->qp_num;
+       rep_param->private_data = (void *)rsp;
+       rep_param->private_data_len = sizeof *rsp;
+       rep_param->rnr_retry_count = 7;
+       rep_param->flow_control = 1;
+       rep_param->failover_accepted = 0;
+       rep_param->srq = 1;
+       rep_param->responder_resources = 4;
+       rep_param->initiator_depth = 4;
+
+       ret = ib_send_cm_rep(cm_id, rep_param);
+       if (ret) {
+               printk(KERN_ERR "sending SRP_LOGIN_REQ response failed"
+                      " (error code = %d)\n", ret);
+               goto release_channel;
+       }
+
+       spin_lock_irq(&sdev->spinlock);
+       list_add_tail(&ch->list, &sdev->rch_list);
+       spin_unlock_irq(&sdev->spinlock);
+
+       goto out;
+
+release_channel:
+       srpt_set_ch_state(ch, CH_RELEASING);
+       transport_deregister_session_configfs(ch->sess);
+
+deregister_session:
+       transport_deregister_session(ch->sess);
+       ch->sess = NULL;
+
+destroy_ib:
+       srpt_destroy_ch_ib(ch);
+
+free_ring:
+       srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
+                            ch->sport->sdev, ch->rq_size,
+                            ch->rsp_size, DMA_TO_DEVICE);
+free_ch:
+       kfree(ch);
+
+reject:
+       rej->opcode = SRP_LOGIN_REJ;
+       rej->tag = req->tag;
+       rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
+                                             | SRP_BUF_FORMAT_INDIRECT);
+
+       ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
+                            (void *)rej, sizeof *rej);
+
+out:
+       kfree(rep_param);
+       kfree(rsp);
+       kfree(rej);
+
+       return ret;
+}
+
+static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
+{
+       printk(KERN_INFO "Received IB REJ for cm_id %p.\n", cm_id);
+       srpt_drain_channel(cm_id);
+}
+
+/**
+ * srpt_cm_rtu_recv() - Process an IB_CM_RTU_RECEIVED or USER_ESTABLISHED event.
+ *
+ * An IB_CM_RTU_RECEIVED message indicates that the connection is established
+ * and that the recipient may begin transmitting (RTU = ready to use).
+ */
+static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
+{
+       struct srpt_rdma_ch *ch;
+       int ret;
+
+       ch = srpt_find_channel(cm_id->context, cm_id);
+       BUG_ON(!ch);
+
+       if (srpt_test_and_set_ch_state(ch, CH_CONNECTING, CH_LIVE)) {
+               struct srpt_recv_ioctx *ioctx, *ioctx_tmp;
+
+               ret = srpt_ch_qp_rts(ch, ch->qp);
+
+               list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list,
+                                        wait_list) {
+                       list_del(&ioctx->wait_list);
+                       srpt_handle_new_iu(ch, ioctx, NULL);
+               }
+               if (ret)
+                       srpt_close_ch(ch);
+       }
+}
+
+static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id)
+{
+       printk(KERN_INFO "Received IB TimeWait exit for cm_id %p.\n", cm_id);
+       srpt_drain_channel(cm_id);
+}
+
+static void srpt_cm_rep_error(struct ib_cm_id *cm_id)
+{
+       printk(KERN_INFO "Received IB REP error for cm_id %p.\n", cm_id);
+       srpt_drain_channel(cm_id);
+}
+
+/**
+ * srpt_cm_dreq_recv() - Process reception of a DREQ message.
+ */
+static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)
+{
+       struct srpt_rdma_ch *ch;
+       unsigned long flags;
+       bool send_drep = false;
+
+       ch = srpt_find_channel(cm_id->context, cm_id);
+       BUG_ON(!ch);
+
+       pr_debug("cm_id= %p ch->state= %d\n", cm_id, srpt_get_ch_state(ch));
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       switch (ch->state) {
+       case CH_CONNECTING:
+       case CH_LIVE:
+               send_drep = true;
+               ch->state = CH_DISCONNECTING;
+               break;
+       case CH_DISCONNECTING:
+       case CH_DRAINING:
+       case CH_RELEASING:
+               WARN(true, "unexpected channel state %d\n", ch->state);
+               break;
+       }
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+
+       if (send_drep) {
+               if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0)
+                       printk(KERN_ERR "Sending IB DREP failed.\n");
+               printk(KERN_INFO "Received DREQ and sent DREP for session %s.\n",
+                      ch->sess_name);
+       }
+}
+
+/**
+ * srpt_cm_drep_recv() - Process reception of a DREP message.
+ */
+static void srpt_cm_drep_recv(struct ib_cm_id *cm_id)
+{
+       printk(KERN_INFO "Received InfiniBand DREP message for cm_id %p.\n",
+              cm_id);
+       srpt_drain_channel(cm_id);
+}
+
+/**
+ * srpt_cm_handler() - IB connection manager callback function.
+ *
+ * A non-zero return value will cause the caller destroy the CM ID.
+ *
+ * Note: srpt_cm_handler() must only return a non-zero value when transferring
+ * ownership of the cm_id to a channel by srpt_cm_req_recv() failed. Returning
+ * a non-zero value in any other case will trigger a race with the
+ * ib_destroy_cm_id() call in srpt_release_channel().
+ */
+static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+{
+       int ret;
+
+       ret = 0;
+       switch (event->event) {
+       case IB_CM_REQ_RECEIVED:
+               ret = srpt_cm_req_recv(cm_id, &event->param.req_rcvd,
+                                      event->private_data);
+               break;
+       case IB_CM_REJ_RECEIVED:
+               srpt_cm_rej_recv(cm_id);
+               break;
+       case IB_CM_RTU_RECEIVED:
+       case IB_CM_USER_ESTABLISHED:
+               srpt_cm_rtu_recv(cm_id);
+               break;
+       case IB_CM_DREQ_RECEIVED:
+               srpt_cm_dreq_recv(cm_id);
+               break;
+       case IB_CM_DREP_RECEIVED:
+               srpt_cm_drep_recv(cm_id);
+               break;
+       case IB_CM_TIMEWAIT_EXIT:
+               srpt_cm_timewait_exit(cm_id);
+               break;
+       case IB_CM_REP_ERROR:
+               srpt_cm_rep_error(cm_id);
+               break;
+       case IB_CM_DREQ_ERROR:
+               printk(KERN_INFO "Received IB DREQ ERROR event.\n");
+               break;
+       case IB_CM_MRA_RECEIVED:
+               printk(KERN_INFO "Received IB MRA event\n");
+               break;
+       default:
+               printk(KERN_ERR "received unrecognized IB CM event %d\n",
+                      event->event);
+               break;
+       }
+
+       return ret;
+}
+
+/**
+ * srpt_perform_rdmas() - Perform IB RDMA.
+ *
+ * Returns zero upon success or a negative number upon failure.
+ */
+static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
+                             struct srpt_send_ioctx *ioctx)
+{
+       struct ib_send_wr wr;
+       struct ib_send_wr *bad_wr;
+       struct rdma_iu *riu;
+       int i;
+       int ret;
+       int sq_wr_avail;
+       enum dma_data_direction dir;
+       const int n_rdma = ioctx->n_rdma;
+
+       dir = ioctx->cmd.data_direction;
+       if (dir == DMA_TO_DEVICE) {
+               /* write */
+               ret = -ENOMEM;
+               sq_wr_avail = atomic_sub_return(n_rdma, &ch->sq_wr_avail);
+               if (sq_wr_avail < 0) {
+                       printk(KERN_WARNING "IB send queue full (needed %d)\n",
+                              n_rdma);
+                       goto out;
+               }
+       }
+
+       ioctx->rdma_aborted = false;
+       ret = 0;
+       riu = ioctx->rdma_ius;
+       memset(&wr, 0, sizeof wr);
+
+       for (i = 0; i < n_rdma; ++i, ++riu) {
+               if (dir == DMA_FROM_DEVICE) {
+                       wr.opcode = IB_WR_RDMA_WRITE;
+                       wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+                                               SRPT_RDMA_WRITE_LAST :
+                                               SRPT_RDMA_MID,
+                                               ioctx->ioctx.index);
+               } else {
+                       wr.opcode = IB_WR_RDMA_READ;
+                       wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+                                               SRPT_RDMA_READ_LAST :
+                                               SRPT_RDMA_MID,
+                                               ioctx->ioctx.index);
+               }
+               wr.next = NULL;
+               wr.wr.rdma.remote_addr = riu->raddr;
+               wr.wr.rdma.rkey = riu->rkey;
+               wr.num_sge = riu->sge_cnt;
+               wr.sg_list = riu->sge;
+
+               /* only get completion event for the last rdma write */
+               if (i == (n_rdma - 1) && dir == DMA_TO_DEVICE)
+                       wr.send_flags = IB_SEND_SIGNALED;
+
+               ret = ib_post_send(ch->qp, &wr, &bad_wr);
+               if (ret)
+                       break;
+       }
+
+       if (ret)
+               printk(KERN_ERR "%s[%d]: ib_post_send() returned %d for %d/%d",
+                                __func__, __LINE__, ret, i, n_rdma);
+       if (ret && i > 0) {
+               wr.num_sge = 0;
+               wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
+               wr.send_flags = IB_SEND_SIGNALED;
+               while (ch->state == CH_LIVE &&
+                       ib_post_send(ch->qp, &wr, &bad_wr) != 0) {
+                       printk(KERN_INFO "Trying to abort failed RDMA transfer [%d]",
+                               ioctx->ioctx.index);
+                       msleep(1000);
+               }
+               while (ch->state != CH_RELEASING && !ioctx->rdma_aborted) {
+                       printk(KERN_INFO "Waiting until RDMA abort finished [%d]",
+                               ioctx->ioctx.index);
+                       msleep(1000);
+               }
+       }
+out:
+       if (unlikely(dir == DMA_TO_DEVICE && ret < 0))
+               atomic_add(n_rdma, &ch->sq_wr_avail);
+       return ret;
+}
+
+/**
+ * srpt_xfer_data() - Start data transfer from initiator to target.
+ */
+static int srpt_xfer_data(struct srpt_rdma_ch *ch,
+                         struct srpt_send_ioctx *ioctx)
+{
+       int ret;
+
+       ret = srpt_map_sg_to_ib_sge(ch, ioctx);
+       if (ret) {
+               printk(KERN_ERR "%s[%d] ret=%d\n", __func__, __LINE__, ret);
+               goto out;
+       }
+
+       ret = srpt_perform_rdmas(ch, ioctx);
+       if (ret) {
+               if (ret == -EAGAIN || ret == -ENOMEM)
+                       printk(KERN_INFO "%s[%d] queue full -- ret=%d\n",
+                                  __func__, __LINE__, ret);
+               else
+                       printk(KERN_ERR "%s[%d] fatal error -- ret=%d\n",
+                              __func__, __LINE__, ret);
+               goto out_unmap;
+       }
+
+out:
+       return ret;
+out_unmap:
+       srpt_unmap_sg_to_ib_sge(ch, ioctx);
+       goto out;
+}
+
+static int srpt_write_pending_status(struct se_cmd *se_cmd)
+{
+       struct srpt_send_ioctx *ioctx;
+
+       ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+       return srpt_get_cmd_state(ioctx) == SRPT_STATE_NEED_DATA;
+}
+
+/*
+ * srpt_write_pending() - Start data transfer from initiator to target (write).
+ */
+static int srpt_write_pending(struct se_cmd *se_cmd)
+{
+       struct srpt_rdma_ch *ch;
+       struct srpt_send_ioctx *ioctx;
+       enum srpt_command_state new_state;
+       enum rdma_ch_state ch_state;
+       int ret;
+
+       ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+
+       new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA);
+       WARN_ON(new_state == SRPT_STATE_DONE);
+
+       ch = ioctx->ch;
+       BUG_ON(!ch);
+
+       ch_state = srpt_get_ch_state(ch);
+       switch (ch_state) {
+       case CH_CONNECTING:
+               WARN(true, "unexpected channel state %d\n", ch_state);
+               ret = -EINVAL;
+               goto out;
+       case CH_LIVE:
+               break;
+       case CH_DISCONNECTING:
+       case CH_DRAINING:
+       case CH_RELEASING:
+               pr_debug("cmd with tag %lld: channel disconnecting\n",
+                        ioctx->tag);
+               srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN);
+               ret = -EINVAL;
+               goto out;
+       }
+       ret = srpt_xfer_data(ch, ioctx);
+
+out:
+       return ret;
+}
+
+static u8 tcm_to_srp_tsk_mgmt_status(const int tcm_mgmt_status)
+{
+       switch (tcm_mgmt_status) {
+       case TMR_FUNCTION_COMPLETE:
+               return SRP_TSK_MGMT_SUCCESS;
+       case TMR_FUNCTION_REJECTED:
+               return SRP_TSK_MGMT_FUNC_NOT_SUPP;
+       }
+       return SRP_TSK_MGMT_FAILED;
+}
+
+/**
+ * srpt_queue_response() - Transmits the response to a SCSI command.
+ *
+ * Callback function called by the TCM core. Must not block since it can be
+ * invoked on the context of the IB completion handler.
+ */
+static int srpt_queue_response(struct se_cmd *cmd)
+{
+       struct srpt_rdma_ch *ch;
+       struct srpt_send_ioctx *ioctx;
+       enum srpt_command_state state;
+       unsigned long flags;
+       int ret;
+       enum dma_data_direction dir;
+       int resp_len;
+       u8 srp_tm_status;
+
+       ret = 0;
+
+       ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
+       ch = ioctx->ch;
+       BUG_ON(!ch);
+
+       spin_lock_irqsave(&ioctx->spinlock, flags);
+       state = ioctx->state;
+       switch (state) {
+       case SRPT_STATE_NEW:
+       case SRPT_STATE_DATA_IN:
+               ioctx->state = SRPT_STATE_CMD_RSP_SENT;
+               break;
+       case SRPT_STATE_MGMT:
+               ioctx->state = SRPT_STATE_MGMT_RSP_SENT;
+               break;
+       default:
+               WARN(true, "ch %p; cmd %d: unexpected command state %d\n",
+                       ch, ioctx->ioctx.index, ioctx->state);
+               break;
+       }
+       spin_unlock_irqrestore(&ioctx->spinlock, flags);
+
+       if (unlikely(transport_check_aborted_status(&ioctx->cmd, false)
+                    || WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT))) {
+               atomic_inc(&ch->req_lim_delta);
+               srpt_abort_cmd(ioctx);
+               goto out;
+       }
+
+       dir = ioctx->cmd.data_direction;
+
+       /* For read commands, transfer the data to the initiator. */
+       if (dir == DMA_FROM_DEVICE && ioctx->cmd.data_length &&
+           !ioctx->queue_status_only) {
+               ret = srpt_xfer_data(ch, ioctx);
+               if (ret) {
+                       printk(KERN_ERR "xfer_data failed for tag %llu\n",
+                              ioctx->tag);
+                       goto out;
+               }
+       }
+
+       if (state != SRPT_STATE_MGMT)
+               resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->tag,
+                                             cmd->scsi_status);
+       else {
+               srp_tm_status
+                       = tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response);
+               resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status,
+                                                ioctx->tag);
+       }
+       ret = srpt_post_send(ch, ioctx, resp_len);
+       if (ret) {
+               printk(KERN_ERR "sending cmd response failed for tag %llu\n",
+                      ioctx->tag);
+               srpt_unmap_sg_to_ib_sge(ch, ioctx);
+               srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+               kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+       }
+
+out:
+       return ret;
+}
+
+static int srpt_queue_status(struct se_cmd *cmd)
+{
+       struct srpt_send_ioctx *ioctx;
+
+       ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
+       BUG_ON(ioctx->sense_data != cmd->sense_buffer);
+       if (cmd->se_cmd_flags &
+           (SCF_TRANSPORT_TASK_SENSE | SCF_EMULATED_TASK_SENSE))
+               WARN_ON(cmd->scsi_status != SAM_STAT_CHECK_CONDITION);
+       ioctx->queue_status_only = true;
+       return srpt_queue_response(cmd);
+}
+
+static void srpt_refresh_port_work(struct work_struct *work)
+{
+       struct srpt_port *sport = container_of(work, struct srpt_port, work);
+
+       srpt_refresh_port(sport);
+}
+
+static int srpt_ch_list_empty(struct srpt_device *sdev)
+{
+       int res;
+
+       spin_lock_irq(&sdev->spinlock);
+       res = list_empty(&sdev->rch_list);
+       spin_unlock_irq(&sdev->spinlock);
+
+       return res;
+}
+
+/**
+ * srpt_release_sdev() - Free the channel resources associated with a target.
+ */
+static int srpt_release_sdev(struct srpt_device *sdev)
+{
+       struct srpt_rdma_ch *ch, *tmp_ch;
+       int res;
+
+       WARN_ON_ONCE(irqs_disabled());
+
+       BUG_ON(!sdev);
+
+       spin_lock_irq(&sdev->spinlock);
+       list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list)
+               __srpt_close_ch(ch);
+       spin_unlock_irq(&sdev->spinlock);
+
+       res = wait_event_interruptible(sdev->ch_releaseQ,
+                                      srpt_ch_list_empty(sdev));
+       if (res)
+               printk(KERN_ERR "%s: interrupted.\n", __func__);
+
+       return 0;
+}
+
+static struct srpt_port *__srpt_lookup_port(const char *name)
+{
+       struct ib_device *dev;
+       struct srpt_device *sdev;
+       struct srpt_port *sport;
+       int i;
+
+       list_for_each_entry(sdev, &srpt_dev_list, list) {
+               dev = sdev->device;
+               if (!dev)
+                       continue;
+
+               for (i = 0; i < dev->phys_port_cnt; i++) {
+                       sport = &sdev->port[i];
+
+                       if (!strcmp(sport->port_guid, name))
+                               return sport;
+               }
+       }
+
+       return NULL;
+}
+
+static struct srpt_port *srpt_lookup_port(const char *name)
+{
+       struct srpt_port *sport;
+
+       spin_lock(&srpt_dev_lock);
+       sport = __srpt_lookup_port(name);
+       spin_unlock(&srpt_dev_lock);
+
+       return sport;
+}
+
+/**
+ * srpt_add_one() - Infiniband device addition callback function.
+ */
+static void srpt_add_one(struct ib_device *device)
+{
+       struct srpt_device *sdev;
+       struct srpt_port *sport;
+       struct ib_srq_init_attr srq_attr;
+       int i;
+
+       pr_debug("device = %p, device->dma_ops = %p\n", device,
+                device->dma_ops);
+
+       sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
+       if (!sdev)
+               goto err;
+
+       sdev->device = device;
+       INIT_LIST_HEAD(&sdev->rch_list);
+       init_waitqueue_head(&sdev->ch_releaseQ);
+       spin_lock_init(&sdev->spinlock);
+
+       if (ib_query_device(device, &sdev->dev_attr))
+               goto free_dev;
+
+       sdev->pd = ib_alloc_pd(device);
+       if (IS_ERR(sdev->pd))
+               goto free_dev;
+
+       sdev->mr = ib_get_dma_mr(sdev->pd, IB_ACCESS_LOCAL_WRITE);
+       if (IS_ERR(sdev->mr))
+               goto err_pd;
+
+       sdev->srq_size = min(srpt_srq_size, sdev->dev_attr.max_srq_wr);
+
+       srq_attr.event_handler = srpt_srq_event;
+       srq_attr.srq_context = (void *)sdev;
+       srq_attr.attr.max_wr = sdev->srq_size;
+       srq_attr.attr.max_sge = 1;
+       srq_attr.attr.srq_limit = 0;
+
+       sdev->srq = ib_create_srq(sdev->pd, &srq_attr);
+       if (IS_ERR(sdev->srq))
+               goto err_mr;
+
+       pr_debug("%s: create SRQ #wr= %d max_allow=%d dev= %s\n",
+                __func__, sdev->srq_size, sdev->dev_attr.max_srq_wr,
+                device->name);
+
+       if (!srpt_service_guid)
+               srpt_service_guid = be64_to_cpu(device->node_guid);
+
+       sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev);
+       if (IS_ERR(sdev->cm_id))
+               goto err_srq;
+
+       /* print out target login information */
+       pr_debug("Target login info: id_ext=%016llx,ioc_guid=%016llx,"
+                "pkey=ffff,service_id=%016llx\n", srpt_service_guid,
+                srpt_service_guid, srpt_service_guid);
+
+       /*
+        * We do not have a consistent service_id (ie. also id_ext of target_id)
+        * to identify this target. We currently use the guid of the first HCA
+        * in the system as service_id; therefore, the target_id will change
+        * if this HCA is gone bad and replaced by different HCA
+        */
+       if (ib_cm_listen(sdev->cm_id, cpu_to_be64(srpt_service_guid), 0, NULL))
+               goto err_cm;
+
+       INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device,
+                             srpt_event_handler);
+       if (ib_register_event_handler(&sdev->event_handler))
+               goto err_cm;
+
+       sdev->ioctx_ring = (struct srpt_recv_ioctx **)
+               srpt_alloc_ioctx_ring(sdev, sdev->srq_size,
+                                     sizeof(*sdev->ioctx_ring[0]),
+                                     srp_max_req_size, DMA_FROM_DEVICE);
+       if (!sdev->ioctx_ring)
+               goto err_event;
+
+       for (i = 0; i < sdev->srq_size; ++i)
+               srpt_post_recv(sdev, sdev->ioctx_ring[i]);
+
+       WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port));
+
+       for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
+               sport = &sdev->port[i - 1];
+               sport->sdev = sdev;
+               sport->port = i;
+               sport->port_attrib.srp_max_rdma_size = DEFAULT_MAX_RDMA_SIZE;
+               sport->port_attrib.srp_max_rsp_size = DEFAULT_MAX_RSP_SIZE;
+               sport->port_attrib.srp_sq_size = DEF_SRPT_SQ_SIZE;
+               INIT_WORK(&sport->work, srpt_refresh_port_work);
+               INIT_LIST_HEAD(&sport->port_acl_list);
+               spin_lock_init(&sport->port_acl_lock);
+
+               if (srpt_refresh_port(sport)) {
+                       printk(KERN_ERR "MAD registration failed for %s-%d.\n",
+                              srpt_sdev_name(sdev), i);
+                       goto err_ring;
+               }
+               snprintf(sport->port_guid, sizeof(sport->port_guid),
+                       "0x%016llx%016llx",
+                       be64_to_cpu(sport->gid.global.subnet_prefix),
+                       be64_to_cpu(sport->gid.global.interface_id));
+       }
+
+       spin_lock(&srpt_dev_lock);
+       list_add_tail(&sdev->list, &srpt_dev_list);
+       spin_unlock(&srpt_dev_lock);
+
+out:
+       ib_set_client_data(device, &srpt_client, sdev);
+       pr_debug("added %s.\n", device->name);
+       return;
+
+err_ring:
+       srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
+                            sdev->srq_size, srp_max_req_size,
+                            DMA_FROM_DEVICE);
+err_event:
+       ib_unregister_event_handler(&sdev->event_handler);
+err_cm:
+       ib_destroy_cm_id(sdev->cm_id);
+err_srq:
+       ib_destroy_srq(sdev->srq);
+err_mr:
+       ib_dereg_mr(sdev->mr);
+err_pd:
+       ib_dealloc_pd(sdev->pd);
+free_dev:
+       kfree(sdev);
+err:
+       sdev = NULL;
+       printk(KERN_INFO "%s(%s) failed.\n", __func__, device->name);
+       goto out;
+}
+
+/**
+ * srpt_remove_one() - InfiniBand device removal callback function.
+ */
+static void srpt_remove_one(struct ib_device *device)
+{
+       struct srpt_device *sdev;
+       int i;
+
+       sdev = ib_get_client_data(device, &srpt_client);
+       if (!sdev) {
+               printk(KERN_INFO "%s(%s): nothing to do.\n", __func__,
+                      device->name);
+               return;
+       }
+
+       srpt_unregister_mad_agent(sdev);
+
+       ib_unregister_event_handler(&sdev->event_handler);
+
+       /* Cancel any work queued by the just unregistered IB event handler. */
+       for (i = 0; i < sdev->device->phys_port_cnt; i++)
+               cancel_work_sync(&sdev->port[i].work);
+
+       ib_destroy_cm_id(sdev->cm_id);
+
+       /*
+        * Unregistering a target must happen after destroying sdev->cm_id
+        * such that no new SRP_LOGIN_REQ information units can arrive while
+        * destroying the target.
+        */
+       spin_lock(&srpt_dev_lock);
+       list_del(&sdev->list);
+       spin_unlock(&srpt_dev_lock);
+       srpt_release_sdev(sdev);
+
+       ib_destroy_srq(sdev->srq);
+       ib_dereg_mr(sdev->mr);
+       ib_dealloc_pd(sdev->pd);
+
+       srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
+                            sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE);
+       sdev->ioctx_ring = NULL;
+       kfree(sdev);
+}
+
+static struct ib_client srpt_client = {
+       .name = DRV_NAME,
+       .add = srpt_add_one,
+       .remove = srpt_remove_one
+};
+
+static int srpt_check_true(struct se_portal_group *se_tpg)
+{
+       return 1;
+}
+
+static int srpt_check_false(struct se_portal_group *se_tpg)
+{
+       return 0;
+}
+
+static char *srpt_get_fabric_name(void)
+{
+       return "srpt";
+}
+
+static u8 srpt_get_fabric_proto_ident(struct se_portal_group *se_tpg)
+{
+       return SCSI_TRANSPORTID_PROTOCOLID_SRP;
+}
+
+static char *srpt_get_fabric_wwn(struct se_portal_group *tpg)
+{
+       struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);
+
+       return sport->port_guid;
+}
+
+static u16 srpt_get_tag(struct se_portal_group *tpg)
+{
+       return 1;
+}
+
+static u32 srpt_get_default_depth(struct se_portal_group *se_tpg)
+{
+       return 1;
+}
+
+static u32 srpt_get_pr_transport_id(struct se_portal_group *se_tpg,
+                                   struct se_node_acl *se_nacl,
+                                   struct t10_pr_registration *pr_reg,
+                                   int *format_code, unsigned char *buf)
+{
+       struct srpt_node_acl *nacl;
+       struct spc_rdma_transport_id *tr_id;
+
+       nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+       tr_id = (void *)buf;
+       tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP;
+       memcpy(tr_id->i_port_id, nacl->i_port_id, sizeof(tr_id->i_port_id));
+       return sizeof(*tr_id);
+}
+
+static u32 srpt_get_pr_transport_id_len(struct se_portal_group *se_tpg,
+                                       struct se_node_acl *se_nacl,
+                                       struct t10_pr_registration *pr_reg,
+                                       int *format_code)
+{
+       *format_code = 0;
+       return sizeof(struct spc_rdma_transport_id);
+}
+
+static char *srpt_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
+                                           const char *buf, u32 *out_tid_len,
+                                           char **port_nexus_ptr)
+{
+       struct spc_rdma_transport_id *tr_id;
+
+       *port_nexus_ptr = NULL;
+       *out_tid_len = sizeof(struct spc_rdma_transport_id);
+       tr_id = (void *)buf;
+       return (char *)tr_id->i_port_id;
+}
+
+static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg)
+{
+       struct srpt_node_acl *nacl;
+
+       nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL);
+       if (!nacl) {
+               printk(KERN_ERR "Unable to alocate struct srpt_node_acl\n");
+               return NULL;
+       }
+
+       return &nacl->nacl;
+}
+
+static void srpt_release_fabric_acl(struct se_portal_group *se_tpg,
+                                   struct se_node_acl *se_nacl)
+{
+       struct srpt_node_acl *nacl;
+
+       nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+       kfree(nacl);
+}
+
+static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+       return 1;
+}
+
+static void srpt_release_cmd(struct se_cmd *se_cmd)
+{
+}
+
+/**
+ * srpt_shutdown_session() - Whether or not a session may be shut down.
+ */
+static int srpt_shutdown_session(struct se_session *se_sess)
+{
+       return true;
+}
+
+/**
+ * srpt_close_session() - Forcibly close a session.
+ *
+ * Callback function invoked by the TCM core to clean up sessions associated
+ * with a node ACL when the user invokes
+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
+ */
+static void srpt_close_session(struct se_session *se_sess)
+{
+       DECLARE_COMPLETION_ONSTACK(release_done);
+       struct srpt_rdma_ch *ch;
+       struct srpt_device *sdev;
+       int res;
+
+       ch = se_sess->fabric_sess_ptr;
+       WARN_ON(ch->sess != se_sess);
+
+       pr_debug("ch %p state %d\n", ch, srpt_get_ch_state(ch));
+
+       sdev = ch->sport->sdev;
+       spin_lock_irq(&sdev->spinlock);
+       BUG_ON(ch->release_done);
+       ch->release_done = &release_done;
+       __srpt_close_ch(ch);
+       spin_unlock_irq(&sdev->spinlock);
+
+       res = wait_for_completion_timeout(&release_done, 60 * HZ);
+       WARN_ON(res <= 0);
+}
+
+/**
+ * To do: Find out whether stop_session() has a meaning for transports
+ * other than iSCSI.
+ */
+static void srpt_stop_session(struct se_session *se_sess, int sess_sleep,
+                             int conn_sleep)
+{
+}
+
+static void srpt_reset_nexus(struct se_session *sess)
+{
+       printk(KERN_ERR "This is the SRP protocol, not iSCSI\n");
+}
+
+static int srpt_sess_logged_in(struct se_session *se_sess)
+{
+       return true;
+}
+
+/**
+ * srpt_sess_get_index() - Return the value of scsiAttIntrPortIndex (SCSI-MIB).
+ *
+ * A quote from RFC 4455 (SCSI-MIB) about this MIB object:
+ * This object represents an arbitrary integer used to uniquely identify a
+ * particular attached remote initiator port to a particular SCSI target port
+ * within a particular SCSI target device within a particular SCSI instance.
+ */
+static u32 srpt_sess_get_index(struct se_session *se_sess)
+{
+       return 0;
+}
+
+static void srpt_set_default_node_attrs(struct se_node_acl *nacl)
+{
+}
+
+static u32 srpt_get_task_tag(struct se_cmd *se_cmd)
+{
+       struct srpt_send_ioctx *ioctx;
+
+       ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+       return ioctx->tag;
+}
+
+/* Note: only used from inside debug printk's by the TCM core. */
+static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd)
+{
+       struct srpt_send_ioctx *ioctx;
+
+       ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+       return srpt_get_cmd_state(ioctx);
+}
+
+static u16 srpt_set_fabric_sense_len(struct se_cmd *cmd, u32 sense_length)
+{
+       return 0;
+}
+
+static u16 srpt_get_fabric_sense_len(void)
+{
+       return 0;
+}
+
+static int srpt_is_state_remove(struct se_cmd *se_cmd)
+{
+       return 0;
+}
+
+/**
+ * srpt_parse_i_port_id() - Parse an initiator port ID.
+ * @name: ASCII representation of a 128-bit initiator port ID.
+ * @i_port_id: Binary 128-bit port ID.
+ */
+static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)
+{
+       const char *p;
+       unsigned len, count, leading_zero_bytes;
+       int ret, rc;
+
+       p = name;
+       if (strnicmp(p, "0x", 2) == 0)
+               p += 2;
+       ret = -EINVAL;
+       len = strlen(p);
+       if (len % 2)
+               goto out;
+       count = min(len / 2, 16U);
+       leading_zero_bytes = 16 - count;
+       memset(i_port_id, 0, leading_zero_bytes);
+       rc = hex2bin(i_port_id + leading_zero_bytes, p, count);
+       if (rc < 0)
+               pr_debug("hex2bin failed for srpt_parse_i_port_id: %d\n", rc);
+       ret = 0;
+out:
+       return ret;
+}
+
+/*
+ * configfs callback function invoked for
+ * mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
+ */
+static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg,
+                                            struct config_group *group,
+                                            const char *name)
+{
+       struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);
+       struct se_node_acl *se_nacl, *se_nacl_new;
+       struct srpt_node_acl *nacl;
+       int ret = 0;
+       u32 nexus_depth = 1;
+       u8 i_port_id[16];
+
+       if (srpt_parse_i_port_id(i_port_id, name) < 0) {
+               printk(KERN_ERR "invalid initiator port ID %s\n", name);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       se_nacl_new = srpt_alloc_fabric_acl(tpg);
+       if (!se_nacl_new) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       /*
+        * nacl_new may be released by core_tpg_add_initiator_node_acl()
+        * when converting a node ACL from demo mode to explict
+        */
+       se_nacl = core_tpg_add_initiator_node_acl(tpg, se_nacl_new, name,
+                                                 nexus_depth);
+       if (IS_ERR(se_nacl)) {
+               ret = PTR_ERR(se_nacl);
+               goto err;
+       }
+       /* Locate our struct srpt_node_acl and set sdev and i_port_id. */
+       nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+       memcpy(&nacl->i_port_id[0], &i_port_id[0], 16);
+       nacl->sport = sport;
+
+       spin_lock_irq(&sport->port_acl_lock);
+       list_add_tail(&nacl->list, &sport->port_acl_list);
+       spin_unlock_irq(&sport->port_acl_lock);
+
+       return se_nacl;
+err:
+       return ERR_PTR(ret);
+}
+
+/*
+ * configfs callback function invoked for
+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
+ */
+static void srpt_drop_nodeacl(struct se_node_acl *se_nacl)
+{
+       struct srpt_node_acl *nacl;
+       struct srpt_device *sdev;
+       struct srpt_port *sport;
+
+       nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+       sport = nacl->sport;
+       sdev = sport->sdev;
+       spin_lock_irq(&sport->port_acl_lock);
+       list_del(&nacl->list);
+       spin_unlock_irq(&sport->port_acl_lock);
+       core_tpg_del_initiator_node_acl(&sport->port_tpg_1, se_nacl, 1);
+       srpt_release_fabric_acl(NULL, se_nacl);
+}
+
+static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+       return sprintf(page, "%u\n", sport->port_attrib.srp_max_rdma_size);
+}
+
+static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(page, 0, &val);
+       if (ret < 0) {
+               pr_err("strict_strtoul() failed with ret: %d\n", ret);
+               return -EINVAL;
+       }
+       if (val > MAX_SRPT_RDMA_SIZE) {
+               pr_err("val: %lu exceeds MAX_SRPT_RDMA_SIZE: %d\n", val,
+                       MAX_SRPT_RDMA_SIZE);
+               return -EINVAL;
+       }
+       if (val < DEFAULT_MAX_RDMA_SIZE) {
+               pr_err("val: %lu smaller than DEFAULT_MAX_RDMA_SIZE: %d\n",
+                       val, DEFAULT_MAX_RDMA_SIZE);
+               return -EINVAL;
+       }
+       sport->port_attrib.srp_max_rdma_size = val;
+
+       return count;
+}
+
+TF_TPG_ATTRIB_ATTR(srpt, srp_max_rdma_size, S_IRUGO | S_IWUSR);
+
+static ssize_t srpt_tpg_attrib_show_srp_max_rsp_size(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+       return sprintf(page, "%u\n", sport->port_attrib.srp_max_rsp_size);
+}
+
+static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(page, 0, &val);
+       if (ret < 0) {
+               pr_err("strict_strtoul() failed with ret: %d\n", ret);
+               return -EINVAL;
+       }
+       if (val > MAX_SRPT_RSP_SIZE) {
+               pr_err("val: %lu exceeds MAX_SRPT_RSP_SIZE: %d\n", val,
+                       MAX_SRPT_RSP_SIZE);
+               return -EINVAL;
+       }
+       if (val < MIN_MAX_RSP_SIZE) {
+               pr_err("val: %lu smaller than MIN_MAX_RSP_SIZE: %d\n", val,
+                       MIN_MAX_RSP_SIZE);
+               return -EINVAL;
+       }
+       sport->port_attrib.srp_max_rsp_size = val;
+
+       return count;
+}
+
+TF_TPG_ATTRIB_ATTR(srpt, srp_max_rsp_size, S_IRUGO | S_IWUSR);
+
+static ssize_t srpt_tpg_attrib_show_srp_sq_size(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+       return sprintf(page, "%u\n", sport->port_attrib.srp_sq_size);
+}
+
+static ssize_t srpt_tpg_attrib_store_srp_sq_size(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(page, 0, &val);
+       if (ret < 0) {
+               pr_err("strict_strtoul() failed with ret: %d\n", ret);
+               return -EINVAL;
+       }
+       if (val > MAX_SRPT_SRQ_SIZE) {
+               pr_err("val: %lu exceeds MAX_SRPT_SRQ_SIZE: %d\n", val,
+                       MAX_SRPT_SRQ_SIZE);
+               return -EINVAL;
+       }
+       if (val < MIN_SRPT_SRQ_SIZE) {
+               pr_err("val: %lu smaller than MIN_SRPT_SRQ_SIZE: %d\n", val,
+                       MIN_SRPT_SRQ_SIZE);
+               return -EINVAL;
+       }
+       sport->port_attrib.srp_sq_size = val;
+
+       return count;
+}
+
+TF_TPG_ATTRIB_ATTR(srpt, srp_sq_size, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *srpt_tpg_attrib_attrs[] = {
+       &srpt_tpg_attrib_srp_max_rdma_size.attr,
+       &srpt_tpg_attrib_srp_max_rsp_size.attr,
+       &srpt_tpg_attrib_srp_sq_size.attr,
+       NULL,
+};
+
+static ssize_t srpt_tpg_show_enable(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+       return snprintf(page, PAGE_SIZE, "%d\n", (sport->enabled) ? 1: 0);
+}
+
+static ssize_t srpt_tpg_store_enable(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+       unsigned long tmp;
+        int ret;
+
+       ret = strict_strtoul(page, 0, &tmp);
+       if (ret < 0) {
+               printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n");
+               return -EINVAL;
+       }
+
+       if ((tmp != 0) && (tmp != 1)) {
+               printk(KERN_ERR "Illegal value for srpt_tpg_store_enable: %lu\n", tmp);
+               return -EINVAL;
+       }
+       if (tmp == 1)
+               sport->enabled = true;
+       else
+               sport->enabled = false;
+
+       return count;
+}
+
+TF_TPG_BASE_ATTR(srpt, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *srpt_tpg_attrs[] = {
+       &srpt_tpg_enable.attr,
+       NULL,
+};
+
+/**
+ * configfs callback invoked for
+ * mkdir /sys/kernel/config/target/$driver/$port/$tpg
+ */
+static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
+                                            struct config_group *group,
+                                            const char *name)
+{
+       struct srpt_port *sport = container_of(wwn, struct srpt_port, port_wwn);
+       int res;
+
+       /* Initialize sport->port_wwn and sport->port_tpg_1 */
+       res = core_tpg_register(&srpt_target->tf_ops, &sport->port_wwn,
+                       &sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
+       if (res)
+               return ERR_PTR(res);
+
+       return &sport->port_tpg_1;
+}
+
+/**
+ * configfs callback invoked for
+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg
+ */
+static void srpt_drop_tpg(struct se_portal_group *tpg)
+{
+       struct srpt_port *sport = container_of(tpg,
+                               struct srpt_port, port_tpg_1);
+
+       sport->enabled = false;
+       core_tpg_deregister(&sport->port_tpg_1);
+}
+
+/**
+ * configfs callback invoked for
+ * mkdir /sys/kernel/config/target/$driver/$port
+ */
+static struct se_wwn *srpt_make_tport(struct target_fabric_configfs *tf,
+                                     struct config_group *group,
+                                     const char *name)
+{
+       struct srpt_port *sport;
+       int ret;
+
+       sport = srpt_lookup_port(name);
+       pr_debug("make_tport(%s)\n", name);
+       ret = -EINVAL;
+       if (!sport)
+               goto err;
+
+       return &sport->port_wwn;
+
+err:
+       return ERR_PTR(ret);
+}
+
+/**
+ * configfs callback invoked for
+ * rmdir /sys/kernel/config/target/$driver/$port
+ */
+static void srpt_drop_tport(struct se_wwn *wwn)
+{
+       struct srpt_port *sport = container_of(wwn, struct srpt_port, port_wwn);
+
+       pr_debug("drop_tport(%s\n", config_item_name(&sport->port_wwn.wwn_group.cg_item));
+}
+
+static ssize_t srpt_wwn_show_attr_version(struct target_fabric_configfs *tf,
+                                             char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%s\n", DRV_VERSION);
+}
+
+TF_WWN_ATTR_RO(srpt, version);
+
+static struct configfs_attribute *srpt_wwn_attrs[] = {
+       &srpt_wwn_version.attr,
+       NULL,
+};
+
+static struct target_core_fabric_ops srpt_template = {
+       .get_fabric_name                = srpt_get_fabric_name,
+       .get_fabric_proto_ident         = srpt_get_fabric_proto_ident,
+       .tpg_get_wwn                    = srpt_get_fabric_wwn,
+       .tpg_get_tag                    = srpt_get_tag,
+       .tpg_get_default_depth          = srpt_get_default_depth,
+       .tpg_get_pr_transport_id        = srpt_get_pr_transport_id,
+       .tpg_get_pr_transport_id_len    = srpt_get_pr_transport_id_len,
+       .tpg_parse_pr_out_transport_id  = srpt_parse_pr_out_transport_id,
+       .tpg_check_demo_mode            = srpt_check_false,
+       .tpg_check_demo_mode_cache      = srpt_check_true,
+       .tpg_check_demo_mode_write_protect = srpt_check_true,
+       .tpg_check_prod_mode_write_protect = srpt_check_false,
+       .tpg_alloc_fabric_acl           = srpt_alloc_fabric_acl,
+       .tpg_release_fabric_acl         = srpt_release_fabric_acl,
+       .tpg_get_inst_index             = srpt_tpg_get_inst_index,
+       .release_cmd                    = srpt_release_cmd,
+       .check_stop_free                = srpt_check_stop_free,
+       .shutdown_session               = srpt_shutdown_session,
+       .close_session                  = srpt_close_session,
+       .stop_session                   = srpt_stop_session,
+       .fall_back_to_erl0              = srpt_reset_nexus,
+       .sess_logged_in                 = srpt_sess_logged_in,
+       .sess_get_index                 = srpt_sess_get_index,
+       .sess_get_initiator_sid         = NULL,
+       .write_pending                  = srpt_write_pending,
+       .write_pending_status           = srpt_write_pending_status,
+       .set_default_node_attributes    = srpt_set_default_node_attrs,
+       .get_task_tag                   = srpt_get_task_tag,
+       .get_cmd_state                  = srpt_get_tcm_cmd_state,
+       .queue_data_in                  = srpt_queue_response,
+       .queue_status                   = srpt_queue_status,
+       .queue_tm_rsp                   = srpt_queue_response,
+       .get_fabric_sense_len           = srpt_get_fabric_sense_len,
+       .set_fabric_sense_len           = srpt_set_fabric_sense_len,
+       .is_state_remove                = srpt_is_state_remove,
+       /*
+        * Setup function pointers for generic logic in
+        * target_core_fabric_configfs.c
+        */
+       .fabric_make_wwn                = srpt_make_tport,
+       .fabric_drop_wwn                = srpt_drop_tport,
+       .fabric_make_tpg                = srpt_make_tpg,
+       .fabric_drop_tpg                = srpt_drop_tpg,
+       .fabric_post_link               = NULL,
+       .fabric_pre_unlink              = NULL,
+       .fabric_make_np                 = NULL,
+       .fabric_drop_np                 = NULL,
+       .fabric_make_nodeacl            = srpt_make_nodeacl,
+       .fabric_drop_nodeacl            = srpt_drop_nodeacl,
+};
+
+/**
+ * srpt_init_module() - Kernel module initialization.
+ *
+ * Note: Since ib_register_client() registers callback functions, and since at
+ * least one of these callback functions (srpt_add_one()) calls target core
+ * functions, this driver must be registered with the target core before
+ * ib_register_client() is called.
+ */
+static int __init srpt_init_module(void)
+{
+       int ret;
+
+       ret = -EINVAL;
+       if (srp_max_req_size < MIN_MAX_REQ_SIZE) {
+               printk(KERN_ERR "invalid value %d for kernel module parameter"
+                      " srp_max_req_size -- must be at least %d.\n",
+                      srp_max_req_size, MIN_MAX_REQ_SIZE);
+               goto out;
+       }
+
+       if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
+           || srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
+               printk(KERN_ERR "invalid value %d for kernel module parameter"
+                      " srpt_srq_size -- must be in the range [%d..%d].\n",
+                      srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE);
+               goto out;
+       }
+
+       srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
+       if (IS_ERR(srpt_target)) {
+               printk(KERN_ERR "couldn't register\n");
+               ret = PTR_ERR(srpt_target);
+               goto out;
+       }
+
+       srpt_target->tf_ops = srpt_template;
+
+       /* Enable SG chaining */
+       srpt_target->tf_ops.task_sg_chaining = true;
+
+       /*
+        * Set up default attribute lists.
+        */
+       srpt_target->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = srpt_wwn_attrs;
+       srpt_target->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = srpt_tpg_attrs;
+       srpt_target->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = srpt_tpg_attrib_attrs;
+       srpt_target->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
+       srpt_target->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
+       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
+       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
+       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
+       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
+
+       ret = target_fabric_configfs_register(srpt_target);
+       if (ret < 0) {
+               printk(KERN_ERR "couldn't register\n");
+               goto out_free_target;
+       }
+
+       ret = ib_register_client(&srpt_client);
+       if (ret) {
+               printk(KERN_ERR "couldn't register IB client\n");
+               goto out_unregister_target;
+       }
+
+       return 0;
+
+out_unregister_target:
+       target_fabric_configfs_deregister(srpt_target);
+       srpt_target = NULL;
+out_free_target:
+       if (srpt_target)
+               target_fabric_configfs_free(srpt_target);
+out:
+       return ret;
+}
+
+static void __exit srpt_cleanup_module(void)
+{
+       ib_unregister_client(&srpt_client);
+       target_fabric_configfs_deregister(srpt_target);
+       srpt_target = NULL;
+}
+
+module_init(srpt_init_module);
+module_exit(srpt_cleanup_module);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
new file mode 100644 (file)
index 0000000..61e52b8
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc.  All rights reserved.
+ * Copyright (C) 2009 - 2010 Bart Van Assche <bvanassche@acm.org>.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef IB_SRPT_H
+#define IB_SRPT_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_cm.h>
+
+#include <scsi/srp.h>
+
+#include "ib_dm_mad.h"
+
+/*
+ * The prefix the ServiceName field must start with in the device management
+ * ServiceEntries attribute pair. See also the SRP specification.
+ */
+#define SRP_SERVICE_NAME_PREFIX                "SRP.T10:"
+
+enum {
+       /*
+        * SRP IOControllerProfile attributes for SRP target ports that have
+        * not been defined in <scsi/srp.h>. Source: section B.7, table B.7
+        * in the SRP specification.
+        */
+       SRP_PROTOCOL = 0x0108,
+       SRP_PROTOCOL_VERSION = 0x0001,
+       SRP_IO_SUBCLASS = 0x609e,
+       SRP_SEND_TO_IOC = 0x01,
+       SRP_SEND_FROM_IOC = 0x02,
+       SRP_RDMA_READ_FROM_IOC = 0x08,
+       SRP_RDMA_WRITE_FROM_IOC = 0x20,
+
+       /*
+        * srp_login_cmd.req_flags bitmasks. See also table 9 in the SRP
+        * specification.
+        */
+       SRP_MTCH_ACTION = 0x03, /* MULTI-CHANNEL ACTION */
+       SRP_LOSOLNT = 0x10, /* logout solicited notification */
+       SRP_CRSOLNT = 0x20, /* credit request solicited notification */
+       SRP_AESOLNT = 0x40, /* asynchronous event solicited notification */
+
+       /*
+        * srp_cmd.sol_nt / srp_tsk_mgmt.sol_not bitmasks. See also tables
+        * 18 and 20 in the SRP specification.
+        */
+       SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */
+       SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */
+
+       /*
+        * srp_rsp.sol_not / srp_t_logout.sol_not bitmasks. See also tables
+        * 16 and 22 in the SRP specification.
+        */
+       SRP_SOLNT = 0x01, /* SOLNT = solicited notification */
+
+       /* See also table 24 in the SRP specification. */
+       SRP_TSK_MGMT_SUCCESS = 0x00,
+       SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,
+       SRP_TSK_MGMT_FAILED = 0x05,
+
+       /* See also table 21 in the SRP specification. */
+       SRP_CMD_SIMPLE_Q = 0x0,
+       SRP_CMD_HEAD_OF_Q = 0x1,
+       SRP_CMD_ORDERED_Q = 0x2,
+       SRP_CMD_ACA = 0x4,
+
+       SRP_LOGIN_RSP_MULTICHAN_NO_CHAN = 0x0,
+       SRP_LOGIN_RSP_MULTICHAN_TERMINATED = 0x1,
+       SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,
+
+       SRPT_DEF_SG_TABLESIZE = 128,
+       SRPT_DEF_SG_PER_WQE = 16,
+
+       MIN_SRPT_SQ_SIZE = 16,
+       DEF_SRPT_SQ_SIZE = 4096,
+       SRPT_RQ_SIZE = 128,
+       MIN_SRPT_SRQ_SIZE = 4,
+       DEFAULT_SRPT_SRQ_SIZE = 4095,
+       MAX_SRPT_SRQ_SIZE = 65535,
+       MAX_SRPT_RDMA_SIZE = 1U << 24,
+       MAX_SRPT_RSP_SIZE = 1024,
+
+       MIN_MAX_REQ_SIZE = 996,
+       DEFAULT_MAX_REQ_SIZE
+               = sizeof(struct srp_cmd)/*48*/
+               + sizeof(struct srp_indirect_buf)/*20*/
+               + 128 * sizeof(struct srp_direct_buf)/*16*/,
+
+       MIN_MAX_RSP_SIZE = sizeof(struct srp_rsp)/*36*/ + 4,
+       DEFAULT_MAX_RSP_SIZE = 256, /* leaves 220 bytes for sense data */
+
+       DEFAULT_MAX_RDMA_SIZE = 65536,
+};
+
+enum srpt_opcode {
+       SRPT_RECV,
+       SRPT_SEND,
+       SRPT_RDMA_MID,
+       SRPT_RDMA_ABORT,
+       SRPT_RDMA_READ_LAST,
+       SRPT_RDMA_WRITE_LAST,
+};
+
+static inline u64 encode_wr_id(u8 opcode, u32 idx)
+{
+       return ((u64)opcode << 32) | idx;
+}
+static inline enum srpt_opcode opcode_from_wr_id(u64 wr_id)
+{
+       return wr_id >> 32;
+}
+static inline u32 idx_from_wr_id(u64 wr_id)
+{
+       return (u32)wr_id;
+}
+
+struct rdma_iu {
+       u64             raddr;
+       u32             rkey;
+       struct ib_sge   *sge;
+       u32             sge_cnt;
+       int             mem_id;
+};
+
+/**
+ * enum srpt_command_state - SCSI command state managed by SRPT.
+ * @SRPT_STATE_NEW:           New command arrived and is being processed.
+ * @SRPT_STATE_NEED_DATA:     Processing a write or bidir command and waiting
+ *                            for data arrival.
+ * @SRPT_STATE_DATA_IN:       Data for the write or bidir command arrived and is
+ *                            being processed.
+ * @SRPT_STATE_CMD_RSP_SENT:  SRP_RSP for SRP_CMD has been sent.
+ * @SRPT_STATE_MGMT:          Processing a SCSI task management command.
+ * @SRPT_STATE_MGMT_RSP_SENT: SRP_RSP for SRP_TSK_MGMT has been sent.
+ * @SRPT_STATE_DONE:          Command processing finished successfully, command
+ *                            processing has been aborted or command processing
+ *                            failed.
+ */
+enum srpt_command_state {
+       SRPT_STATE_NEW           = 0,
+       SRPT_STATE_NEED_DATA     = 1,
+       SRPT_STATE_DATA_IN       = 2,
+       SRPT_STATE_CMD_RSP_SENT  = 3,
+       SRPT_STATE_MGMT          = 4,
+       SRPT_STATE_MGMT_RSP_SENT = 5,
+       SRPT_STATE_DONE          = 6,
+};
+
+/**
+ * struct srpt_ioctx - Shared SRPT I/O context information.
+ * @buf:   Pointer to the buffer.
+ * @dma:   DMA address of the buffer.
+ * @index: Index of the I/O context in its ioctx_ring array.
+ */
+struct srpt_ioctx {
+       void                    *buf;
+       dma_addr_t              dma;
+       uint32_t                index;
+};
+
+/**
+ * struct srpt_recv_ioctx - SRPT receive I/O context.
+ * @ioctx:     See above.
+ * @wait_list: Node for insertion in srpt_rdma_ch.cmd_wait_list.
+ */
+struct srpt_recv_ioctx {
+       struct srpt_ioctx       ioctx;
+       struct list_head        wait_list;
+};
+
+/**
+ * struct srpt_send_ioctx - SRPT send I/O context.
+ * @ioctx:       See above.
+ * @ch:          Channel pointer.
+ * @free_list:   Node in srpt_rdma_ch.free_list.
+ * @n_rbuf:      Number of data buffers in the received SRP command.
+ * @rbufs:       Pointer to SRP data buffer array.
+ * @single_rbuf: SRP data buffer if the command has only a single buffer.
+ * @sg:          Pointer to sg-list associated with this I/O context.
+ * @sg_cnt:      SG-list size.
+ * @mapped_sg_count: ib_dma_map_sg() return value.
+ * @n_rdma_ius:  Number of elements in the rdma_ius array.
+ * @rdma_ius:    Array with information about the RDMA mapping.
+ * @tag:         Tag of the received SRP information unit.
+ * @spinlock:    Protects 'state'.
+ * @state:       I/O context state.
+ * @rdma_aborted: If initiating a multipart RDMA transfer failed, whether
+ *              the already initiated transfers have finished.
+ * @cmd:         Target core command data structure.
+ * @sense_data:  SCSI sense data.
+ */
+struct srpt_send_ioctx {
+       struct srpt_ioctx       ioctx;
+       struct srpt_rdma_ch     *ch;
+       struct kref              kref;
+       struct rdma_iu          *rdma_ius;
+       struct srp_direct_buf   *rbufs;
+       struct srp_direct_buf   single_rbuf;
+       struct scatterlist      *sg;
+       struct list_head        free_list;
+       spinlock_t              spinlock;
+       enum srpt_command_state state;
+       bool                    rdma_aborted;
+       struct se_cmd           cmd;
+       struct completion       tx_done;
+       u64                     tag;
+       int                     sg_cnt;
+       int                     mapped_sg_count;
+       u16                     n_rdma_ius;
+       u8                      n_rdma;
+       u8                      n_rbuf;
+       bool                    queue_status_only;
+       u8                      sense_data[SCSI_SENSE_BUFFERSIZE];
+};
+
+/**
+ * enum rdma_ch_state - SRP channel state.
+ * @CH_CONNECTING:      QP is in RTR state; waiting for RTU.
+ * @CH_LIVE:            QP is in RTS state.
+ * @CH_DISCONNECTING:    DREQ has been received; waiting for DREP
+ *                       or DREQ has been send and waiting for DREP
+ *                       or .
+ * @CH_DRAINING:        QP is in ERR state; waiting for last WQE event.
+ * @CH_RELEASING:       Last WQE event has been received; releasing resources.
+ */
+enum rdma_ch_state {
+       CH_CONNECTING,
+       CH_LIVE,
+       CH_DISCONNECTING,
+       CH_DRAINING,
+       CH_RELEASING
+};
+
+/**
+ * struct srpt_rdma_ch - RDMA channel.
+ * @wait_queue:    Allows the kernel thread to wait for more work.
+ * @thread:        Kernel thread that processes the IB queues associated with
+ *                 the channel.
+ * @cm_id:         IB CM ID associated with the channel.
+ * @qp:            IB queue pair used for communicating over this channel.
+ * @cq:            IB completion queue for this channel.
+ * @rq_size:       IB receive queue size.
+ * @rsp_size      IB response message size in bytes.
+ * @sq_wr_avail:   number of work requests available in the send queue.
+ * @sport:         pointer to the information of the HCA port used by this
+ *                 channel.
+ * @i_port_id:     128-bit initiator port identifier copied from SRP_LOGIN_REQ.
+ * @t_port_id:     128-bit target port identifier copied from SRP_LOGIN_REQ.
+ * @max_ti_iu_len: maximum target-to-initiator information unit length.
+ * @req_lim:       request limit: maximum number of requests that may be sent
+ *                 by the initiator without having received a response.
+ * @req_lim_delta: Number of credits not yet sent back to the initiator.
+ * @spinlock:      Protects free_list and state.
+ * @free_list:     Head of list with free send I/O contexts.
+ * @state:         channel state. See also enum rdma_ch_state.
+ * @ioctx_ring:    Send ring.
+ * @wc:            IB work completion array for srpt_process_completion().
+ * @list:          Node for insertion in the srpt_device.rch_list list.
+ * @cmd_wait_list: List of SCSI commands that arrived before the RTU event. This
+ *                 list contains struct srpt_ioctx elements and is protected
+ *                 against concurrent modification by the cm_id spinlock.
+ * @sess:          Session information associated with this SRP channel.
+ * @sess_name:     Session name.
+ * @release_work:  Allows scheduling of srpt_release_channel().
+ * @release_done:  Enables waiting for srpt_release_channel() completion.
+ */
+struct srpt_rdma_ch {
+       wait_queue_head_t       wait_queue;
+       struct task_struct      *thread;
+       struct ib_cm_id         *cm_id;
+       struct ib_qp            *qp;
+       struct ib_cq            *cq;
+       int                     rq_size;
+       u32                     rsp_size;
+       atomic_t                sq_wr_avail;
+       struct srpt_port        *sport;
+       u8                      i_port_id[16];
+       u8                      t_port_id[16];
+       int                     max_ti_iu_len;
+       atomic_t                req_lim;
+       atomic_t                req_lim_delta;
+       spinlock_t              spinlock;
+       struct list_head        free_list;
+       enum rdma_ch_state      state;
+       struct srpt_send_ioctx  **ioctx_ring;
+       struct ib_wc            wc[16];
+       struct list_head        list;
+       struct list_head        cmd_wait_list;
+       struct se_session       *sess;
+       u8                      sess_name[36];
+       struct work_struct      release_work;
+       struct completion       *release_done;
+};
+
+/**
+ * struct srpt_port_attib - Attributes for SRPT port
+ * @srp_max_rdma_size: Maximum size of SRP RDMA transfers for new connections.
+ * @srp_max_rsp_size: Maximum size of SRP response messages in bytes.
+ * @srp_sq_size: Shared receive queue (SRQ) size.
+ */
+struct srpt_port_attrib {
+       u32                     srp_max_rdma_size;
+       u32                     srp_max_rsp_size;
+       u32                     srp_sq_size;
+};
+
+/**
+ * struct srpt_port - Information associated by SRPT with a single IB port.
+ * @sdev:      backpointer to the HCA information.
+ * @mad_agent: per-port management datagram processing information.
+ * @enabled:   Whether or not this target port is enabled.
+ * @port_guid: ASCII representation of Port GUID
+ * @port:      one-based port number.
+ * @sm_lid:    cached value of the port's sm_lid.
+ * @lid:       cached value of the port's lid.
+ * @gid:       cached value of the port's gid.
+ * @port_acl_lock spinlock for port_acl_list:
+ * @work:      work structure for refreshing the aforementioned cached values.
+ * @port_tpg_1 Target portal group = 1 data.
+ * @port_wwn:  Target core WWN data.
+ * @port_acl_list: Head of the list with all node ACLs for this port.
+ */
+struct srpt_port {
+       struct srpt_device      *sdev;
+       struct ib_mad_agent     *mad_agent;
+       bool                    enabled;
+       u8                      port_guid[64];
+       u8                      port;
+       u16                     sm_lid;
+       u16                     lid;
+       union ib_gid            gid;
+       spinlock_t              port_acl_lock;
+       struct work_struct      work;
+       struct se_portal_group  port_tpg_1;
+       struct se_wwn           port_wwn;
+       struct list_head        port_acl_list;
+       struct srpt_port_attrib port_attrib;
+};
+
+/**
+ * struct srpt_device - Information associated by SRPT with a single HCA.
+ * @device:        Backpointer to the struct ib_device managed by the IB core.
+ * @pd:            IB protection domain.
+ * @mr:            L_Key (local key) with write access to all local memory.
+ * @srq:           Per-HCA SRQ (shared receive queue).
+ * @cm_id:         Connection identifier.
+ * @dev_attr:      Attributes of the InfiniBand device as obtained during the
+ *                 ib_client.add() callback.
+ * @srq_size:      SRQ size.
+ * @ioctx_ring:    Per-HCA SRQ.
+ * @rch_list:      Per-device channel list -- see also srpt_rdma_ch.list.
+ * @ch_releaseQ:   Enables waiting for removal from rch_list.
+ * @spinlock:      Protects rch_list and tpg.
+ * @port:          Information about the ports owned by this HCA.
+ * @event_handler: Per-HCA asynchronous IB event handler.
+ * @list:          Node in srpt_dev_list.
+ */
+struct srpt_device {
+       struct ib_device        *device;
+       struct ib_pd            *pd;
+       struct ib_mr            *mr;
+       struct ib_srq           *srq;
+       struct ib_cm_id         *cm_id;
+       struct ib_device_attr   dev_attr;
+       int                     srq_size;
+       struct srpt_recv_ioctx  **ioctx_ring;
+       struct list_head        rch_list;
+       wait_queue_head_t       ch_releaseQ;
+       spinlock_t              spinlock;
+       struct srpt_port        port[2];
+       struct ib_event_handler event_handler;
+       struct list_head        list;
+};
+
+/**
+ * struct srpt_node_acl - Per-initiator ACL data (managed via configfs).
+ * @i_port_id: 128-bit SRP initiator port ID.
+ * @sport:     port information.
+ * @nacl:      Target core node ACL information.
+ * @list:      Element of the per-HCA ACL list.
+ */
+struct srpt_node_acl {
+       u8                      i_port_id[16];
+       struct srpt_port        *sport;
+       struct se_node_acl      nacl;
+       struct list_head        list;
+};
+
+/*
+ * SRP-releated SCSI persistent reservation definitions.
+ *
+ * See also SPC4r28, section 7.6.1 (Protocol specific parameters introduction).
+ * See also SPC4r28, section 7.6.4.5 (TransportID for initiator ports using
+ * SCSI over an RDMA interface).
+ */
+
+enum {
+       SCSI_TRANSPORTID_PROTOCOLID_SRP = 4,
+};
+
+struct spc_rdma_transport_id {
+       uint8_t protocol_identifier;
+       uint8_t reserved[7];
+       uint8_t i_port_id[16];
+};
+
+#endif                         /* IB_SRPT_H */
index 76457d50bc3493e351c40fbe5b667d1b2e33ff6a..afc166fcc3d9c41ad6654bae17d5c893382c3705 100644 (file)
@@ -386,7 +386,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
        struct input_event event;
-       int retval;
+       int retval = 0;
 
        if (count < input_event_size())
                return -EINVAL;
index a588578037ebe7bb05481c221839a54287e6910b..67bec14e8b963de66d6ad7f5df966ff1343c0be9 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/i2c/twl.h>
 #include <linux/slab.h>
 
-
 /*
  * The TWL4030 family chips include a keypad controller that supports
  * up to an 8x8 switch matrix.  The controller can issue system wakeup
@@ -302,7 +301,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
        if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0)
                return -EIO;
 
-       /* Set timeout period to 100 ms */
+       /* Set timeout period to 200 ms */
        i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
        if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0)
                return -EIO;
@@ -466,4 +465,3 @@ MODULE_AUTHOR("Texas Instruments");
 MODULE_DESCRIPTION("TWL4030 Keypad Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:twl4030_keypad");
-
index b4cfc6c8be89db327134dd7dd722dfa2623d472a..5ec774d6c82b4be13f06c97efffe7cc42860ebab 100644 (file)
@@ -512,6 +512,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
                },
        },
+       {
+               /* Lenovo Ideapad U455 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
+               },
+       },
        { }
 };
 
index 8250299fd64ff37d78d97910a702f00710157532..4494233d331ac4689eef8ca58366c7138904627d 100644 (file)
@@ -164,7 +164,8 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
        struct serio_raw_client *client = file->private_data;
        struct serio_raw *serio_raw = client->serio_raw;
        char uninitialized_var(c);
-       ssize_t retval = 0;
+       ssize_t read = 0;
+       int retval;
 
        if (serio_raw->dead)
                return -ENODEV;
@@ -180,13 +181,15 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
        if (serio_raw->dead)
                return -ENODEV;
 
-       while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
-               if (put_user(c, buffer++))
-                       return -EFAULT;
-               retval++;
+       while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
+               if (put_user(c, buffer++)) {
+                       retval = -EFAULT;
+                       break;
+               }
+               read++;
        }
 
-       return retval;
+       return read ?: retval;
 }
 
 static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
index cce1f03b8895324d7d6e92cd6094cc39e7673cbe..f75e0608be5bb298d40443462bc31316bc8165df 100644 (file)
@@ -2863,6 +2863,9 @@ static unsigned device_dma_ops_init(void)
 
        for_each_pci_dev(pdev) {
                if (!check_device(&pdev->dev)) {
+
+                       iommu_ignore_device(&pdev->dev);
+
                        unhandled += 1;
                        continue;
                }
index 08a90b88e40d80feb9d01185e534a1351cf7473d..cee307e866060ca30aa2627eaaf3f0cb7789802e 100644 (file)
@@ -482,23 +482,19 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
 
        priv = domain->priv;
 
-       if (!priv) {
-               ret = -ENODEV;
+       if (!priv)
                goto fail;
-       }
 
        fl_table = priv->pgtable;
 
        if (len != SZ_16M && len != SZ_1M &&
            len != SZ_64K && len != SZ_4K) {
                pr_debug("Bad length: %d\n", len);
-               ret = -EINVAL;
                goto fail;
        }
 
        if (!fl_table) {
                pr_debug("Null page table\n");
-               ret = -EINVAL;
                goto fail;
        }
 
@@ -507,7 +503,6 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
 
        if (*fl_pte == 0) {
                pr_debug("First level PTE is 0\n");
-               ret = -ENODEV;
                goto fail;
        }
 
index 2339d7396b9ea305dd845e592d227bd726d3d43b..802ab87a78b662052bd2115f1d9bf4fc9ed5ae47 100644 (file)
@@ -1901,7 +1901,7 @@ static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
 {
        isdn_net_local *lp = netdev_priv(dev);
        unsigned char *p;
-       ushort len = 0;
+       int len = 0;
 
        switch (lp->p_encap) {
                case ISDN_NET_ENCAP_ETHER:
index c957c344233f4ed283df710222492f1ee38d9bf0..9ca28fced2b9d4d17facfbe03922a8079d831615 100644 (file)
@@ -403,6 +403,13 @@ config LEDS_MAX8997
          This option enables support for on-chip LED drivers on
          MAXIM MAX8997 PMIC.
 
+config LEDS_OT200
+       tristate "LED support for the Bachmann OT200"
+       depends on LEDS_CLASS && HAS_IOMEM
+       help
+         This option enables support for the LEDs on the Bachmann OT200.
+         Say Y to enable LEDs on the Bachmann OT200.
+
 config LEDS_TRIGGERS
        bool "LED Trigger support"
        depends on LEDS_CLASS
index b8a9723477f0819b2fb07e2c19a61847888945e6..1fc6875a8b201d02a1d59122548948955829de1d 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_LEDS_LP5523)             += leds-lp5523.o
 obj-$(CONFIG_LEDS_TCA6507)             += leds-tca6507.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
+obj-$(CONFIG_LEDS_OT200)               += leds-ot200.o
 obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
 obj-$(CONFIG_LEDS_PCA955X)             += leds-pca955x.o
 obj-$(CONFIG_LEDS_DA903X)              += leds-da903x.o
index 45e6878d73741d8359db2069b68bbe1df2589f2e..e59c166a0ce2261dd2515930ff297c1b57b5d25a 100644 (file)
@@ -164,8 +164,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
 
        if (drvdata->mode == LM3530_BL_MODE_ALS) {
                if (pltfm->als_vmax == 0) {
-                       pltfm->als_vmin = als_vmin = 0;
-                       pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV;
+                       pltfm->als_vmin = 0;
+                       pltfm->als_vmax = LM3530_ALS_WINDOW_mV;
                }
 
                als_vmin = pltfm->als_vmin;
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
new file mode 100644 (file)
index 0000000..c464682
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Bachmann ot200 leds driver.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *         Christian Gmeiner <christian.gmeiner@gmail.com>
+ *
+ * License: GPL as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+
+struct ot200_led {
+       struct led_classdev cdev;
+       const char *name;
+       unsigned long port;
+       u8 mask;
+};
+
+/*
+ * The device has three leds on the back panel (led_err, led_init and led_run)
+ * and can handle up to seven leds on the front panel.
+ */
+
+static struct ot200_led leds[] = {
+       {
+               .name = "led_run",
+               .port = 0x5a,
+               .mask = BIT(0),
+       },
+       {
+               .name = "led_init",
+               .port = 0x5a,
+               .mask = BIT(1),
+       },
+       {
+               .name = "led_err",
+               .port = 0x5a,
+               .mask = BIT(2),
+       },
+       {
+               .name = "led_1",
+               .port = 0x49,
+               .mask = BIT(7),
+       },
+       {
+               .name = "led_2",
+               .port = 0x49,
+               .mask = BIT(6),
+       },
+       {
+               .name = "led_3",
+               .port = 0x49,
+               .mask = BIT(5),
+       },
+       {
+               .name = "led_4",
+               .port = 0x49,
+               .mask = BIT(4),
+       },
+       {
+               .name = "led_5",
+               .port = 0x49,
+               .mask = BIT(3),
+       },
+       {
+               .name = "led_6",
+               .port = 0x49,
+               .mask = BIT(2),
+       },
+       {
+               .name = "led_7",
+               .port = 0x49,
+               .mask = BIT(1),
+       }
+};
+
+static DEFINE_SPINLOCK(value_lock);
+
+/*
+ * we need to store the current led states, as it is not
+ * possible to read the current led state via inb().
+ */
+static u8 leds_back;
+static u8 leds_front;
+
+static void ot200_led_brightness_set(struct led_classdev *led_cdev,
+               enum led_brightness value)
+{
+       struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev);
+       u8 *val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&value_lock, flags);
+
+       if (led->port == 0x49)
+               val = &leds_front;
+       else if (led->port == 0x5a)
+               val = &leds_back;
+       else
+               BUG();
+
+       if (value == LED_OFF)
+               *val &= ~led->mask;
+       else
+               *val |= led->mask;
+
+       outb(*val, led->port);
+       spin_unlock_irqrestore(&value_lock, flags);
+}
+
+static int __devinit ot200_led_probe(struct platform_device *pdev)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < ARRAY_SIZE(leds); i++) {
+
+               leds[i].cdev.name = leds[i].name;
+               leds[i].cdev.brightness_set = ot200_led_brightness_set;
+
+               ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
+               if (ret < 0)
+                       goto err;
+       }
+
+       leds_front = 0;         /* turn off all front leds */
+       leds_back = BIT(1);     /* turn on init led */
+       outb(leds_front, 0x49);
+       outb(leds_back, 0x5a);
+
+       return 0;
+
+err:
+       for (i = i - 1; i >= 0; i--)
+               led_classdev_unregister(&leds[i].cdev);
+
+       return ret;
+}
+
+static int __devexit ot200_led_remove(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(leds); i++)
+               led_classdev_unregister(&leds[i].cdev);
+
+       return 0;
+}
+
+static struct platform_driver ot200_led_driver = {
+       .probe          = ot200_led_probe,
+       .remove         = __devexit_p(ot200_led_remove),
+       .driver         = {
+               .name   = "leds-ot200",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(ot200_led_driver);
+
+MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("ot200 LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-ot200");
index 75049e765191eb6a75ec44b1670304785cba3a9e..b026896206ca4fb1ee66df1df93036dcc7b72f9b 100644 (file)
@@ -710,7 +710,7 @@ static ssize_t adb_read(struct file *file, char __user *buf,
        req = NULL;
        spin_lock_irqsave(&state->lock, flags);
        add_wait_queue(&state->wait_queue, &wait);
-       current->state = TASK_INTERRUPTIBLE;
+       set_current_state(TASK_INTERRUPTIBLE);
 
        for (;;) {
                req = state->completed;
@@ -734,7 +734,7 @@ static ssize_t adb_read(struct file *file, char __user *buf,
                spin_lock_irqsave(&state->lock, flags);
        }
 
-       current->state = TASK_RUNNING;
+       set_current_state(TASK_RUNNING);
        remove_wait_queue(&state->wait_queue, &wait);
        spin_unlock_irqrestore(&state->lock, flags);
        
index c2907d836e4e563ba50834e2524ae91919ddbd81..86cb7e5d83d545f1cca9706e689665780148c5db 100644 (file)
@@ -56,7 +56,8 @@ struct raid_dev {
 struct raid_set {
        struct dm_target *ti;
 
-       uint64_t print_flags;
+       uint32_t bitmap_loaded;
+       uint32_t print_flags;
 
        struct mddev md;
        struct raid_type *raid_type;
@@ -1085,7 +1086,7 @@ static int raid_status(struct dm_target *ti, status_type_t type,
                                raid_param_cnt += 2;
                }
 
-               raid_param_cnt += (hweight64(rs->print_flags & ~DMPF_REBUILD) * 2);
+               raid_param_cnt += (hweight32(rs->print_flags & ~DMPF_REBUILD) * 2);
                if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC))
                        raid_param_cnt--;
 
@@ -1197,7 +1198,12 @@ static void raid_resume(struct dm_target *ti)
 {
        struct raid_set *rs = ti->private;
 
-       bitmap_load(&rs->md);
+       if (!rs->bitmap_loaded) {
+               bitmap_load(&rs->md);
+               rs->bitmap_loaded = 1;
+       } else
+               md_wakeup_thread(rs->md.thread);
+
        mddev_resume(&rs->md);
 }
 
index 9417ae2fa0bbc68b061d6b50ba23f5127dae5b2c..ce88755baf4a91a6216b628117e84a697c21d3c8 100644 (file)
@@ -7333,7 +7333,8 @@ void md_do_sync(struct mddev *mddev)
                                        printk(KERN_INFO
                                               "md: checkpointing %s of %s.\n",
                                               desc, mdname(mddev));
-                                       mddev->recovery_cp = mddev->curr_resync;
+                                       mddev->recovery_cp =
+                                               mddev->curr_resync_completed;
                                }
                        } else
                                mddev->recovery_cp = MaxSector;
@@ -7351,9 +7352,9 @@ void md_do_sync(struct mddev *mddev)
                        rcu_read_unlock();
                }
        }
+ skip:
        set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
- skip:
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
                /* We completed so min/max setting can be forgotten if used. */
                if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
index 27555995f7e4c344f74afdfa14824ecbfac2b912..b5ee3ebfcfca03e2f9fd5973cd5d72b52d1c5f53 100644 (file)
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
+/* Registers (Write-only) */
+#define XREG_INIT         0x00
+#define XREG_RF_FREQ      0x02
+#define XREG_POWER_DOWN   0x08
+
+/* Registers (Read-only) */
+#define XREG_FREQ_ERROR   0x01
+#define XREG_LOCK         0x02
+#define XREG_VERSION      0x04
+#define XREG_PRODUCT_ID   0x08
+#define XREG_HSYNC_FREQ   0x10
+#define XREG_FRAME_LINES  0x20
+#define XREG_SNR          0x40
+
+#define XREG_ADC_ENV      0x0100
 
 static int debug;
 module_param(debug, int, 0644);
@@ -885,7 +900,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
        mutex_lock(&priv->lock);
 
        /* Sync Lock Indicator */
-       rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
+       rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
        if (rc < 0)
                goto ret;
 
@@ -894,7 +909,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
                signal = 1 << 11;
 
        /* Get SNR of the video signal */
-       rc = xc2028_get_reg(priv, 0x0040, &signal);
+       rc = xc2028_get_reg(priv, XREG_SNR, &signal);
        if (rc < 0)
                goto ret;
 
@@ -1019,9 +1034,9 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
 
        /* CMD= Set frequency */
        if (priv->firm_version < 0x0202)
-               rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+               rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00});
        else
-               rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
+               rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00});
        if (rc < 0)
                goto ret;
 
@@ -1201,9 +1216,9 @@ static int xc2028_sleep(struct dvb_frontend *fe)
        mutex_lock(&priv->lock);
 
        if (priv->firm_version < 0x0202)
-               rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
+               rc = send_seq(priv, {0x00, XREG_POWER_DOWN, 0x00, 0x00});
        else
-               rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
+               rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
 
        priv->cur_fw.type = 0;  /* need firmware reload */
 
index d218c1d68c33a622cdc791aa684e5645441965bf..68397110b7d932fec46c3cdd4ecc0b9d2e99ddf4 100644 (file)
@@ -154,6 +154,8 @@ struct xc4000_priv {
 #define XREG_SNR          0x06
 #define XREG_VERSION      0x07
 #define XREG_PRODUCT_ID   0x08
+#define XREG_SIGNAL_LEVEL 0x0A
+#define XREG_NOISE_LEVEL  0x0B
 
 /*
    Basic firmware description. This will remain with
@@ -486,6 +488,16 @@ static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
        return xc4000_readreg(priv, XREG_QUALITY, quality);
 }
 
+static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
+{
+       return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
+}
+
+static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
+{
+       return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
+}
+
 static u16 xc_wait_for_lock(struct xc4000_priv *priv)
 {
        u16     lock_state = 0;
@@ -1089,6 +1101,8 @@ static void xc_debug_dump(struct xc4000_priv *priv)
        u32     hsync_freq_hz = 0;
        u16     frame_lines;
        u16     quality;
+       u16     signal = 0;
+       u16     noise = 0;
        u8      hw_majorversion = 0, hw_minorversion = 0;
        u8      fw_majorversion = 0, fw_minorversion = 0;
 
@@ -1119,6 +1133,12 @@ static void xc_debug_dump(struct xc4000_priv *priv)
 
        xc_get_quality(priv, &quality);
        dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+
+       xc_get_signal_level(priv, &signal);
+       dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
+
+       xc_get_noise_level(priv, &noise);
+       dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
 }
 
 static int xc4000_set_params(struct dvb_frontend *fe)
@@ -1432,6 +1452,71 @@ fail:
        return ret;
 }
 
+static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
+{
+       struct xc4000_priv *priv = fe->tuner_priv;
+       u16 value = 0;
+       int rc;
+
+       mutex_lock(&priv->lock);
+       rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
+       mutex_unlock(&priv->lock);
+
+       if (rc < 0)
+               goto ret;
+
+       /* Informations from real testing of DVB-T and radio part,
+          coeficient for one dB is 0xff.
+        */
+       tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
+
+       /* all known digital modes */
+       if ((priv->video_standard == XC4000_DTV6) ||
+           (priv->video_standard == XC4000_DTV7) ||
+           (priv->video_standard == XC4000_DTV7_8) ||
+           (priv->video_standard == XC4000_DTV8))
+               goto digital;
+
+       /* Analog mode has NOISE LEVEL important, signal
+          depends only on gain of antenna and amplifiers,
+          but it doesn't tell anything about real quality
+          of reception.
+        */
+       mutex_lock(&priv->lock);
+       rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
+       mutex_unlock(&priv->lock);
+
+       tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
+
+       /* highest noise level: 32dB */
+       if (value >= 0x2000) {
+               value = 0;
+       } else {
+               value = ~value << 3;
+       }
+
+       goto ret;
+
+       /* Digital mode has SIGNAL LEVEL important and real
+          noise level is stored in demodulator registers.
+        */
+digital:
+       /* best signal: -50dB */
+       if (value <= 0x3200) {
+               value = 0xffff;
+       /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
+       } else if (value >= 0x713A) {
+               value = 0;
+       } else {
+               value = ~(value - 0x3200) << 2;
+       }
+
+ret:
+       *strength = value;
+
+       return rc;
+}
+
 static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 {
        struct xc4000_priv *priv = fe->tuner_priv;
@@ -1559,6 +1644,7 @@ static const struct dvb_tuner_ops xc4000_tuner_ops = {
        .set_params        = xc4000_set_params,
        .set_analog_params = xc4000_set_analog_params,
        .get_frequency     = xc4000_get_frequency,
+       .get_rf_strength   = xc4000_get_signal,
        .get_bandwidth     = xc4000_get_bandwidth,
        .get_status        = xc4000_get_status
 };
index b15db4fe347b9218ec8b9e348802f424abb5d72b..fbbe545a74cb5357c3c1cdf445511c80f32dd724 100644 (file)
@@ -904,8 +904,11 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int i;
+       u32 delsys;
 
+       delsys = c->delivery_system;
        memset(c, 0, sizeof(struct dtv_frontend_properties));
+       c->delivery_system = delsys;
 
        c->state = DTV_CLEAR;
 
@@ -1009,25 +1012,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
        _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
 
-       _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0),
-       _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0),
-       _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0),
-
        _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
        _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
 
@@ -1413,6 +1397,15 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        enum dvbv3_emulation_type type;
 
+       /*
+        * It was reported that some old DVBv5 applications were
+        * filling delivery_system with SYS_UNDEFINED. If this happens,
+        * assume that the application wants to use the first supported
+        * delivery system.
+        */
+       if (c->delivery_system == SYS_UNDEFINED)
+               c->delivery_system = fe->ops.delsys[0];
+
        if (desired_system == SYS_UNDEFINED) {
                /*
                 * A DVBv3 call doesn't know what's the desired system.
@@ -1732,6 +1725,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int err = 0;
 
@@ -1798,9 +1792,14 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 
                /*
                 * Fills the cache out struct with the cache contents, plus
-                * the data retrieved from get_frontend.
+                * the data retrieved from get_frontend, if the frontend
+                * is not idle. Otherwise, returns the cached content
                 */
-               dtv_get_frontend(fe, NULL);
+               if (fepriv->state != FESTATE_IDLE) {
+                       err = dtv_get_frontend(fe, NULL);
+                       if (err < 0)
+                               goto out;
+               }
                for (i = 0; i < tvps->num; i++) {
                        err = dtv_property_process_get(fe, c, tvp + i, file);
                        if (err < 0)
index d66192974d68a0a2de44fd41f156f7b6c9c90a85..cf0c318d6989e11eda05286c7dd209e8e41fc673 100644 (file)
@@ -877,24 +877,17 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
        case ANYSEE_HW_508T2C: /* 20 */
                /* E7 T2C */
 
+               if (state->fe_id)
+                       break;
+
                /* enable DVB-T/T2/C demod on IOE[5] */
                ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
                if (ret)
                        goto error;
 
-               if (state->fe_id == 0)  {
-                       /* DVB-T/T2 */
-                       adap->fe_adap[state->fe_id].fe =
-                               dvb_attach(cxd2820r_attach,
-                               &anysee_cxd2820r_config,
-                               &adap->dev->i2c_adap, NULL);
-               } else {
-                       /* DVB-C */
-                       adap->fe_adap[state->fe_id].fe =
-                               dvb_attach(cxd2820r_attach,
-                               &anysee_cxd2820r_config,
-                               &adap->dev->i2c_adap, adap->fe_adap[0].fe);
-               }
+               /* attach demod */
+               adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
+                               &anysee_cxd2820r_config, &adap->dev->i2c_adap);
 
                state->has_ci = true;
 
@@ -1195,6 +1188,14 @@ static int anysee_ci_init(struct dvb_usb_device *d)
        if (ret)
                return ret;
 
+       ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 2)|(0 << 1)|(0 << 0), 0x07);
+       if (ret)
+               return ret;
+
+       ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 2)|(1 << 1)|(1 << 0), 0x07);
+       if (ret)
+               return ret;
+
        ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
        if (ret)
                return ret;
index 8a57ed8272dec10adfbbd989f81442ed6cc48ef9..1efc028a76c9c5bb937f6c8979d672ec68104596 100644 (file)
@@ -276,14 +276,15 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
        param.flags = 0;
 
        switch (fep->bandwidth_hz) {
+       default:
        case 8000000:
-               param.bandwidth = 0;
+               param.bandwidth = 8;
                break;
        case 7000000:
-               param.bandwidth = 1;
+               param.bandwidth = 7;
                break;
        case 6000000:
-               param.bandwidth = 2;
+               param.bandwidth = 6;
                break;
        }
 
index 9bd6d51b3b938b21659dffe90f7ee68877ad6302..7de125c0b36f4576f951ea8e90a87d7c308f0857 100644 (file)
@@ -48,6 +48,8 @@ struct dib0700_state {
        u8 disable_streaming_master_mode;
        u32 fw_version;
        u32 nb_packet_buffer_size;
+       int (*read_status)(struct dvb_frontend *, fe_status_t *);
+       int (*sleep)(struct dvb_frontend* fe);
        u8 buf[255];
 };
 
index 206999476f028238c430797ba11b762b55dee379..070e82aa53f53248f33448d9e61d22b484e6b28a 100644 (file)
@@ -834,6 +834,7 @@ static struct usb_driver dib0700_driver = {
 
 module_usb_driver(dib0700_driver);
 
+MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw");
 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
 MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
 MODULE_VERSION("1.0");
index 81ef4b46f790f936129b849e55878e8b8a9ff89e..f9e966aa26e75d19b0ce129221be038bd6787fe5 100644 (file)
@@ -3066,19 +3066,25 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
        }
 };
 
-static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+static void stk7070pd_init(struct dvb_usb_device *dev)
 {
-       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO6, GPIO_OUT, 1);
        msleep(10);
-       dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-       dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-       dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       dib0700_set_gpio(dev, GPIO9, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO4, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO7, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 0);
 
-       dib0700_ctrl_clock(adap->dev, 72, 1);
+       dib0700_ctrl_clock(dev, 72, 1);
 
        msleep(10);
-       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 1);
+}
+
+static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+{
+       stk7070pd_init(adap->dev);
+
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
@@ -3099,6 +3105,77 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
        return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
+static int novatd_read_status_override(struct dvb_frontend *fe,
+               fe_status_t *stat)
+{
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dvb_usb_device *dev = adap->dev;
+       struct dib0700_state *state = dev->priv;
+       int ret;
+
+       ret = state->read_status(fe, stat);
+
+       if (!ret)
+               dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT,
+                               !!(*stat & FE_HAS_LOCK));
+
+       return ret;
+}
+
+static int novatd_sleep_override(struct dvb_frontend* fe)
+{
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dvb_usb_device *dev = adap->dev;
+       struct dib0700_state *state = dev->priv;
+
+       /* turn off LED */
+       dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, 0);
+
+       return state->sleep(fe);
+}
+
+/**
+ * novatd_frontend_attach - Nova-TD specific attach
+ *
+ * Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for
+ * information purposes.
+ */
+static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *dev = adap->dev;
+       struct dib0700_state *st = dev->priv;
+
+       if (adap->id == 0) {
+               stk7070pd_init(dev);
+
+               /* turn the power LED on, the other two off (just in case) */
+               dib0700_set_gpio(dev, GPIO0, GPIO_OUT, 0);
+               dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
+               dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
+
+               if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
+                                            stk7070pd_dib7000p_config) != 0) {
+                       err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+                           __func__);
+                       return -ENODEV;
+               }
+       }
+
+       adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
+                       adap->id == 0 ? 0x80 : 0x82,
+                       &stk7070pd_dib7000p_config[adap->id]);
+
+       if (adap->fe_adap[0].fe == NULL)
+               return -ENODEV;
+
+       st->read_status = adap->fe_adap[0].fe->ops.read_status;
+       adap->fe_adap[0].fe->ops.read_status = novatd_read_status_override;
+       st->sleep = adap->fe_adap[0].fe->ops.sleep;
+       adap->fe_adap[0].fe->ops.sleep = novatd_sleep_override;
+
+       return 0;
+}
+
 /* S5H1411 */
 static struct s5h1411_config pinnacle_801e_config = {
        .output_mode   = S5H1411_PARALLEL_OUTPUT,
@@ -3861,6 +3938,57 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
+               .num_adapters = 2,
+               .adapter = {
+                       {
+                       .num_frontends = 1,
+                       .fe = {{
+                               .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                               .pid_filter_count = 32,
+                               .pid_filter       = stk70x0p_pid_filter,
+                               .pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+                               .frontend_attach  = novatd_frontend_attach,
+                               .tuner_attach     = dib7070p_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+                       }},
+                               .size_of_priv     = sizeof(struct dib0700_adapter_state),
+                       }, {
+                       .num_frontends = 1,
+                       .fe = {{
+                               .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                               .pid_filter_count = 32,
+                               .pid_filter       = stk70x0p_pid_filter,
+                               .pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+                               .frontend_attach  = novatd_frontend_attach,
+                               .tuner_attach     = dib7070p_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+                       }},
+                               .size_of_priv     = sizeof(struct dib0700_adapter_state),
+                       }
+               },
+
+               .num_device_descs = 1,
+               .devices = {
+                       {   "Hauppauge Nova-TD Stick (52009)",
+                               { &dib0700_usb_id_table[35], NULL },
+                               { NULL },
+                       },
+               },
+
+               .rc.core = {
+                       .rc_interval      = DEFAULT_RC_INTERVAL,
+                       .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+                       .module_name      = "dib0700",
+                       .rc_query         = dib0700_rc_query_old_firmware,
+                       .allowed_protos   = RC_TYPE_RC5 |
+                                           RC_TYPE_RC6 |
+                                           RC_TYPE_NEC,
+                       .change_protocol = dib0700_change_protocol,
+               },
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
                .num_adapters = 2,
                .adapter = {
                        {
@@ -3892,7 +4020,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        }
                },
 
-               .num_device_descs = 6,
+               .num_device_descs = 5,
                .devices = {
                        {   "DiBcom STK7070PD reference design",
                                { &dib0700_usb_id_table[17], NULL },
@@ -3902,10 +4030,6 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[18], NULL },
                                { NULL },
                        },
-                       {   "Hauppauge Nova-TD Stick (52009)",
-                               { &dib0700_usb_id_table[35], NULL },
-                               { NULL },
-                       },
                        {   "Hauppauge Nova-TD-500 (84xxx)",
                                { &dib0700_usb_id_table[36], NULL },
                                { NULL },
index cf0f546aa1d1bdf94f47666692c0313cf69d6643..5aa306ebb7ef93bd8f356e6bc98325735c88503c 100644 (file)
@@ -77,14 +77,12 @@ struct cxd2820r_config {
        (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
 extern struct dvb_frontend *cxd2820r_attach(
        const struct cxd2820r_config *config,
-       struct i2c_adapter *i2c,
-       struct dvb_frontend *fe
+       struct i2c_adapter *i2c
 );
 #else
 static inline struct dvb_frontend *cxd2820r_attach(
        const struct cxd2820r_config *config,
-       struct i2c_adapter *i2c,
-       struct dvb_frontend *fe
+       struct i2c_adapter *i2c
 )
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
index 93e1b12e79077ddc851ffd5fd85c8240c795eed7..5c7c2aaf9bf58583eb52ed6f3ba7b4d48df6d29b 100644 (file)
@@ -309,9 +309,14 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
 static int cxd2820r_get_frontend(struct dvb_frontend *fe)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
        dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+       if (priv->delivery_system == SYS_UNDEFINED)
+               return 0;
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_get_frontend_t(fe);
@@ -476,11 +481,20 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
        dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
 
        /* switch between DVB-T and DVB-T2 when tune fails */
-       if (priv->last_tune_failed && (priv->delivery_system != SYS_DVBC_ANNEX_A)) {
-               if (priv->delivery_system == SYS_DVBT)
+       if (priv->last_tune_failed) {
+               if (priv->delivery_system == SYS_DVBT) {
+                       ret = cxd2820r_sleep_t(fe);
+                       if (ret)
+                               goto error;
+
                        c->delivery_system = SYS_DVBT2;
-               else
+               } else if (priv->delivery_system == SYS_DVBT2) {
+                       ret = cxd2820r_sleep_t2(fe);
+                       if (ret)
+                               goto error;
+
                        c->delivery_system = SYS_DVBT;
+               }
        }
 
        /* set frontend */
@@ -492,6 +506,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
        /* frontend lock wait loop count */
        switch (priv->delivery_system) {
        case SYS_DVBT:
+       case SYS_DVBC_ANNEX_A:
                i = 20;
                break;
        case SYS_DVBT2:
@@ -556,7 +571,7 @@ static const struct dvb_frontend_ops cxd2820r_ops = {
        .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
        /* default: DVB-T/T2 */
        .info = {
-               .name = "Sony CXD2820R (DVB-T/T2)",
+               .name = "Sony CXD2820R",
 
                .caps = FE_CAN_FEC_1_2                  |
                        FE_CAN_FEC_2_3                  |
@@ -566,7 +581,9 @@ static const struct dvb_frontend_ops cxd2820r_ops = {
                        FE_CAN_FEC_AUTO                 |
                        FE_CAN_QPSK                     |
                        FE_CAN_QAM_16                   |
+                       FE_CAN_QAM_32                   |
                        FE_CAN_QAM_64                   |
+                       FE_CAN_QAM_128                  |
                        FE_CAN_QAM_256                  |
                        FE_CAN_QAM_AUTO                 |
                        FE_CAN_TRANSMISSION_MODE_AUTO   |
@@ -596,8 +613,7 @@ static const struct dvb_frontend_ops cxd2820r_ops = {
 };
 
 struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
-                                    struct i2c_adapter *i2c,
-                                    struct dvb_frontend *fe)
+               struct i2c_adapter *i2c)
 {
        struct cxd2820r_priv *priv = NULL;
        int ret;
index 938777065de6d1d14effed1ab4f9a01b3f7dc8c7..af65d013db11e8ed843c555fe0dc73d114103729 100644 (file)
@@ -1195,7 +1195,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe)
 
        for (i = 0; i < 30 ; i++) {
                ds3000_read_status(fe, &status);
-               if (status && FE_HAS_LOCK)
+               if (status & FE_HAS_LOCK)
                        break;
 
                msleep(10);
index 7fa3e472cdcaf40e0af6d97a4515a6b383dea0dd..fade566927c3ee93d65cba68a14309c798051d7b 100644 (file)
@@ -402,7 +402,7 @@ static int mb86a20s_get_modulation(struct mb86a20s_state *state,
                [2] = 0x8e,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
@@ -435,7 +435,7 @@ static int mb86a20s_get_fec(struct mb86a20s_state *state,
                [2] = 0x8f,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
@@ -470,7 +470,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
                [2] = 0x90,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
@@ -494,7 +494,7 @@ static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
                [2] = 0x91,     /* Layer C */
        };
 
-       if (layer > ARRAY_SIZE(reg))
+       if (layer >= ARRAY_SIZE(reg))
                return -EINVAL;
        rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
        if (rc < 0)
index 86da3d816498e320772a3a094702d9699b894e19..ad7c72e8f517728539f93adde89f63ddf980d137 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
index ec859a580651e327475f0ce57f7faba7f5a1d26b..f241702a0f36442aa7e3ab1c8d9fe55213e00d78 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 #include <media/as3645a.h>
 #include <media/v4l2-ctrls.h>
index 9fe4519176a4850ceecda1d29fb961eeb7b03fb2..ec3f6a06f9c3baf5f92e09abbb4e2bcef54196bd 100644 (file)
@@ -922,7 +922,9 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev)
                        isi->fb_descriptors_phys);
 
        iounmap(isi->regs);
+       clk_unprepare(isi->mck);
        clk_put(isi->mck);
+       clk_unprepare(isi->pclk);
        clk_put(isi->pclk);
        kfree(isi);
 
@@ -955,6 +957,10 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
        if (IS_ERR(pclk))
                return PTR_ERR(pclk);
 
+       ret = clk_prepare(pclk);
+       if (ret)
+               goto err_clk_prepare_pclk;
+
        isi = kzalloc(sizeof(struct atmel_isi), GFP_KERNEL);
        if (!isi) {
                ret = -ENOMEM;
@@ -978,6 +984,10 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
                goto err_clk_get;
        }
 
+       ret = clk_prepare(isi->mck);
+       if (ret)
+               goto err_clk_prepare_mck;
+
        /* Set ISI_MCK's frequency, it should be faster than pixel clock */
        ret = clk_set_rate(isi->mck, pdata->mck_hz);
        if (ret < 0)
@@ -1059,10 +1069,14 @@ err_alloc_ctx:
                        isi->fb_descriptors_phys);
 err_alloc_descriptors:
 err_set_mck_rate:
+       clk_unprepare(isi->mck);
+err_clk_prepare_mck:
        clk_put(isi->mck);
 err_clk_get:
        kfree(isi);
 err_alloc_isi:
+       clk_unprepare(pclk);
+err_clk_prepare_pclk:
        clk_put(pclk);
 
        return ret;
index 14cb961c22bdba5ef506ba56ad55e59d2dc1ade5..4bfd865a4106069538b893720622e424b0097915 100644 (file)
@@ -751,20 +751,10 @@ int cx18_v4l2_close(struct file *filp)
 
        CX18_DEBUG_IOCTL("close() of %s\n", s->name);
 
-       v4l2_fh_del(fh);
-       v4l2_fh_exit(fh);
-
-       /* Easy case first: this stream was never claimed by us */
-       if (s->id != id->open_id) {
-               kfree(id);
-               return 0;
-       }
-
-       /* 'Unclaim' this stream */
-
-       /* Stop radio */
        mutex_lock(&cx->serialize_lock);
-       if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
+       /* Stop radio */
+       if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                /* Closing radio device, return to TV mode */
                cx18_mute(cx);
                /* Mark that the radio is no longer in use */
@@ -781,10 +771,14 @@ int cx18_v4l2_close(struct file *filp)
                }
                /* Done! Unmute and continue. */
                cx18_unmute(cx);
-               cx18_release_stream(s);
-       } else {
-               cx18_stop_capture(id, 0);
        }
+
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
+
+       /* 'Unclaim' this stream */
+       if (s->id == id->open_id)
+               cx18_stop_capture(id, 0);
        kfree(id);
        mutex_unlock(&cx->serialize_lock);
        return 0;
@@ -810,21 +804,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
 
        item->open_id = cx->open_id++;
        filp->private_data = &item->fh;
+       v4l2_fh_add(&item->fh);
 
-       if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
-               /* Try to claim this stream */
-               if (cx18_claim_stream(item, item->type)) {
-                       /* No, it's already in use */
-                       v4l2_fh_exit(&item->fh);
-                       kfree(item);
-                       return -EBUSY;
-               }
-
+       if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
                        if (atomic_read(&cx->ana_capturing) > 0) {
                                /* switching to radio while capture is
                                   in progress is not polite */
-                               cx18_release_stream(s);
+                               v4l2_fh_del(&item->fh);
                                v4l2_fh_exit(&item->fh);
                                kfree(item);
                                return -EBUSY;
@@ -842,7 +830,6 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
                /* Done! Unmute and continue. */
                cx18_unmute(cx);
        }
-       v4l2_fh_add(&item->fh);
        return 0;
 }
 
index 919ed77b32f2dec7fc6e6b195a9722c6f77f6fbb..875a7ce947361ffb720ced4e811dd909cb03b15b 100644 (file)
@@ -1052,7 +1052,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                cx231xx_err(DRIVER_NAME ": out of memory!\n");
-               clear_bit(dev->devno, &cx231xx_devused);
+               clear_bit(nr, &cx231xx_devused);
                return -ENOMEM;
        }
 
index 3c01be999e353817718ab342c27943fc1a52d78f..19b5499d2624cc9b130e8340062222fd12a465e3 100644 (file)
@@ -213,8 +213,8 @@ struct cx23885_board cx23885_boards[] = {
                .portc          = CX23885_MPEG_DVB,
                .tuner_type     = TUNER_XC4000,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC4000,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = {{
                        .type   = CX23885_VMUX_TELEVISION,
                        .vmux   = CX25840_VIN2_CH1 |
index af8a225763d3dbfc3a41068855625a83bf13d4cd..6835eb1fc09319cb52c006f6af6e299f7fc76833 100644 (file)
@@ -943,6 +943,11 @@ static int dvb_register(struct cx23885_tsport *port)
 
                        fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
                                        &dev->i2c_bus[1].i2c_adap, &cfg);
+                       if (!fe) {
+                               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+                                      dev->name);
+                               goto frontend_detach;
+                       }
                }
                break;
        case CX23885_BOARD_TBS_6920:
index 4bbf9bb97bde984e23c0665fda59a72bc7dbd80a..c654bdc7ccb201dd4e285c0b7ddfe703ab89cb61 100644 (file)
@@ -1550,7 +1550,6 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
        struct v4l2_control ctrl;
        struct videobuf_dvb_frontend *vfe;
        struct dvb_frontend *fe;
-       int err = 0;
 
        struct analog_parameters params = {
                .mode      = V4L2_TUNER_ANALOG_TV,
@@ -1572,8 +1571,10 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
                params.frequency, f->tuner, params.std);
 
        vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
-       if (!vfe)
-               err = -EINVAL;
+       if (!vfe) {
+               mutex_unlock(&dev->lock);
+               return -EINVAL;
+       }
 
        fe = vfe->dvb.frontend;
 
index 62c7ad050f9bb0b067a963405ddda6e8cbcd1838..cbd5d119a2c660ebd7f8e9aba9b4206795d290e9 100644 (file)
@@ -1573,8 +1573,8 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Pinnacle Hybrid PCTV",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC2028,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
@@ -1611,8 +1611,8 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Leadtek TV2000 XP Global",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC2028,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
@@ -2115,8 +2115,8 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Terratec Cinergy HT PCI MKII",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
-               .radio_type     = TUNER_XC2028,
-               .radio_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
@@ -2154,9 +2154,9 @@ static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_WINFAST_DTV1800H] = {
                .name           = "Leadtek WinFast DTV1800 Hybrid",
                .tuner_type     = TUNER_XC2028,
-               .radio_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
                .tuner_addr     = 0x61,
-               .radio_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
                /*
                 * GPIO setting
                 *
@@ -2195,9 +2195,9 @@ static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
                .name           = "Leadtek WinFast DTV1800 H (XC4000)",
                .tuner_type     = TUNER_XC4000,
-               .radio_type     = TUNER_XC4000,
+               .radio_type     = UNSET,
                .tuner_addr     = 0x61,
-               .radio_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
                /*
                 * GPIO setting
                 *
@@ -2236,9 +2236,9 @@ static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
                .name           = "Leadtek WinFast DTV2000 H PLUS",
                .tuner_type     = TUNER_XC4000,
-               .radio_type     = TUNER_XC4000,
+               .radio_type     = UNSET,
                .tuner_addr     = 0x61,
-               .radio_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
                /*
                 * GPIO
                 *   2: 1: mute audio
index 9449423098e0d4163eabe8d7a0b0c57cdb484cc2..aabbf4854f6629d9d1c14939642bb2879b7df70f 100644 (file)
@@ -853,8 +853,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
        case EM28174_BOARD_PCTV_290E:
                dvb->fe[0] = dvb_attach(cxd2820r_attach,
                                        &em28xx_cxd2820r_config,
-                                       &dev->i2c_adap,
-                                       NULL);
+                                       &dev->i2c_adap);
                if (dvb->fe[0]) {
                        /* FE 0 attach tuner */
                        if (!dvb_attach(tda18271_attach,
index 544af91cbdc1b0fb9962d6550cb9c4892299a74b..3949b7dc2368370ebe6d28f15b3b83bc2999babe 100644 (file)
@@ -731,9 +731,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
 
        init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
 
-       /* start counting open_id at 1 */
-       itv->open_id = 1;
-
        /* Initial settings */
        itv->cxhdl.port = CX2341X_PORT_MEMORY;
        itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
index 8f9cc17b518eaaf6320e092d0a667d8d4876e586..06f3d78389bfbb250f89d655a9d6e57ebe359d24 100644 (file)
@@ -332,7 +332,7 @@ struct ivtv_stream {
        const char *name;               /* name of the stream */
        int type;                       /* stream type */
 
-       u32 id;
+       struct v4l2_fh *fh;             /* pointer to the streaming filehandle */
        spinlock_t qlock;               /* locks access to the queues */
        unsigned long s_flags;          /* status flags, see above */
        int dma;                        /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
@@ -379,7 +379,6 @@ struct ivtv_stream {
 
 struct ivtv_open_id {
        struct v4l2_fh fh;
-       u32 open_id;                    /* unique ID for this file descriptor */
        int type;                       /* stream type */
        int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode */
        struct ivtv *itv;
index 38f052257f4620498d6b23e0bf3b7cfb88aa5ba9..2cd6c89b7d917d618de7791bf919bb1015c899b9 100644 (file)
@@ -50,16 +50,16 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
 
        if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
                /* someone already claimed this stream */
-               if (s->id == id->open_id) {
+               if (s->fh == &id->fh) {
                        /* yes, this file descriptor did. So that's OK. */
                        return 0;
                }
-               if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI ||
+               if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
                                         type == IVTV_ENC_STREAM_TYPE_VBI)) {
                        /* VBI is handled already internally, now also assign
                           the file descriptor to this stream for external
                           reading of the stream. */
-                       s->id = id->open_id;
+                       s->fh = &id->fh;
                        IVTV_DEBUG_INFO("Start Read VBI\n");
                        return 0;
                }
@@ -67,7 +67,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
                IVTV_DEBUG_INFO("Stream %d is busy\n", type);
                return -EBUSY;
        }
-       s->id = id->open_id;
+       s->fh = &id->fh;
        if (type == IVTV_DEC_STREAM_TYPE_VBI) {
                /* Enable reinsertion interrupt */
                ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
@@ -104,7 +104,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
        struct ivtv *itv = s->itv;
        struct ivtv_stream *s_vbi;
 
-       s->id = -1;
+       s->fh = NULL;
        if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
                test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
                /* this stream is still in use internally */
@@ -136,7 +136,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
                /* was already cleared */
                return;
        }
-       if (s_vbi->id != -1) {
+       if (s_vbi->fh) {
                /* VBI stream still claimed by a file descriptor */
                return;
        }
@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
                }
 
                /* wait for more data to arrive */
+               mutex_unlock(&itv->serialize_lock);
                prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
                /* New buffers might have become available before we were added to the waitqueue */
                if (!s->q_full.buffers)
                        schedule();
                finish_wait(&s->waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
                if (signal_pending(current)) {
                        /* return if a signal was received */
                        IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@@ -357,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
        size_t tot_written = 0;
        int single_frame = 0;
 
-       if (atomic_read(&itv->capturing) == 0 && s->id == -1) {
+       if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
                /* shouldn't happen */
                IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
                return -EIO;
@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
 
        IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
 
-       mutex_lock(&itv->serialize_lock);
        rc = ivtv_start_capture(id);
-       mutex_unlock(&itv->serialize_lock);
        if (rc)
                return rc;
        return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
        set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
 
        /* Start decoder (returns 0 if already started) */
-       mutex_lock(&itv->serialize_lock);
        rc = ivtv_start_decoding(id, itv->speed);
-       mutex_unlock(&itv->serialize_lock);
        if (rc) {
                IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
 
@@ -627,11 +625,13 @@ retry:
                        break;
                if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
+               mutex_unlock(&itv->serialize_lock);
                prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
                /* New buffers might have become free before we were added to the waitqueue */
                if (!s->q_free.buffers)
                        schedule();
                finish_wait(&s->waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
                if (signal_pending(current)) {
                        IVTV_DEBUG_INFO("User stopped %s\n", s->name);
                        return -EINTR;
@@ -686,12 +686,14 @@ retry:
                        if (mode == OUT_YUV)
                                ivtv_yuv_setup_stream_frame(itv);
 
+                       mutex_unlock(&itv->serialize_lock);
                        prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
                        while (!(got_sig = signal_pending(current)) &&
                                        test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
                                schedule();
                        }
                        finish_wait(&itv->dma_waitq, &wait);
+                       mutex_lock(&itv->serialize_lock);
                        if (got_sig) {
                                IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
                                return -EINTR;
@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
                int rc;
 
-               mutex_lock(&itv->serialize_lock);
                rc = ivtv_start_capture(id);
-               mutex_unlock(&itv->serialize_lock);
                if (rc) {
                        IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
                                        s->name, rc);
@@ -808,7 +808,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
                     id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
                    test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
                        /* Also used internally, don't stop capturing */
-                       s->id = -1;
+                       s->fh = NULL;
                }
                else {
                        ivtv_stop_v4l2_encode_stream(s, gop_end);
@@ -861,20 +861,9 @@ int ivtv_v4l2_close(struct file *filp)
 
        IVTV_DEBUG_FILE("close %s\n", s->name);
 
-       v4l2_fh_del(fh);
-       v4l2_fh_exit(fh);
-
-       /* Easy case first: this stream was never claimed by us */
-       if (s->id != id->open_id) {
-               kfree(id);
-               return 0;
-       }
-
-       /* 'Unclaim' this stream */
-
        /* Stop radio */
-       mutex_lock(&itv->serialize_lock);
-       if (id->type == IVTV_ENC_STREAM_TYPE_RAD) {
+       if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                /* Closing radio device, return to TV mode */
                ivtv_mute(itv);
                /* Mark that the radio is no longer in use */
@@ -890,13 +879,25 @@ int ivtv_v4l2_close(struct file *filp)
                if (atomic_read(&itv->capturing) > 0) {
                        /* Undo video mute */
                        ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
-                               v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
-                               (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+                                       v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
+                                       (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
                }
                /* Done! Unmute and continue. */
                ivtv_unmute(itv);
-               ivtv_release_stream(s);
-       } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+       }
+
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
+
+       /* Easy case first: this stream was never claimed by us */
+       if (s->fh != &id->fh) {
+               kfree(id);
+               return 0;
+       }
+
+       /* 'Unclaim' this stream */
+
+       if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
                struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
 
                ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
@@ -911,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp)
                ivtv_stop_capture(id, 0);
        }
        kfree(id);
-       mutex_unlock(&itv->serialize_lock);
        return 0;
 }
 
-static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
+int ivtv_v4l2_open(struct file *filp)
 {
-#ifdef CONFIG_VIDEO_ADV_DEBUG
        struct video_device *vdev = video_devdata(filp);
-#endif
+       struct ivtv_stream *s = video_get_drvdata(vdev);
        struct ivtv *itv = s->itv;
        struct ivtv_open_id *item;
        int res = 0;
 
        IVTV_DEBUG_FILE("open %s\n", s->name);
 
+       if (ivtv_init_on_first_open(itv)) {
+               IVTV_ERR("Failed to initialize on device %s\n",
+                        video_device_node_name(vdev));
+               return -ENXIO;
+       }
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        /* Unless ivtv_fw_debug is set, error out if firmware dead. */
        if (ivtv_fw_debug) {
@@ -966,31 +971,19 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
                return -ENOMEM;
        }
        v4l2_fh_init(&item->fh, s->vdev);
-       if (res < 0) {
-               v4l2_fh_exit(&item->fh);
-               kfree(item);
-               return res;
-       }
        item->itv = itv;
        item->type = s->type;
 
-       item->open_id = itv->open_id++;
        filp->private_data = &item->fh;
+       v4l2_fh_add(&item->fh);
 
-       if (item->type == IVTV_ENC_STREAM_TYPE_RAD) {
-               /* Try to claim this stream */
-               if (ivtv_claim_stream(item, item->type)) {
-                       /* No, it's already in use */
-                       v4l2_fh_exit(&item->fh);
-                       kfree(item);
-                       return -EBUSY;
-               }
-
+       if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
                if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
                        if (atomic_read(&itv->capturing) > 0) {
                                /* switching to radio while capture is
                                   in progress is not polite */
-                               ivtv_release_stream(s);
+                               v4l2_fh_del(&item->fh);
                                v4l2_fh_exit(&item->fh);
                                kfree(item);
                                return -EBUSY;
@@ -1022,32 +1015,9 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
                itv->yuv_info.stream_size = 0;
        }
-       v4l2_fh_add(&item->fh);
        return 0;
 }
 
-int ivtv_v4l2_open(struct file *filp)
-{
-       int res;
-       struct ivtv *itv = NULL;
-       struct ivtv_stream *s = NULL;
-       struct video_device *vdev = video_devdata(filp);
-
-       s = video_get_drvdata(vdev);
-       itv = s->itv;
-
-       mutex_lock(&itv->serialize_lock);
-       if (ivtv_init_on_first_open(itv)) {
-               IVTV_ERR("Failed to initialize on device %s\n",
-                        video_device_node_name(vdev));
-               mutex_unlock(&itv->serialize_lock);
-               return -ENXIO;
-       }
-       res = ivtv_serialized_open(s, filp);
-       mutex_unlock(&itv->serialize_lock);
-       return res;
-}
-
 void ivtv_mute(struct ivtv *itv)
 {
        if (atomic_read(&itv->capturing))
index ecafa697326e302803ab85604c0a7ab8aec697f6..c4bc481430985c6405580a461e2cc8e518ae2d73 100644 (file)
@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
                ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
 
                /* Wait for any DMA to finish */
+               mutex_unlock(&itv->serialize_lock);
                prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
                while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
                        got_sig = signal_pending(current);
@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
                        schedule();
                }
                finish_wait(&itv->dma_waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
                if (got_sig)
                        return -EINTR;
 
@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
         * happens within the first 100 lines of the top field.
         * Make 4 attempts to sync to the decoder before giving up.
         */
+       mutex_unlock(&itv->serialize_lock);
        for (f = 0; f < 4; f++) {
                prepare_to_wait(&itv->vsync_waitq, &wait,
                                TASK_UNINTERRUPTIBLE);
@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
                schedule_timeout(msecs_to_jiffies(25));
        }
        finish_wait(&itv->vsync_waitq, &wait);
+       mutex_lock(&itv->serialize_lock);
 
        if (f == 4)
                IVTV_WARN("Mode change failed to sync to decoder\n");
@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
        return 0;
 }
 
-static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct video_device *vfd = video_devdata(filp);
        long ret;
@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
        return ret;
 }
 
-long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       long res;
-
-       /* DQEVENT can block, so this should not run with the serialize lock */
-       if (cmd == VIDIOC_DQEVENT)
-               return ivtv_serialized_ioctl(itv, filp, cmd, arg);
-       mutex_lock(&itv->serialize_lock);
-       res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
-       mutex_unlock(&itv->serialize_lock);
-       return res;
-}
-
 static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
        .vidioc_querycap                    = ivtv_querycap,
        .vidioc_s_audio                     = ivtv_s_audio,
index 9c29e964d400b955d36074487c17c22e1195bbcd..1b3b9578bf47657915b464e9b9513f48b481aa0e 100644 (file)
@@ -288,13 +288,13 @@ static void dma_post(struct ivtv_stream *s)
                        ivtv_process_vbi_data(itv, buf, 0, s->type);
                        s->q_dma.bytesused += buf->bytesused;
                }
-               if (s->id == -1) {
+               if (s->fh == NULL) {
                        ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
                        return;
                }
        }
        ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
-       if (s->id != -1)
+       if (s->fh)
                wake_up(&s->waitq);
 }
 
index e7794dc1330e50348a5e358714abf9f54702e56d..c6e28b4ebbed6dfe3e821e443dcff04d8e4694e3 100644 (file)
@@ -159,7 +159,6 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
                s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
        spin_lock_init(&s->qlock);
        init_waitqueue_head(&s->waitq);
-       s->id = -1;
        s->sg_handle = IVTV_DMA_UNMAPPED;
        ivtv_queue_init(&s->q_free);
        ivtv_queue_init(&s->q_full);
@@ -214,6 +213,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
        s->vdev->fops = ivtv_stream_info[type].fops;
        s->vdev->release = video_device_release;
        s->vdev->tvnorms = V4L2_STD_ALL;
+       s->vdev->lock = &itv->serialize_lock;
        set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
        ivtv_set_funcs(s->vdev);
        return 0;
index dcbab6ad4c26ee8843336f673aeb1f9f7fe7ef80..2ad65eb29832754b54a5d190257cadd5d6a09031 100644 (file)
@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
 {
        struct yuv_playback_info *yi = &itv->yuv_info;
        struct ivtv_dma_frame dma_args;
+       int res;
 
        ivtv_yuv_setup_stream_frame(itv);
 
        /* We only need to supply source addresses for this */
        dma_args.y_source = src;
        dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
-       return ivtv_yuv_udma_frame(itv, &dma_args);
+       /* Wait for frame DMA. Note that serialize_lock is locked,
+          so to allow other processes to access the driver while
+          we are waiting unlock first and later lock again. */
+       mutex_unlock(&itv->serialize_lock);
+       res = ivtv_yuv_udma_frame(itv, &dma_args);
+       mutex_lock(&itv->serialize_lock);
+       return res;
 }
 
 /* IVTV_IOC_DMA_FRAME ioctl handler */
 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
-/*     IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
+       int res;
 
+/*     IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
        ivtv_yuv_next_free(itv);
        ivtv_yuv_setup_frame(itv, args);
-       return ivtv_yuv_udma_frame(itv, args);
+       /* Wait for frame DMA. Note that serialize_lock is locked,
+          so to allow other processes to access the driver while
+          we are waiting unlock first and later lock again. */
+       mutex_unlock(&itv->serialize_lock);
+       res = ivtv_yuv_udma_frame(itv, args);
+       mutex_lock(&itv->serialize_lock);
+       return res;
 }
 
 void ivtv_yuv_close(struct ivtv *itv)
@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv)
        int h_filter, v_filter_1, v_filter_2;
 
        IVTV_DEBUG_YUV("ivtv_yuv_close\n");
+       mutex_unlock(&itv->serialize_lock);
        ivtv_waitq(&itv->vsync_waitq);
+       mutex_lock(&itv->serialize_lock);
 
        yi->running = 0;
        atomic_set(&yi->next_dma_frame, -1);
index 0cb461dd396af39ffbff65b387fdae11742d4ebf..74522773e934c18e417f36b36aed40017b35e02f 100644 (file)
@@ -287,7 +287,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
                sg_dma_len(sg)          = new_size;
 
                txd = ichan->dma_chan.device->device_prep_slave_sg(
-                       &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
+                       &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT);
                if (!txd)
                        goto error;
index a277f95091ef2b481b369dca5cacc30cbf04afe4..1fb7d5bd5ec26a3f8955e8a6cdc3e7a6cd3841f9 100644 (file)
@@ -1042,7 +1042,8 @@ static int vidioc_querycap(struct file *file, void *fh,
        strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
        strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
        cap->bus_info[0] = '\0';
-       cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
+       cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+               V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
 
        return 0;
 }
@@ -1825,7 +1826,9 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
        ovid = &vout->vid_info;
        ovl = ovid->overlays[0];
 
-       a->flags = 0x0;
+       /* The video overlay must stay within the framebuffer and can't be
+          positioned independently. */
+       a->flags = V4L2_FBUF_FLAG_OVERLAY;
        a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
                | V4L2_FBUF_CAP_SRC_CHROMAKEY;
 
index 905d41d90c6aa816b7162ddf1d0f5e99bee4912a..1f506fde97d0a52433a7477f6ac843cc60af1f2f 100644 (file)
@@ -104,47 +104,16 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
 
 /****************************************************************************/
 
-static int _send_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, int index, void *buf, int buflen)
-{
-       int rc;
-       void *kbuf = NULL;
-
-       if (buflen) {
-               kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */
-               if (kbuf == NULL)
-                       return -ENOMEM;
-       }
-
-       rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-               request,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value,
-               index,
-               kbuf, buflen, USB_CTRL_SET_TIMEOUT);
-
-       kfree(kbuf);
-       return rc;
-}
-
 static int recv_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, void *buf, int buflen)
+       u8 request, u16 value, int recv_count)
 {
        int rc;
-       void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
-
-       if (kbuf == NULL)
-               return -ENOMEM;
 
        rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
                request,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value,
-               pdev->vcinterface,
-               kbuf, buflen, USB_CTRL_GET_TIMEOUT);
-       memcpy(buf, kbuf, buflen);
-       kfree(kbuf);
-
+               value, pdev->vcinterface,
+               pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
        if (rc < 0)
                PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
                          rc, request, value);
@@ -152,27 +121,39 @@ static int recv_control_msg(struct pwc_device *pdev,
 }
 
 static inline int send_video_command(struct pwc_device *pdev,
-       int index, void *buf, int buflen)
+       int index, const unsigned char *buf, int buflen)
 {
-       return _send_control_msg(pdev,
-               SET_EP_STREAM_CTL,
-               VIDEO_OUTPUT_CONTROL_FORMATTER,
-               index,
-               buf, buflen);
+       int rc;
+
+       memcpy(pdev->ctrl_buf, buf, buflen);
+
+       rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+                       SET_EP_STREAM_CTL,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       VIDEO_OUTPUT_CONTROL_FORMATTER, index,
+                       pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
+       if (rc >= 0)
+               memcpy(pdev->cmd_buf, buf, buflen);
+       else
+               PWC_ERROR("send_video_command error %d\n", rc);
+
+       return rc;
 }
 
 int send_control_msg(struct pwc_device *pdev,
        u8 request, u16 value, void *buf, int buflen)
 {
-       return _send_control_msg(pdev,
-               request, value, pdev->vcinterface, buf, buflen);
+       return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+                       request,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, pdev->vcinterface,
+                       buf, buflen, USB_CTRL_SET_TIMEOUT);
 }
 
-static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
-                              int *compression)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
+                              int frames, int *compression, int send_to_cam)
 {
-       unsigned char buf[3];
-       int ret, fps;
+       int fps, ret = 0;
        struct Nala_table_entry *pEntry;
        int frames2frames[31] =
        { /* closest match of framerate */
@@ -194,30 +175,29 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
          7              /* 30    */
        };
 
-       if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+       if (size < 0 || size > PSZ_CIF)
                return -EINVAL;
+       if (frames < 4)
+               frames = 4;
+       else if (frames > 25)
+               frames = 25;
        frames = frames2frames[frames];
        fps = frames2table[frames];
        pEntry = &Nala_table[size][fps];
        if (pEntry->alternate == 0)
                return -EINVAL;
 
-       memcpy(buf, pEntry->mode, 3);
-       ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
-       if (ret < 0) {
-               PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
+       if (send_to_cam)
+               ret = send_video_command(pdev, pdev->vendpoint,
+                                        pEntry->mode, 3);
+       if (ret < 0)
                return ret;
-       }
-       if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
-               if (ret < 0)
-                       return ret;
-       }
 
-       pdev->cmd_len = 3;
-       memcpy(pdev->cmd_buf, buf, 3);
+       if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec1_init(pdev, pEntry->mode);
 
        /* Set various parameters */
+       pdev->pixfmt = pixfmt;
        pdev->vframes = frames;
        pdev->valternate = pEntry->alternate;
        pdev->width  = pwc_image_sizes[size][0];
@@ -243,18 +223,20 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
 }
 
 
-static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
-       int *compression)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
+                               int frames, int *compression, int send_to_cam)
 {
-       unsigned char buf[13];
        const struct Timon_table_entry *pChoose;
-       int ret, fps;
+       int fps, ret = 0;
 
-       if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
-           *compression < 0 || *compression > 3)
-               return -EINVAL;
-       if (size == PSZ_VGA && frames > 15)
+       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
                return -EINVAL;
+       if (frames < 5)
+               frames = 5;
+       else if (size == PSZ_VGA && frames > 15)
+               frames = 15;
+       else if (frames > 30)
+               frames = 30;
        fps = (frames / 5) - 1;
 
        /* Find a supported framerate with progressively higher compression */
@@ -268,22 +250,18 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
 
-       memcpy(buf, pChoose->mode, 13);
-       ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
+       if (send_to_cam)
+               ret = send_video_command(pdev, pdev->vendpoint,
+                                        pChoose->mode, 13);
        if (ret < 0)
                return ret;
 
-       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               ret = pwc_dec23_init(pdev, pdev->type, buf);
-               if (ret < 0)
-                       return ret;
-       }
-
-       pdev->cmd_len = 13;
-       memcpy(pdev->cmd_buf, buf, 13);
+       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec23_init(pdev, pChoose->mode);
 
        /* Set various parameters */
-       pdev->vframes = frames;
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = (fps + 1) * 5;
        pdev->valternate = pChoose->alternate;
        pdev->width  = pwc_image_sizes[size][0];
        pdev->height = pwc_image_sizes[size][1];
@@ -296,18 +274,20 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
 }
 
 
-static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
-       int *compression)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
+                               int frames, int *compression, int send_to_cam)
 {
        const struct Kiara_table_entry *pChoose = NULL;
-       int fps, ret;
-       unsigned char buf[12];
+       int fps, ret = 0;
 
-       if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
-           *compression < 0 || *compression > 3)
-               return -EINVAL;
-       if (size == PSZ_VGA && frames > 15)
+       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
                return -EINVAL;
+       if (frames < 5)
+               frames = 5;
+       else if (size == PSZ_VGA && frames > 15)
+               frames = 15;
+       else if (frames > 30)
+               frames = 30;
        fps = (frames / 5) - 1;
 
        /* Find a supported framerate with progressively higher compression */
@@ -320,26 +300,18 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
 
-       PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
-
-       /* usb_control_msg won't take staticly allocated arrays as argument?? */
-       memcpy(buf, pChoose->mode, 12);
-
        /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
-       ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12);
+       if (send_to_cam)
+               ret = send_video_command(pdev, 4, pChoose->mode, 12);
        if (ret < 0)
                return ret;
 
-       if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               ret = pwc_dec23_init(pdev, pdev->type, buf);
-               if (ret < 0)
-                       return ret;
-       }
+       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec23_init(pdev, pChoose->mode);
 
-       pdev->cmd_len = 12;
-       memcpy(pdev->cmd_buf, buf, 12);
        /* All set and go */
-       pdev->vframes = frames;
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = (fps + 1) * 5;
        pdev->valternate = pChoose->alternate;
        pdev->width  = pwc_image_sizes[size][0];
        pdev->height = pwc_image_sizes[size][1];
@@ -354,22 +326,24 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
 }
 
 int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
-       int frames, int *compression)
+       int pixfmt, int frames, int *compression, int send_to_cam)
 {
        int ret, size;
 
-       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
+       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
+                      width, height, frames, pixfmt);
        size = pwc_get_size(pdev, width, height);
        PWC_TRACE("decode_size = %d.\n", size);
 
        if (DEVICE_USE_CODEC1(pdev->type)) {
-               ret = set_video_mode_Nala(pdev, size, frames, compression);
-
+               ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
+                                         compression, send_to_cam);
        } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               ret = set_video_mode_Kiara(pdev, size, frames, compression);
-
+               ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
+                                          compression, send_to_cam);
        } else {
-               ret = set_video_mode_Timon(pdev, size, frames, compression);
+               ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
+                                          compression, send_to_cam);
        }
        if (ret < 0) {
                PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
@@ -436,13 +410,12 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
 int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
-       u8 buf;
 
-       ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, 1);
        if (ret < 0)
                return ret;
 
-       *data = buf;
+       *data = pdev->ctrl_buf[0];
        return 0;
 }
 
@@ -450,7 +423,8 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
 {
        int ret;
 
-       ret = send_control_msg(pdev, request, value, &data, sizeof(data));
+       pdev->ctrl_buf[0] = data;
+       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
        if (ret < 0)
                return ret;
 
@@ -460,37 +434,34 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
 int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
-       s8 buf;
 
-       ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, 1);
        if (ret < 0)
                return ret;
 
-       *data = buf;
+       *data = ((s8 *)pdev->ctrl_buf)[0];
        return 0;
 }
 
 int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
-       u8 buf[2];
 
-       ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
+       ret = recv_control_msg(pdev, request, value, 2);
        if (ret < 0)
                return ret;
 
-       *data = (buf[1] << 8) | buf[0];
+       *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
        return 0;
 }
 
 int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
 {
        int ret;
-       u8 buf[2];
 
-       buf[0] = data & 0xff;
-       buf[1] = data >> 8;
-       ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
+       pdev->ctrl_buf[0] = data & 0xff;
+       pdev->ctrl_buf[1] = data >> 8;
+       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
        if (ret < 0)
                return ret;
 
@@ -511,7 +482,6 @@ int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
 /* POWER */
 void pwc_camera_power(struct pwc_device *pdev, int power)
 {
-       char buf;
        int r;
 
        if (!pdev->power_save)
@@ -521,13 +491,11 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
                return; /* Not supported by Nala or Timon < release 6 */
 
        if (power)
-               buf = 0x00; /* active */
+               pdev->ctrl_buf[0] = 0x00; /* active */
        else
-               buf = 0xFF; /* power save */
-       r = send_control_msg(pdev,
-               SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
-               &buf, sizeof(buf));
-
+               pdev->ctrl_buf[0] = 0xFF; /* power save */
+       r = send_control_msg(pdev, SET_STATUS_CTL,
+               SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
        if (r < 0)
                PWC_ERROR("Failed to power %s camera (%d)\n",
                          power ? "on" : "off", r);
@@ -535,7 +503,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
 
 int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 {
-       unsigned char buf[2];
        int r;
 
        if (pdev->type < 730)
@@ -551,11 +518,11 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
        if (off_value > 0xff)
                off_value = 0xff;
 
-       buf[0] = on_value;
-       buf[1] = off_value;
+       pdev->ctrl_buf[0] = on_value;
+       pdev->ctrl_buf[1] = off_value;
 
        r = send_control_msg(pdev,
-               SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
+               SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
        if (r < 0)
                PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
 
@@ -565,7 +532,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 #ifdef CONFIG_USB_PWC_DEBUG
 int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
 {
-       unsigned char buf;
        int ret = -1, request;
 
        if (pdev->type < 675)
@@ -575,14 +541,13 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
        else
                request = SENSOR_TYPE_FORMATTER2;
 
-       ret = recv_control_msg(pdev,
-               GET_STATUS_CTL, request, &buf, sizeof(buf));
+       ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
        if (ret < 0)
                return ret;
        if (pdev->type < 675)
-               *sensor = buf | 0x100;
+               *sensor = pdev->ctrl_buf[0] | 0x100;
        else
-               *sensor = buf;
+               *sensor = pdev->ctrl_buf[0];
        return 0;
 }
 #endif
index be0e02cb487f1ff2cba5f32fbccd1826056eb93f..e899036aadf4a4734e0dd611386bf47909fe34bb 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
-#include "pwc-dec1.h"
+#include "pwc.h"
 
-int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer)
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
 {
-       struct pwc_dec1_private *pdec;
+       struct pwc_dec1_private *pdec = &pdev->dec1;
 
-       if (pwc->decompress_data == NULL) {
-               pdec = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
-               if (pdec == NULL)
-                       return -ENOMEM;
-               pwc->decompress_data = pdec;
-       }
-       pdec = pwc->decompress_data;
-
-       return 0;
+       pdec->version = pdev->release;
 }
index a57d8601080babf0ca5ed403aef63220f900f2af..c565ef8f52fb3a83e29f5c428744aaf354b16db6 100644 (file)
 #ifndef PWC_DEC1_H
 #define PWC_DEC1_H
 
-#include "pwc.h"
+#include <linux/mutex.h>
+
+struct pwc_device;
 
 struct pwc_dec1_private
 {
        int version;
 };
 
-int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer);
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
 
 #endif
index 2c6709112b2f2c4d206e40701505658c73483a38..3792fedff9515e85734200d8ffb22aa1ed15bb93 100644 (file)
@@ -294,22 +294,17 @@ static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
 
 
 /* If the type or the command change, we rebuild the lookup table */
-int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
 {
        int flags, version, shift, i;
-       struct pwc_dec23_private *pdec;
-
-       if (pwc->decompress_data == NULL) {
-               pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
-               if (pdec == NULL)
-                       return -ENOMEM;
-               pwc->decompress_data = pdec;
-       }
-       pdec = pwc->decompress_data;
+       struct pwc_dec23_private *pdec = &pdev->dec23;
 
        mutex_init(&pdec->lock);
 
-       if (DEVICE_USE_CODEC3(type)) {
+       if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
+               return;
+
+       if (DEVICE_USE_CODEC3(pdev->type)) {
                flags = cmd[2] & 0x18;
                if (flags == 8)
                        pdec->nbits = 7;        /* More bits, mean more bits to encode the stream, but better quality */
@@ -356,7 +351,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
                pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
 #endif
 
-       return 0;
+       pdec->last_cmd = cmd[2];
+       pdec->last_cmd_valid = 1;
 }
 
 /*
@@ -659,12 +655,12 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
  * src: raw data
  * dst: image output
  */
-void pwc_dec23_decompress(const struct pwc_device *pwc,
+void pwc_dec23_decompress(struct pwc_device *pdev,
                          const void *src,
                          void *dst)
 {
        int bandlines_left, bytes_per_block;
-       struct pwc_dec23_private *pdec = pwc->decompress_data;
+       struct pwc_dec23_private *pdec = &pdev->dec23;
 
        /* YUV420P image format */
        unsigned char *pout_planar_y;
@@ -674,23 +670,22 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
 
        mutex_lock(&pdec->lock);
 
-       bandlines_left = pwc->height / 4;
-       bytes_per_block = pwc->width * 4;
-       plane_size = pwc->height * pwc->width;
+       bandlines_left = pdev->height / 4;
+       bytes_per_block = pdev->width * 4;
+       plane_size = pdev->height * pdev->width;
 
        pout_planar_y = dst;
        pout_planar_u = dst + plane_size;
        pout_planar_v = dst + plane_size + plane_size / 4;
 
        while (bandlines_left--) {
-               DecompressBand23(pwc->decompress_data,
-                                src,
+               DecompressBand23(pdec, src,
                                 pout_planar_y, pout_planar_u, pout_planar_v,
-                                pwc->width, pwc->width);
-               src += pwc->vbandlength;
+                                pdev->width, pdev->width);
+               src += pdev->vbandlength;
                pout_planar_y += bytes_per_block;
-               pout_planar_u += pwc->width;
-               pout_planar_v += pwc->width;
+               pout_planar_u += pdev->width;
+               pout_planar_v += pdev->width;
        }
        mutex_unlock(&pdec->lock);
 }
index d64a3c281af6aa0d5fe03471c5cd03d16f010588..c655b1c1e6a9f7d7c7e8ff725672190bb2829e0c 100644 (file)
 #ifndef PWC_DEC23_H
 #define PWC_DEC23_H
 
-#include "pwc.h"
+struct pwc_device;
 
 struct pwc_dec23_private
 {
        struct mutex lock;
 
+       unsigned char last_cmd, last_cmd_valid;
+
   unsigned int scalebits;
   unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
 
   unsigned int reservoir;
   unsigned int nbits_in_reservoir;
+
   const unsigned char *stream;
   int temp_colors[16];
 
@@ -51,8 +54,8 @@ struct pwc_dec23_private
 
 };
 
-int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
-void pwc_dec23_decompress(const struct pwc_device *pwc,
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
+void pwc_dec23_decompress(struct pwc_device *pdev,
                          const void *src,
                          void *dst);
 #endif
index 943d37ad0d33dd3983318bbddd0f4d19f185f55b..122fbd0081eb548a3416f2848661cc144066a78b 100644 (file)
@@ -128,18 +128,11 @@ static struct usb_driver pwc_driver = {
 #define MAX_DEV_HINTS  20
 #define MAX_ISOC_ERRORS        20
 
-static int default_fps = 10;
 #ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
 static int power_save = -1;
-static int led_on = 100, led_off; /* defaults to LED that is on while in use */
-static struct {
-       int type;
-       char serial_number[30];
-       int device_node;
-       struct pwc_device *pdev;
-} device_hint[MAX_DEV_HINTS];
+static int leds[2] = { 100, 0 };
 
 /***/
 
@@ -386,8 +379,8 @@ static int pwc_isoc_init(struct pwc_device *pdev)
 retry:
        /* We first try with low compression and then retry with a higher
           compression setting if there is not enough bandwidth. */
-       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height,
-                                pdev->vframes, &compression);
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+                                pdev->vframes, &compression, 1);
 
        /* Get the current alternate interface, adjust packet size */
        intf = usb_ifnum_to_if(udev, 0);
@@ -597,23 +590,9 @@ leave:
 static void pwc_video_release(struct v4l2_device *v)
 {
        struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
-       int hint;
-
-       /* search device_hint[] table if we occupy a slot, by any chance */
-       for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-               if (device_hint[hint].pdev == pdev)
-                       device_hint[hint].pdev = NULL;
-
-       /* Free intermediate decompression buffer & tables */
-       if (pdev->decompress_data != NULL) {
-               PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
-                                pdev->decompress_data);
-               kfree(pdev->decompress_data);
-               pdev->decompress_data = NULL;
-       }
 
        v4l2_ctrl_handler_free(&pdev->ctrl_handler);
-
+       kfree(pdev->ctrl_buf);
        kfree(pdev);
 }
 
@@ -758,7 +737,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
 
        /* Turn on camera and set LEDS on */
        pwc_camera_power(pdev, 1);
-       pwc_set_leds(pdev, led_on, led_off);
+       pwc_set_leds(pdev, leds[0], leds[1]);
 
        r = pwc_isoc_init(pdev);
        if (r) {
@@ -813,10 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        struct usb_device *udev = interface_to_usbdev(intf);
        struct pwc_device *pdev = NULL;
        int vendor_id, product_id, type_id;
-       int hint, rc;
+       int rc;
        int features = 0;
        int compression = 0;
-       int video_nr = -1; /* default: use next available device */
        int my_power_save = power_save;
        char serial_number[30], *name;
 
@@ -1076,7 +1054,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                return -ENOMEM;
        }
        pdev->type = type_id;
-       pdev->vframes = default_fps;
        pdev->features = features;
        pwc_construct(pdev); /* set min/max sizes correct */
 
@@ -1107,24 +1084,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
        PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
 
-       /* Now search device_hint[] table for a match, so we can hint a node number. */
-       for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
-               if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
-                    (device_hint[hint].pdev == NULL)) {
-                       /* so far, so good... try serial number */
-                       if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
-                               /* match! */
-                               video_nr = device_hint[hint].device_node;
-                               PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
-                               break;
-                       }
-               }
+       /* Allocate USB command buffers */
+       pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
+       if (!pdev->ctrl_buf) {
+               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+               rc = -ENOMEM;
+               goto err_free_mem;
        }
 
-       /* occupy slot */
-       if (hint < MAX_DEV_HINTS)
-               device_hint[hint].pdev = pdev;
-
 #ifdef CONFIG_USB_PWC_DEBUG
        /* Query sensor type */
        if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@@ -1138,8 +1105,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pwc_set_leds(pdev, 0, 0);
 
        /* Setup intial videomode */
-       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes,
-                               &compression);
+       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
+                               V4L2_PIX_FMT_YUV420, 30, &compression, 1);
        if (rc)
                goto err_free_mem;
 
@@ -1164,7 +1131,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
        pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
 
-       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
+       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
        if (rc < 0) {
                PWC_ERROR("Failed to register as video device (%d).\n", rc);
                goto err_unregister_v4l2_dev;
@@ -1207,8 +1174,7 @@ err_unregister_v4l2_dev:
 err_free_controls:
        v4l2_ctrl_handler_free(&pdev->ctrl_handler);
 err_free_mem:
-       if (hint < MAX_DEV_HINTS)
-               device_hint[hint].pdev = NULL;
+       kfree(pdev->ctrl_buf);
        kfree(pdev);
        return rc;
 }
@@ -1243,27 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
  * Initialization code & module stuff
  */
 
-static int fps;
-static int leds[2] = { -1, -1 };
 static unsigned int leds_nargs;
-static char *dev_hint[MAX_DEV_HINTS];
-static unsigned int dev_hint_nargs;
 
-module_param(fps, int, 0444);
 #ifdef CONFIG_USB_PWC_DEBUG
 module_param_named(trace, pwc_trace, int, 0644);
 #endif
 module_param(power_save, int, 0644);
 module_param_array(leds, int, &leds_nargs, 0444);
-module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
 
-MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
 #ifdef CONFIG_USB_PWC_DEBUG
 MODULE_PARM_DESC(trace, "For debugging purposes");
 #endif
 MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM_DESC(dev_hint, "Device node hints");
 
 MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
@@ -1273,114 +1231,13 @@ MODULE_VERSION( PWC_VERSION );
 
 static int __init usb_pwc_init(void)
 {
-       int i;
-
-#ifdef CONFIG_USB_PWC_DEBUG
-       PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
-       PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
-       PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
-       PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
-
-       if (pwc_trace >= 0) {
-               PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
-       }
-#endif
-
-       if (fps) {
-               if (fps < 4 || fps > 30) {
-                       PWC_ERROR("Framerate out of bounds (4-30).\n");
-                       return -EINVAL;
-               }
-               default_fps = fps;
-               PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
-       }
-
-       if (leds[0] >= 0)
-               led_on = leds[0];
-       if (leds[1] >= 0)
-               led_off = leds[1];
-
-       /* Big device node whoopla. Basically, it allows you to assign a
-          device node (/dev/videoX) to a camera, based on its type
-          & serial number. The format is [type[.serialnumber]:]node.
-
-          Any camera that isn't matched by these rules gets the next
-          available free device node.
-        */
-       for (i = 0; i < MAX_DEV_HINTS; i++) {
-               char *s, *colon, *dot;
-
-               /* This loop also initializes the array */
-               device_hint[i].pdev = NULL;
-               s = dev_hint[i];
-               if (s != NULL && *s != '\0') {
-                       device_hint[i].type = -1; /* wildcard */
-                       strcpy(device_hint[i].serial_number, "*");
-
-                       /* parse string: chop at ':' & '/' */
-                       colon = dot = s;
-                       while (*colon != '\0' && *colon != ':')
-                               colon++;
-                       while (*dot != '\0' && *dot != '.')
-                               dot++;
-                       /* Few sanity checks */
-                       if (*dot != '\0' && dot > colon) {
-                               PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
-                               return -EINVAL;
-                       }
-
-                       if (*colon == '\0') {
-                               /* No colon */
-                               if (*dot != '\0') {
-                                       PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
-                                       return -EINVAL;
-                               }
-                               else {
-                                       /* No type or serial number specified, just a number. */
-                                       device_hint[i].device_node =
-                                               simple_strtol(s, NULL, 10);
-                               }
-                       }
-                       else {
-                               /* There's a colon, so we have at least a type and a device node */
-                               device_hint[i].type =
-                                       simple_strtol(s, NULL, 10);
-                               device_hint[i].device_node =
-                                       simple_strtol(colon + 1, NULL, 10);
-                               if (*dot != '\0') {
-                                       /* There's a serial number as well */
-                                       int k;
-
-                                       dot++;
-                                       k = 0;
-                                       while (*dot != ':' && k < 29) {
-                                               device_hint[i].serial_number[k++] = *dot;
-                                               dot++;
-                                       }
-                                       device_hint[i].serial_number[k] = '\0';
-                               }
-                       }
-                       PWC_TRACE("device_hint[%d]:\n", i);
-                       PWC_TRACE("  type    : %d\n", device_hint[i].type);
-                       PWC_TRACE("  serial# : %s\n", device_hint[i].serial_number);
-                       PWC_TRACE("  node    : %d\n", device_hint[i].device_node);
-               }
-               else
-                       device_hint[i].type = 0; /* not filled */
-       } /* ..for MAX_DEV_HINTS */
-
-       PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
        return usb_register(&pwc_driver);
 }
 
 static void __exit usb_pwc_exit(void)
 {
-       PWC_DEBUG_MODULE("Deregistering driver.\n");
        usb_deregister(&pwc_driver);
-       PWC_INFO("Philips webcam module removed.\n");
 }
 
 module_init(usb_pwc_init);
 module_exit(usb_pwc_exit);
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 23a55b5814fc494ea2f2c95e8fb37b4142769726..9be5adffa874683929ec57d41e17eeb36bf600aa 100644 (file)
@@ -90,5 +90,4 @@ void pwc_construct(struct pwc_device *pdev)
                pdev->frame_header_size = 0;
                pdev->frame_trailer_size = 0;
        }
-       pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
 }
index 80e25842e84a218dc3dada13e96ced27e68c3b39..f495eeb5403aaff31dd66ba582a07d86297752b9 100644 (file)
@@ -493,16 +493,11 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
                        (pixelformat>>24)&255);
 
        ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
-                                pdev->vframes, &compression);
+                                pixelformat, 30, &compression, 0);
 
        PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
 
-       if (ret == 0) {
-               pdev->pixfmt = pixelformat;
-               pwc_vidioc_fill_fmt(f, pdev->width, pdev->height,
-                                   pdev->pixfmt);
-       }
-
+       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
 leave:
        mutex_unlock(&pdev->udevlock);
        return ret;
@@ -777,33 +772,33 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
 static int pwc_set_motor(struct pwc_device *pdev)
 {
        int ret;
-       u8 buf[4];
 
-       buf[0] = 0;
+       pdev->ctrl_buf[0] = 0;
        if (pdev->motor_pan_reset->is_new)
-               buf[0] |= 0x01;
+               pdev->ctrl_buf[0] |= 0x01;
        if (pdev->motor_tilt_reset->is_new)
-               buf[0] |= 0x02;
+               pdev->ctrl_buf[0] |= 0x02;
        if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
                ret = send_control_msg(pdev, SET_MPT_CTL,
-                                      PT_RESET_CONTROL_FORMATTER, buf, 1);
+                                      PT_RESET_CONTROL_FORMATTER,
+                                      pdev->ctrl_buf, 1);
                if (ret < 0)
                        return ret;
        }
 
-       memset(buf, 0, sizeof(buf));
+       memset(pdev->ctrl_buf, 0, 4);
        if (pdev->motor_pan->is_new) {
-               buf[0] = pdev->motor_pan->val & 0xFF;
-               buf[1] = (pdev->motor_pan->val >> 8);
+               pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
+               pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
        }
        if (pdev->motor_tilt->is_new) {
-               buf[2] = pdev->motor_tilt->val & 0xFF;
-               buf[3] = (pdev->motor_tilt->val >> 8);
+               pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
+               pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
        }
        if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
                ret = send_control_msg(pdev, SET_MPT_CTL,
                                       PT_RELATIVE_CONTROL_FORMATTER,
-                                      buf, sizeof(buf));
+                                      pdev->ctrl_buf, 4);
                if (ret < 0)
                        return ret;
        }
@@ -1094,6 +1089,63 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
        return 0;
 }
 
+static int pwc_g_parm(struct file *file, void *fh,
+                     struct v4l2_streamparm *parm)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(parm, 0, sizeof(*parm));
+
+       parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       parm->parm.capture.readbuffers = MIN_FRAMES;
+       parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+       parm->parm.capture.timeperframe.denominator = pdev->vframes;
+       parm->parm.capture.timeperframe.numerator = 1;
+
+       return 0;
+}
+
+static int pwc_s_parm(struct file *file, void *fh,
+                     struct v4l2_streamparm *parm)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int compression = 0;
+       int ret, fps;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           parm->parm.capture.timeperframe.numerator == 0)
+               return -EINVAL;
+
+       if (pwc_test_n_set_capt_file(pdev, file))
+               return -EBUSY;
+
+       fps = parm->parm.capture.timeperframe.denominator /
+             parm->parm.capture.timeperframe.numerator;
+
+       mutex_lock(&pdev->udevlock);
+       if (!pdev->udev) {
+               ret = -ENODEV;
+               goto leave;
+       }
+
+       if (pdev->iso_init) {
+               ret = -EBUSY;
+               goto leave;
+       }
+
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+                                fps, &compression, 0);
+
+       pwc_g_parm(file, fh, parm);
+
+leave:
+       mutex_unlock(&pdev->udevlock);
+       return ret;
+}
+
 static int pwc_log_status(struct file *file, void *priv)
 {
        struct pwc_device *pdev = video_drvdata(file);
@@ -1120,4 +1172,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
        .vidioc_log_status                  = pwc_log_status,
        .vidioc_enum_framesizes             = pwc_enum_framesizes,
        .vidioc_enum_frameintervals         = pwc_enum_frameintervals,
+       .vidioc_g_parm                      = pwc_g_parm,
+       .vidioc_s_parm                      = pwc_s_parm,
 };
index 47c518fef179949be25f50c51eac12f95ea7c819..e4d4d711dd1f4df7182d20bcc3591fda9e32f628 100644 (file)
@@ -44,6 +44,8 @@
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/input.h>
 #endif
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 /* Version block */
 #define PWC_VERSION    "10.0.15"
 #define DEVICE_USE_CODEC3(x) ((x)>=700)
 #define DEVICE_USE_CODEC23(x) ((x)>=675)
 
-/* from pwc-dec.h */
-#define PWCX_FLAG_PLANAR        0x0001
-
 /* Request types: video */
 #define SET_LUM_CTL                    0x01
 #define GET_LUM_CTL                    0x02
@@ -248,8 +247,8 @@ struct pwc_device
        char vmirror;           /* for ToUCaM series */
        char power_save;        /* Do powersaving for this cam */
 
-       int cmd_len;
        unsigned char cmd_buf[13];
+       unsigned char *ctrl_buf;
 
        struct urb *urbs[MAX_ISO_BUFS];
        char iso_init;
@@ -272,7 +271,10 @@ struct pwc_device
        int frame_total_size;   /* including header & trailer */
        int drop_frames;
 
-       void *decompress_data;  /* private data for decompression engine */
+       union { /* private data for decompression engine */
+               struct pwc_dec1_private dec1;
+               struct pwc_dec23_private dec23;
+       };
 
        /*
         * We have an 'image' and a 'view', where 'image' is the fixed-size img
@@ -364,7 +366,7 @@ void pwc_construct(struct pwc_device *pdev);
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
-                             int frames, int *compression);
+       int pixfmt, int frames, int *compression, int send_to_cam);
 extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
index 510cfab477fff48c57ddd2d9151b53ec144f91ea..a9e9653beeb4581a90ea34eed1b3d96eab2aae5d 100644 (file)
@@ -693,7 +693,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                        mf->code = 0;
                        continue;
                }
-               if (mf->width != tfmt->width || mf->width != tfmt->width) {
+               if (mf->width != tfmt->width || mf->height != tfmt->height) {
                        u32 fcc = ffmt->fourcc;
                        tfmt->width  = mf->width;
                        tfmt->height = mf->height;
@@ -702,7 +702,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                                               NULL, &fcc, FIMC_SD_PAD_SOURCE);
                        if (ffmt && ffmt->mbus_code)
                                mf->code = ffmt->mbus_code;
-                       if (mf->width != tfmt->width || mf->width != tfmt->width)
+                       if (mf->width != tfmt->width ||
+                           mf->height != tfmt->height)
                                continue;
                        tfmt->code = mf->code;
                }
@@ -710,7 +711,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                        ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
 
                if (mf->code == tfmt->code &&
-                   mf->width == tfmt->width && mf->width == tfmt->width)
+                   mf->width == tfmt->width && mf->height == tfmt->height)
                        break;
        }
 
index f5cbb8a4c540fc7d6beac2891c36aa812f05f281..81bcbb9492ea0a6d425375a57f3600837082d773 100644 (file)
@@ -848,11 +848,11 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
        v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
 
        ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
-                                    V4L2_CID_HFLIP, 0, 1, 1, 0);
+                                       V4L2_CID_ROTATE, 0, 270, 90, 0);
        ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
-                                   V4L2_CID_VFLIP, 0, 1, 1, 0);
+                                       V4L2_CID_HFLIP, 0, 1, 1, 0);
        ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
-                                   V4L2_CID_ROTATE, 0, 270, 90, 0);
+                                       V4L2_CID_VFLIP, 0, 1, 1, 0);
        if (variant->has_alpha)
                ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
                                    &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
index 615c862f0360ef20061e28701d1a99f460d0a7e1..8ea4ee116e46900224a528fa415d300d2c43196b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <media/v4l2-ctrls.h>
 #include <media/media-device.h>
 
index c40b0dde188353eb9dba6b9f88e894c7f586d4c3..febaa673d3635c019011ff174c70eee17818de17 100644 (file)
@@ -184,6 +184,7 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl)
                        ctx->rop = ROP4_INVERT;
                else
                        ctx->rop = ROP4_COPY;
+               break;
        default:
                v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n");
                return -EINVAL;
index f841a3e9845c6f6a00028884beedd27595a0da1e..1105a8749c8b23922c979adf2abe7dee222fe14c 100644 (file)
@@ -989,9 +989,10 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
  * ============================================================================
  */
 
-static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-                               unsigned int *nplanes, unsigned int sizes[],
-                               void *alloc_ctxs[])
+static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
+                          const struct v4l2_format *fmt,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], void *alloc_ctxs[])
 {
        struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
        struct s5p_jpeg_q_data *q_data = NULL;
index e43e128baf5f7c3ec7051337a1574821e9e863a2..83fe461af263529df7502f020886f58d63b68c1c 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
 #include <media/videobuf2-core.h>
@@ -475,7 +474,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
                        ctx->mv_size = 0;
                }
                ctx->dpb_count = s5p_mfc_get_dpb_count();
-               if (ctx->img_width == 0 || ctx->img_width == 0)
+               if (ctx->img_width == 0 || ctx->img_height == 0)
                        ctx->state = MFCINST_ERROR;
                else
                        ctx->state = MFCINST_HEAD_PARSED;
index 844a4d7797bc0be85ff01eae08837d5d49dbee69..c25ec022d2678f734e46b1f1f3b5b0d496150c8d 100644 (file)
@@ -165,7 +165,7 @@ static struct mfc_control controls[] = {
                .maximum = 32,
                .step = 1,
                .default_value = 1,
-               .flags = V4L2_CTRL_FLAG_VOLATILE,
+               .is_volatile = 1,
        },
 };
 
index 971591d6450fccc5a7164adb94cb40e3404fb635..5b72da5ce4183c15bf98dd570762f2f8f2ffb9de 100644 (file)
@@ -269,8 +269,6 @@ struct saa7164_board saa7164_boards[] = {
                .portb          = SAA7164_MPEG_DVB,
                .portc          = SAA7164_MPEG_ENCODER,
                .portd          = SAA7164_MPEG_ENCODER,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
                .porte          = SAA7164_MPEG_VBI,
                .portf          = SAA7164_MPEG_VBI,
                .chiprev        = SAA7164_CHIP_REV3,
@@ -333,8 +331,6 @@ struct saa7164_board saa7164_boards[] = {
                .portd          = SAA7164_MPEG_ENCODER,
                .porte          = SAA7164_MPEG_VBI,
                .portf          = SAA7164_MPEG_VBI,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
                .chiprev        = SAA7164_CHIP_REV3,
                .unit           = {{
                        .id             = 0x28,
index 0a2d75f0406631f582b17b50aaf6c4cd11e074df..4ed1c7c28ae704b4f1e843cb8db0ae7b74981c02 100644 (file)
@@ -565,7 +565,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        spin_unlock_irq(&fh->queue_lock);
 
        desc = fh->chan->device->device_prep_slave_sg(fh->chan,
-               buf->sg, sg_elems, DMA_FROM_DEVICE,
+               buf->sg, sg_elems, DMA_DEV_TO_MEM,
                DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
        if (!desc) {
                spin_lock_irq(&fh->queue_lock);
index 129f135d5a5fe1deffaa12fdc81611bd2ecd12d4..c096b3f742003bcbcfc40df79b49a2728f8b9539 100644 (file)
@@ -374,7 +374,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
 }
 #endif
 
-static bool check_firmware(struct usb_device *udev, int *down_firmware)
+static int check_firmware(struct usb_device *udev, int *down_firmware)
 {
        void *buf;
        int ret;
@@ -398,7 +398,7 @@ static bool check_firmware(struct usb_device *udev, int *down_firmware)
                *down_firmware = 1;
                return firmware_download(udev);
        }
-       return ret;
+       return 0;
 }
 
 static int poseidon_probe(struct usb_interface *interface,
index da1f4c2d2d4b8d217cd2e3dafc716b88a25ef762..cccd42be718ae7cc25d2b21189f9880528f38225 100644 (file)
@@ -465,8 +465,8 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_CHROMA_GAIN:              return "Chroma Gain";
        case V4L2_CID_ILLUMINATORS_1:           return "Illuminator 1";
        case V4L2_CID_ILLUMINATORS_2:           return "Illuminator 2";
-       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:  return "Minimum Number of Capture Buffers";
-       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:   return "Minimum Number of Output Buffers";
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:  return "Min Number of Capture Buffers";
+       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:   return "Min Number of Output Buffers";
        case V4L2_CID_ALPHA_COMPONENT:          return "Alpha Component";
 
        /* MPEG controls */
@@ -506,25 +506,25 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_MUTE_YUV:      return "Video Mute YUV";
        case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:       return "Decoder Slice Interface";
        case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:  return "MPEG4 Loop Filter Enable";
-       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:       return "The Number of Intra Refresh MBs";
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:       return "Number of Intra Refresh MBs";
        case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:               return "Frame Level Rate Control Enable";
        case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:                  return "H264 MB Level Rate Control";
        case V4L2_CID_MPEG_VIDEO_HEADER_MODE:                   return "Sequence Header Mode";
-       case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:                   return "The Max Number of Reference Picture";
+       case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:                   return "Max Number of Reference Pics";
        case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:               return "H263 I-Frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:               return "H263 P frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:               return "H263 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:               return "H263 P-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:               return "H263 B-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:                   return "H263 Minimum QP Value";
        case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:                   return "H263 Maximum QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:               return "H264 I-Frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:               return "H264 P frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:               return "H264 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:               return "H264 P-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:               return "H264 B-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:                   return "H264 Maximum QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:                   return "H264 Minimum QP Value";
        case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:            return "H264 8x8 Transform Enable";
        case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:                 return "H264 CPB Buffer Size";
-       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:             return "H264 Entorpy Mode";
-       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:                 return "H264 I Period";
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:             return "H264 Entropy Mode";
+       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:                 return "H264 I-Frame Period";
        case V4L2_CID_MPEG_VIDEO_H264_LEVEL:                    return "H264 Level";
        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:        return "H264 Loop Filter Alpha Offset";
        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:         return "H264 Loop Filter Beta Offset";
@@ -535,16 +535,16 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:           return "Aspect Ratio VUI Enable";
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:              return "VUI Aspect Ratio IDC";
        case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:              return "MPEG4 I-Frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P frame QP Value";
-       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P-Frame QP Value";
+       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:                  return "MPEG4 Minimum QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:                  return "MPEG4 Maximum QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:                   return "MPEG4 Level";
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:                 return "MPEG4 Profile";
        case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:                    return "Quarter Pixel Search Enable";
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:         return "The Maximum Bytes Per Slice";
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:            return "The Number of MB in a Slice";
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:              return "The Slice Partitioning Method";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:         return "Maximum Bytes in a Slice";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:            return "Number of MBs in a Slice";
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:              return "Slice Partitioning Method";
        case V4L2_CID_MPEG_VIDEO_VBV_SIZE:                      return "VBV Buffer Size";
 
        /* CAMERA controls */
@@ -580,7 +580,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_AUDIO_LIMITER_ENABLED:    return "Audio Limiter Feature Enabled";
        case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
        case V4L2_CID_AUDIO_LIMITER_DEVIATION:  return "Audio Limiter Deviation";
-       case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
+       case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled";
        case V4L2_CID_AUDIO_COMPRESSION_GAIN:   return "Audio Compression Gain";
        case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
        case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
@@ -588,24 +588,24 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_PILOT_TONE_ENABLED:       return "Pilot Tone Feature Enabled";
        case V4L2_CID_PILOT_TONE_DEVIATION:     return "Pilot Tone Deviation";
        case V4L2_CID_PILOT_TONE_FREQUENCY:     return "Pilot Tone Frequency";
-       case V4L2_CID_TUNE_PREEMPHASIS:         return "Pre-emphasis settings";
+       case V4L2_CID_TUNE_PREEMPHASIS:         return "Pre-Emphasis";
        case V4L2_CID_TUNE_POWER_LEVEL:         return "Tune Power Level";
        case V4L2_CID_TUNE_ANTENNA_CAPACITOR:   return "Tune Antenna Capacitor";
 
        /* Flash controls */
-       case V4L2_CID_FLASH_CLASS:              return "Flash controls";
-       case V4L2_CID_FLASH_LED_MODE:           return "LED mode";
-       case V4L2_CID_FLASH_STROBE_SOURCE:      return "Strobe source";
+       case V4L2_CID_FLASH_CLASS:              return "Flash Controls";
+       case V4L2_CID_FLASH_LED_MODE:           return "LED Mode";
+       case V4L2_CID_FLASH_STROBE_SOURCE:      return "Strobe Source";
        case V4L2_CID_FLASH_STROBE:             return "Strobe";
-       case V4L2_CID_FLASH_STROBE_STOP:        return "Stop strobe";
-       case V4L2_CID_FLASH_STROBE_STATUS:      return "Strobe status";
-       case V4L2_CID_FLASH_TIMEOUT:            return "Strobe timeout";
-       case V4L2_CID_FLASH_INTENSITY:          return "Intensity, flash mode";
-       case V4L2_CID_FLASH_TORCH_INTENSITY:    return "Intensity, torch mode";
-       case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator";
+       case V4L2_CID_FLASH_STROBE_STOP:        return "Stop Strobe";
+       case V4L2_CID_FLASH_STROBE_STATUS:      return "Strobe Status";
+       case V4L2_CID_FLASH_TIMEOUT:            return "Strobe Timeout";
+       case V4L2_CID_FLASH_INTENSITY:          return "Intensity, Flash Mode";
+       case V4L2_CID_FLASH_TORCH_INTENSITY:    return "Intensity, Torch Mode";
+       case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator";
        case V4L2_CID_FLASH_FAULT:              return "Faults";
        case V4L2_CID_FLASH_CHARGE:             return "Charge";
-       case V4L2_CID_FLASH_READY:              return "Ready to strobe";
+       case V4L2_CID_FLASH_READY:              return "Ready to Strobe";
 
        default:
                return NULL;
index 77feeb67e2db389334e186299c882ce4fd87e847..3f623859a337126aa035df7c00817a6ad5da6fee 100644 (file)
@@ -1871,6 +1871,7 @@ static long __video_do_ioctl(struct file *file,
        case VIDIOC_S_FREQUENCY:
        {
                struct v4l2_frequency *p = arg;
+               enum v4l2_tuner_type type;
 
                if (!ops->vidioc_s_frequency)
                        break;
@@ -1878,9 +1879,14 @@ static long __video_do_ioctl(struct file *file,
                        ret = ret_prio;
                        break;
                }
+               type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
+                       V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
                dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
                                p->tuner, p->type, p->frequency);
-               ret = ops->vidioc_s_frequency(file, fh, p);
+               if (p->type != type)
+                       ret = -EINVAL;
+               else
+                       ret = ops->vidioc_s_frequency(file, fh, p);
                break;
        }
        case VIDIOC_G_SLICED_VBI_CAP:
index f6d26419445ee8728367fe925ed3f80d2d484092..4c09ab781ec3a3cbf503f2626c64b449e94dabf3 100644 (file)
@@ -1958,7 +1958,6 @@ static int zoran_g_fbuf(struct file *file, void *__fh,
        mutex_unlock(&zr->resource_lock);
        fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
        fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->flags = V4L2_FBUF_FLAG_OVERLAY;
        fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
 
        return 0;
index cd13e9f2f5e668d14927b698b851b6d0f99dd7bb..f147395bac9a1ef14b5afee016d17e1d0f89e40f 100644 (file)
@@ -200,7 +200,7 @@ config MENELAUS
 
 config TWL4030_CORE
        bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
-       depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN
+       depends on I2C=y && GENERIC_HARDIRQS
        help
          Say yes here if you have TWL4030 / TWL6030 family chip on your board.
          This core driver provides register access and IRQ handling
index 63be60bc3455396e764fa57661f497d5670b04a8..86cc3f7841cdfdb2714368b1459a5fd54ac6491a 100644 (file)
 #define to_mcp(d)              container_of(d, struct mcp, attached_device)
 #define to_mcp_driver(d)       container_of(d, struct mcp_driver, drv)
 
-static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id,
-                                               const char *codec)
-{
-       while (id->name[0]) {
-               if (strcmp(codec, id->name) == 0)
-                       return id;
-               id++;
-       }
-       return NULL;
-}
-
-const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp)
-{
-       const struct mcp_driver *driver =
-               to_mcp_driver(mcp->attached_device.driver);
-
-       return mcp_match_id(driver->id_table, mcp->codec);
-}
-EXPORT_SYMBOL(mcp_get_device_id);
-
 static int mcp_bus_match(struct device *dev, struct device_driver *drv)
 {
-       const struct mcp *mcp = to_mcp(dev);
-       const struct mcp_driver *driver = to_mcp_driver(drv);
-
-       if (driver->id_table)
-               return !!mcp_match_id(driver->id_table, mcp->codec);
-
-       return 0;
+       return 1;
 }
 
 static int mcp_bus_probe(struct device *dev)
@@ -100,18 +74,9 @@ static int mcp_bus_resume(struct device *dev)
        return ret;
 }
 
-static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       struct mcp *mcp = to_mcp(dev);
-
-       add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec);
-       return 0;
-}
-
 static struct bus_type mcp_bus_type = {
        .name           = "mcp",
        .match          = mcp_bus_match,
-       .uevent         = mcp_bus_uevent,
        .probe          = mcp_bus_probe,
        .remove         = mcp_bus_remove,
        .suspend        = mcp_bus_suspend,
@@ -128,9 +93,11 @@ static struct bus_type mcp_bus_type = {
  */
 void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
 {
-       spin_lock_irq(&mcp->lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&mcp->lock, flags);
        mcp->ops->set_telecom_divisor(mcp, div);
-       spin_unlock_irq(&mcp->lock);
+       spin_unlock_irqrestore(&mcp->lock, flags);
 }
 EXPORT_SYMBOL(mcp_set_telecom_divisor);
 
@@ -143,9 +110,11 @@ EXPORT_SYMBOL(mcp_set_telecom_divisor);
  */
 void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
 {
-       spin_lock_irq(&mcp->lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&mcp->lock, flags);
        mcp->ops->set_audio_divisor(mcp, div);
-       spin_unlock_irq(&mcp->lock);
+       spin_unlock_irqrestore(&mcp->lock, flags);
 }
 EXPORT_SYMBOL(mcp_set_audio_divisor);
 
@@ -198,10 +167,11 @@ EXPORT_SYMBOL(mcp_reg_read);
  */
 void mcp_enable(struct mcp *mcp)
 {
-       spin_lock_irq(&mcp->lock);
+       unsigned long flags;
+       spin_lock_irqsave(&mcp->lock, flags);
        if (mcp->use_count++ == 0)
                mcp->ops->enable(mcp);
-       spin_unlock_irq(&mcp->lock);
+       spin_unlock_irqrestore(&mcp->lock, flags);
 }
 EXPORT_SYMBOL(mcp_enable);
 
@@ -247,14 +217,9 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
 }
 EXPORT_SYMBOL(mcp_host_alloc);
 
-int mcp_host_register(struct mcp *mcp, void *pdata)
+int mcp_host_register(struct mcp *mcp)
 {
-       if (!mcp->codec)
-               return -EINVAL;
-
-       mcp->attached_device.platform_data = pdata;
        dev_set_name(&mcp->attached_device, "mcp0");
-       request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec);
        return device_register(&mcp->attached_device);
 }
 EXPORT_SYMBOL(mcp_host_register);
index 9adc2eb6949252031b3964320d3e6e1dfa4d4ed0..02c53a0766c4275d7496ece5b96cb20b0e1ddc49 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/mcp.h>
-#include <linux/io.h>
 
 #include <mach/dma.h>
 #include <mach/hardware.h>
 #include <asm/system.h>
 #include <mach/mcp.h>
 
-/* Register offsets */
-#define MCCR0  0x00
-#define MCDR0  0x08
-#define MCDR1  0x0C
-#define MCDR2  0x10
-#define MCSR   0x18
-#define MCCR1  0x00
+#include <mach/assabet.h>
+
 
 struct mcp_sa11x0 {
-       u32             mccr0;
-       u32             mccr1;
-       unsigned char   *mccr0_base;
-       unsigned char   *mccr1_base;
+       u32     mccr0;
+       u32     mccr1;
 };
 
 #define priv(mcp)      ((struct mcp_sa11x0 *)mcp_priv(mcp))
@@ -47,25 +39,25 @@ struct mcp_sa11x0 {
 static void
 mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
 {
-       struct mcp_sa11x0 *priv = priv(mcp);
+       unsigned int mccr0;
 
        divisor /= 32;
 
-       priv->mccr0 &= ~0x00007f00;
-       priv->mccr0 |= divisor << 8;
-       __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+       mccr0 = Ser4MCCR0 & ~0x00007f00;
+       mccr0 |= divisor << 8;
+       Ser4MCCR0 = mccr0;
 }
 
 static void
 mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
 {
-       struct mcp_sa11x0 *priv = priv(mcp);
+       unsigned int mccr0;
 
        divisor /= 32;
 
-       priv->mccr0 &= ~0x0000007f;
-       priv->mccr0 |= divisor;
-       __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+       mccr0 = Ser4MCCR0 & ~0x0000007f;
+       mccr0 |= divisor;
+       Ser4MCCR0 = mccr0;
 }
 
 /*
@@ -79,16 +71,12 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
 {
        int ret = -ETIME;
        int i;
-       u32 mcpreg;
-       struct mcp_sa11x0 *priv = priv(mcp);
 
-       mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff);
-       __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
+       Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
 
        for (i = 0; i < 2; i++) {
                udelay(mcp->rw_timeout);
-               mcpreg = __raw_readl(priv->mccr0_base + MCSR);
-               if (mcpreg & MCSR_CWC) {
+               if (Ser4MCSR & MCSR_CWC) {
                        ret = 0;
                        break;
                }
@@ -109,18 +97,13 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
 {
        int ret = -ETIME;
        int i;
-       u32 mcpreg;
-       struct mcp_sa11x0 *priv = priv(mcp);
 
-       mcpreg = reg << 17 | MCDR2_Rd;
-       __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
+       Ser4MCDR2 = reg << 17 | MCDR2_Rd;
 
        for (i = 0; i < 2; i++) {
                udelay(mcp->rw_timeout);
-               mcpreg = __raw_readl(priv->mccr0_base + MCSR);
-               if (mcpreg & MCSR_CRC) {
-                       ret = __raw_readl(priv->mccr0_base + MCDR2)
-                               & 0xffff;
+               if (Ser4MCSR & MCSR_CRC) {
+                       ret = Ser4MCDR2 & 0xffff;
                        break;
                }
        }
@@ -133,19 +116,13 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
 
 static void mcp_sa11x0_enable(struct mcp *mcp)
 {
-       struct mcp_sa11x0 *priv = priv(mcp);
-
-       __raw_writel(-1, priv->mccr0_base + MCSR);
-       priv->mccr0 |= MCCR0_MCE;
-       __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+       Ser4MCSR = -1;
+       Ser4MCCR0 |= MCCR0_MCE;
 }
 
 static void mcp_sa11x0_disable(struct mcp *mcp)
 {
-       struct mcp_sa11x0 *priv = priv(mcp);
-
-       priv->mccr0 &= ~MCCR0_MCE;
-       __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+       Ser4MCCR0 &= ~MCCR0_MCE;
 }
 
 /*
@@ -165,69 +142,50 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
        struct mcp_plat_data *data = pdev->dev.platform_data;
        struct mcp *mcp;
        int ret;
-       struct mcp_sa11x0 *priv;
-       struct resource *res_mem0, *res_mem1;
-       u32 size0, size1;
 
        if (!data)
                return -ENODEV;
 
-       if (!data->codec)
-               return -ENODEV;
-
-       res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res_mem0)
-               return -ENODEV;
-       size0 = res_mem0->end - res_mem0->start + 1;
-
-       res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res_mem1)
-               return -ENODEV;
-       size1 = res_mem1->end - res_mem1->start + 1;
-
-       if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp"))
+       if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
                return -EBUSY;
 
-       if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) {
-               ret = -EBUSY;
-               goto release;
-       }
-
        mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
        if (!mcp) {
                ret = -ENOMEM;
-               goto release2;
+               goto release;
        }
 
-       priv = priv(mcp);
-
        mcp->owner              = THIS_MODULE;
        mcp->ops                = &mcp_sa11x0;
        mcp->sclk_rate          = data->sclk_rate;
-       mcp->dma_audio_rd       = DDAR_DevAdd(res_mem0->start + MCDR0)
-                               + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
-       mcp->dma_audio_wr       = DDAR_DevAdd(res_mem0->start + MCDR0)
-                               + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
-       mcp->dma_telco_rd       = DDAR_DevAdd(res_mem0->start + MCDR1)
-                               + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
-       mcp->dma_telco_wr       = DDAR_DevAdd(res_mem0->start + MCDR1)
-                               + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
-       mcp->codec              = data->codec;
+       mcp->dma_audio_rd       = DMA_Ser4MCP0Rd;
+       mcp->dma_audio_wr       = DMA_Ser4MCP0Wr;
+       mcp->dma_telco_rd       = DMA_Ser4MCP1Rd;
+       mcp->dma_telco_wr       = DMA_Ser4MCP1Wr;
+       mcp->gpio_base          = data->gpio_base;
 
        platform_set_drvdata(pdev, mcp);
 
+       if (machine_is_assabet()) {
+               ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+       }
+
+       /*
+        * Setup the PPC unit correctly.
+        */
+       PPDR &= ~PPC_RXD4;
+       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+       PSDR |= PPC_RXD4;
+       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
        /*
         * Initialise device.  Note that we initially
         * set the sampling rate to minimum.
         */
-       priv->mccr0_base = ioremap(res_mem0->start, size0);
-       priv->mccr1_base = ioremap(res_mem1->start, size1);
-
-       __raw_writel(-1, priv->mccr0_base + MCSR);
-       priv->mccr1 = data->mccr1;
-       priv->mccr0 = data->mccr0 | 0x7f7f;
-       __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
-       __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
+       Ser4MCSR = -1;
+       Ser4MCCR1 = data->mccr1;
+       Ser4MCCR0 = data->mccr0 | 0x7f7f;
 
        /*
         * Calculate the read/write timeout (us) from the bit clock
@@ -237,53 +195,36 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
        mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
                          mcp->sclk_rate;
 
-       ret = mcp_host_register(mcp, data->codec_pdata);
+       ret = mcp_host_register(mcp);
        if (ret == 0)
                goto out;
 
- release2:
-       release_mem_region(res_mem1->start, size1);
  release:
-       release_mem_region(res_mem0->start, size0);
+       release_mem_region(0x80060000, 0x60);
        platform_set_drvdata(pdev, NULL);
 
  out:
        return ret;
 }
 
-static int mcp_sa11x0_remove(struct platform_device *pdev)
+static int mcp_sa11x0_remove(struct platform_device *dev)
 {
-       struct mcp *mcp = platform_get_drvdata(pdev);
-       struct mcp_sa11x0 *priv = priv(mcp);
-       struct resource *res_mem;
-       u32 size;
+       struct mcp *mcp = platform_get_drvdata(dev);
 
-       platform_set_drvdata(pdev, NULL);
+       platform_set_drvdata(dev, NULL);
        mcp_host_unregister(mcp);
+       release_mem_region(0x80060000, 0x60);
 
-       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res_mem) {
-               size = res_mem->end - res_mem->start + 1;
-               release_mem_region(res_mem->start, size);
-       }
-       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (res_mem) {
-               size = res_mem->end - res_mem->start + 1;
-               release_mem_region(res_mem->start, size);
-       }
-       iounmap(priv->mccr0_base);
-       iounmap(priv->mccr1_base);
        return 0;
 }
 
 static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
 {
        struct mcp *mcp = platform_get_drvdata(dev);
-       struct mcp_sa11x0 *priv = priv(mcp);
-       u32 mccr0;
 
-       mccr0 = priv->mccr0 & ~MCCR0_MCE;
-       __raw_writel(mccr0, priv->mccr0_base + MCCR0);
+       priv(mcp)->mccr0 = Ser4MCCR0;
+       priv(mcp)->mccr1 = Ser4MCCR1;
+       Ser4MCCR0 &= ~MCCR0_MCE;
 
        return 0;
 }
@@ -291,10 +232,9 @@ static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
 static int mcp_sa11x0_resume(struct platform_device *dev)
 {
        struct mcp *mcp = platform_get_drvdata(dev);
-       struct mcp_sa11x0 *priv = priv(mcp);
 
-       __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
-       __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
+       Ser4MCCR1 = priv(mcp)->mccr1;
+       Ser4MCCR0 = priv(mcp)->mccr0;
 
        return 0;
 }
@@ -311,7 +251,6 @@ static struct platform_driver mcp_sa11x0_driver = {
        .resume         = mcp_sa11x0_resume,
        .driver         = {
                .name   = "sa11x0-mcp",
-               .owner  = THIS_MODULE,
        },
 };
 
index e04e04ddc15e41f933b2a58de5f3bc8d28e86c25..8ce3959c69199444f8b0cc27edc66b04968165cb 100644 (file)
@@ -263,7 +263,9 @@ struct twl_client {
 
 static struct twl_client twl_modules[TWL_NUM_SLAVES];
 
+#ifdef CONFIG_IRQ_DOMAIN
 static struct irq_domain domain;
+#endif
 
 /* mapping the module id to slave id and base address */
 struct twl_mapping {
@@ -1226,13 +1228,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
        pdata->irq_base = status;
        pdata->irq_end = pdata->irq_base + nr_irqs;
 
+#ifdef CONFIG_IRQ_DOMAIN
        domain.irq_base = pdata->irq_base;
        domain.nr_irq = nr_irqs;
-#ifdef CONFIG_OF_IRQ
        domain.of_node = of_node_get(node);
        domain.ops = &irq_domain_simple_ops;
-#endif
        irq_domain_add(&domain);
+#endif
 
        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
                dev_dbg(&client->dev, "can't talk I2C?\n");
index d905f5171153e7f5ee3d8a808c493255883dd704..79ca33dfacca79e5fb8db8b11f32236eef78ad2d 100644 (file)
@@ -124,7 +124,7 @@ static u8 res_config_addrs[] = {
        [RES_MAIN_REF]  = 0x94,
 };
 
-static int __init twl4030_write_script_byte(u8 address, u8 byte)
+static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
 {
        int err;
 
@@ -138,7 +138,7 @@ out:
        return err;
 }
 
-static int __init twl4030_write_script_ins(u8 address, u16 pmb_message,
+static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,
                                           u8 delay, u8 next)
 {
        int err;
@@ -158,7 +158,7 @@ out:
        return err;
 }
 
-static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
+static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script,
                                       int len)
 {
        int err;
@@ -183,7 +183,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
        return err;
 }
 
-static int __init twl4030_config_wakeup3_sequence(u8 address)
+static int __devinit twl4030_config_wakeup3_sequence(u8 address)
 {
        int err;
        u8 data;
@@ -208,7 +208,7 @@ out:
        return err;
 }
 
-static int __init twl4030_config_wakeup12_sequence(u8 address)
+static int __devinit twl4030_config_wakeup12_sequence(u8 address)
 {
        int err = 0;
        u8 data;
@@ -262,7 +262,7 @@ out:
        return err;
 }
 
-static int __init twl4030_config_sleep_sequence(u8 address)
+static int __devinit twl4030_config_sleep_sequence(u8 address)
 {
        int err;
 
@@ -276,7 +276,7 @@ static int __init twl4030_config_sleep_sequence(u8 address)
        return err;
 }
 
-static int __init twl4030_config_warmreset_sequence(u8 address)
+static int __devinit twl4030_config_warmreset_sequence(u8 address)
 {
        int err;
        u8 rd_data;
@@ -324,7 +324,7 @@ out:
        return err;
 }
 
-static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
+static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig)
 {
        int rconfig_addr;
        int err;
@@ -416,7 +416,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
        return 0;
 }
 
-static int __init load_twl4030_script(struct twl4030_script *tscript,
+static int __devinit load_twl4030_script(struct twl4030_script *tscript,
               u8 address)
 {
        int err;
@@ -527,7 +527,7 @@ void twl4030_power_off(void)
                pr_err("TWL4030 Unable to power off\n");
 }
 
-void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
+void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 {
        int err = 0;
        int i;
index dda86293dc9fc0a3f8baaf678591d764824cfe14..b2d8e512d3cb002b6f3e809e47a12f01f96de588 100644 (file)
@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                /* Default PLL configuration after power up */
                twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
                twl6040->sysclk = 19200000;
+               twl6040->mclk = 32768;
        } else {
                /* already powered-down */
                if (!twl6040->power_count) {
@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                        twl6040_power_down(twl6040);
                }
                twl6040->sysclk = 0;
+               twl6040->mclk = 0;
        }
 
 out:
@@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
        hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
        lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
 
+       /* Force full reconfiguration when switching between PLL */
+       if (pll_id != twl6040->pll) {
+               twl6040->sysclk = 0;
+               twl6040->mclk = 0;
+       }
+
        switch (pll_id) {
        case TWL6040_SYSCLK_SEL_LPPLL:
                /* low-power PLL divider */
-               switch (freq_out) {
-               case 17640000:
-                       lppllctl |= TWL6040_LPLLFIN;
-                       break;
-               case 19200000:
-                       lppllctl &= ~TWL6040_LPLLFIN;
-                       break;
-               default:
-                       dev_err(twl6040->dev,
-                               "freq_out %d not supported\n", freq_out);
-                       ret = -EINVAL;
-                       goto pll_out;
+               /* Change the sysclk configuration only if it has been canged */
+               if (twl6040->sysclk != freq_out) {
+                       switch (freq_out) {
+                       case 17640000:
+                               lppllctl |= TWL6040_LPLLFIN;
+                               break;
+                       case 19200000:
+                               lppllctl &= ~TWL6040_LPLLFIN;
+                               break;
+                       default:
+                               dev_err(twl6040->dev,
+                                       "freq_out %d not supported\n",
+                                       freq_out);
+                               ret = -EINVAL;
+                               goto pll_out;
+                       }
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
                }
-               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+               /* The PLL in use has not been change, we can exit */
+               if (twl6040->pll == pll_id)
+                       break;
 
                switch (freq_in) {
                case 32768:
@@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
                        goto pll_out;
                }
 
-               hppllctl &= ~TWL6040_MCLK_MSK;
+               if (twl6040->mclk != freq_in) {
+                       hppllctl &= ~TWL6040_MCLK_MSK;
+
+                       switch (freq_in) {
+                       case 12000000:
+                               /* PLL enabled, active mode */
+                               hppllctl |= TWL6040_MCLK_12000KHZ |
+                                           TWL6040_HPLLENA;
+                               break;
+                       case 19200000:
+                               /*
+                               * PLL disabled
+                               * (enable PLL if MCLK jitter quality
+                               *  doesn't meet specification)
+                               */
+                               hppllctl |= TWL6040_MCLK_19200KHZ;
+                               break;
+                       case 26000000:
+                               /* PLL enabled, active mode */
+                               hppllctl |= TWL6040_MCLK_26000KHZ |
+                                           TWL6040_HPLLENA;
+                               break;
+                       case 38400000:
+                               /* PLL enabled, active mode */
+                               hppllctl |= TWL6040_MCLK_38400KHZ |
+                                           TWL6040_HPLLENA;
+                               break;
+                       default:
+                               dev_err(twl6040->dev,
+                                       "freq_in %d not supported\n", freq_in);
+                               ret = -EINVAL;
+                               goto pll_out;
+                       }
 
-               switch (freq_in) {
-               case 12000000:
-                       /* PLL enabled, active mode */
-                       hppllctl |= TWL6040_MCLK_12000KHZ |
-                                   TWL6040_HPLLENA;
-                       break;
-               case 19200000:
                        /*
-                        * PLL disabled
-                        * (enable PLL if MCLK jitter quality
-                        *  doesn't meet specification)
+                        * enable clock slicer to ensure input waveform is
+                        * square
                         */
-                       hppllctl |= TWL6040_MCLK_19200KHZ;
-                       break;
-               case 26000000:
-                       /* PLL enabled, active mode */
-                       hppllctl |= TWL6040_MCLK_26000KHZ |
-                                   TWL6040_HPLLENA;
-                       break;
-               case 38400000:
-                       /* PLL enabled, active mode */
-                       hppllctl |= TWL6040_MCLK_38400KHZ |
-                                   TWL6040_HPLLENA;
-                       break;
-               default:
-                       dev_err(twl6040->dev,
-                               "freq_in %d not supported\n", freq_in);
-                       ret = -EINVAL;
-                       goto pll_out;
-               }
+                       hppllctl |= TWL6040_HPLLSQRENA;
 
-               /* enable clock slicer to ensure input waveform is square */
-               hppllctl |= TWL6040_HPLLSQRENA;
-
-               twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
-               usleep_range(500, 700);
-               lppllctl |= TWL6040_HPLLSEL;
-               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-               lppllctl &= ~TWL6040_LPLLENA;
-               twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+                       twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+                                         hppllctl);
+                       usleep_range(500, 700);
+                       lppllctl |= TWL6040_HPLLSEL;
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
+                       lppllctl &= ~TWL6040_LPLLENA;
+                       twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+                                         lppllctl);
+               }
                break;
        default:
                dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
@@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
        }
 
        twl6040->sysclk = freq_out;
+       twl6040->mclk = freq_in;
        twl6040->pll = pll_id;
 
 pll_out:
index 91c4f25e0e558fe20a04ae10e1554d98f0f3fff9..febc90cdef7ea4a97885f7cc88b36ceb543e8b7e 100644 (file)
@@ -36,15 +36,6 @@ static DEFINE_MUTEX(ucb1x00_mutex);
 static LIST_HEAD(ucb1x00_drivers);
 static LIST_HEAD(ucb1x00_devices);
 
-static struct mcp_device_id ucb1x00_id[] = {
-       { "ucb1x00", 0 },  /* auto-detection */
-       { "ucb1200", UCB_ID_1200 },
-       { "ucb1300", UCB_ID_1300 },
-       { "tc35143", UCB_ID_TC35143 },
-       { }
-};
-MODULE_DEVICE_TABLE(mcp, ucb1x00_id);
-
 /**
  *     ucb1x00_io_set_dir - set IO direction
  *     @ucb: UCB1x00 structure describing chip
@@ -157,16 +148,22 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
 {
        struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
        unsigned long flags;
+       unsigned old, mask = 1 << offset;
 
        spin_lock_irqsave(&ucb->io_lock, flags);
-       ucb->io_dir |= (1 << offset);
-       ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
-
+       old = ucb->io_out;
        if (value)
-               ucb->io_out |= 1 << offset;
+               ucb->io_out |= mask;
        else
-               ucb->io_out &= ~(1 << offset);
-       ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+               ucb->io_out &= ~mask;
+
+       if (old != ucb->io_out)
+               ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+
+       if (!(ucb->io_dir & mask)) {
+               ucb->io_dir |= mask;
+               ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+       }
        spin_unlock_irqrestore(&ucb->io_lock, flags);
 
        return 0;
@@ -536,33 +533,17 @@ static struct class ucb1x00_class = {
 
 static int ucb1x00_probe(struct mcp *mcp)
 {
-       const struct mcp_device_id *mid;
        struct ucb1x00 *ucb;
        struct ucb1x00_driver *drv;
-       struct ucb1x00_plat_data *pdata;
        unsigned int id;
        int ret = -ENODEV;
        int temp;
 
        mcp_enable(mcp);
        id = mcp_reg_read(mcp, UCB_ID);
-       mid = mcp_get_device_id(mcp);
 
-       if (mid && mid->driver_data) {
-               if (id != mid->driver_data) {
-                       printk(KERN_WARNING "%s wrong ID %04x found: %04x\n",
-                               mid->name, (unsigned int) mid->driver_data, id);
-                       goto err_disable;
-               }
-       } else {
-               mid = &ucb1x00_id[1];
-               while (mid->driver_data) {
-                       if (id == mid->driver_data)
-                               break;
-                       mid++;
-               }
-               printk(KERN_WARNING "%s ID not found: %04x\n",
-                       ucb1x00_id[0].name, id);
+       if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
+               printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
                goto err_disable;
        }
 
@@ -571,28 +552,28 @@ static int ucb1x00_probe(struct mcp *mcp)
        if (!ucb)
                goto err_disable;
 
-       pdata = mcp->attached_device.platform_data;
+
        ucb->dev.class = &ucb1x00_class;
        ucb->dev.parent = &mcp->attached_device;
-       dev_set_name(&ucb->dev, mid->name);
+       dev_set_name(&ucb->dev, "ucb1x00");
 
        spin_lock_init(&ucb->lock);
        spin_lock_init(&ucb->io_lock);
        sema_init(&ucb->adc_sem, 1);
 
-       ucb->id  = mid;
+       ucb->id  = id;
        ucb->mcp = mcp;
        ucb->irq = ucb1x00_detect_irq(ucb);
        if (ucb->irq == NO_IRQ) {
-               printk(KERN_ERR "%s: IRQ probe failed\n", mid->name);
+               printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
                ret = -ENODEV;
                goto err_free;
        }
 
        ucb->gpio.base = -1;
-       if (pdata && (pdata->gpio_base >= 0)) {
+       if (mcp->gpio_base != 0) {
                ucb->gpio.label = dev_name(&ucb->dev);
-               ucb->gpio.base = pdata->gpio_base;
+               ucb->gpio.base = mcp->gpio_base;
                ucb->gpio.ngpio = 10;
                ucb->gpio.set = ucb1x00_gpio_set;
                ucb->gpio.get = ucb1x00_gpio_get;
@@ -605,10 +586,10 @@ static int ucb1x00_probe(struct mcp *mcp)
                dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
 
        ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
-                         mid->name, ucb);
+                         "UCB1x00", ucb);
        if (ret) {
-               printk(KERN_ERR "%s: unable to grab irq%d: %d\n",
-                       mid->name, ucb->irq, ret);
+               printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
+                       ucb->irq, ret);
                goto err_gpio;
        }
 
@@ -712,6 +693,7 @@ static int ucb1x00_resume(struct mcp *mcp)
        struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
        struct ucb1x00_dev *dev;
 
+       ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
        ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
        mutex_lock(&ucb1x00_mutex);
        list_for_each_entry(dev, &ucb->devs, dev_node) {
@@ -730,7 +712,6 @@ static struct mcp_driver ucb1x00_driver = {
        .remove         = ucb1x00_remove,
        .suspend        = ucb1x00_suspend,
        .resume         = ucb1x00_resume,
-       .id_table       = ucb1x00_id,
 };
 
 static int __init ucb1x00_init(void)
index 40ec3c118868d7f02e104d2ed10e2f766840a0f4..63a3cbdfa3f33a85a146f34fff7459cc6b46c17a 100644 (file)
@@ -47,7 +47,6 @@ struct ucb1x00_ts {
        u16                     x_res;
        u16                     y_res;
 
-       unsigned int            restart:1;
        unsigned int            adcsync:1;
 };
 
@@ -207,15 +206,17 @@ static int ucb1x00_thread(void *_ts)
 {
        struct ucb1x00_ts *ts = _ts;
        DECLARE_WAITQUEUE(wait, current);
+       bool frozen, ignore = false;
        int valid = 0;
 
        set_freezable();
        add_wait_queue(&ts->irq_wait, &wait);
-       while (!kthread_should_stop()) {
+       while (!kthread_freezable_should_stop(&frozen)) {
                unsigned int x, y, p;
                signed long timeout;
 
-               ts->restart = 0;
+               if (frozen)
+                       ignore = true;
 
                ucb1x00_adc_enable(ts->ucb);
 
@@ -258,7 +259,7 @@ static int ucb1x00_thread(void *_ts)
                         * space.  We therefore leave it to user space
                         * to do any filtering they please.
                         */
-                       if (!ts->restart) {
+                       if (!ignore) {
                                ucb1x00_ts_evt_add(ts, p, x, y);
                                valid = 1;
                        }
@@ -267,8 +268,6 @@ static int ucb1x00_thread(void *_ts)
                        timeout = HZ / 100;
                }
 
-               try_to_freeze();
-
                schedule_timeout(timeout);
        }
 
@@ -340,26 +339,6 @@ static void ucb1x00_ts_close(struct input_dev *idev)
        ucb1x00_disable(ts->ucb);
 }
 
-#ifdef CONFIG_PM
-static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
-{
-       struct ucb1x00_ts *ts = dev->priv;
-
-       if (ts->rtask != NULL) {
-               /*
-                * Restart the TS thread to ensure the
-                * TS interrupt mode is set up again
-                * after sleep.
-                */
-               ts->restart = 1;
-               wake_up(&ts->irq_wait);
-       }
-       return 0;
-}
-#else
-#define ucb1x00_ts_resume NULL
-#endif
-
 
 /*
  * Initialisation.
@@ -382,7 +361,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
        ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
 
        idev->name       = "Touchscreen panel";
-       idev->id.product = ts->ucb->id->driver_data;
+       idev->id.product = ts->ucb->id;
        idev->open       = ucb1x00_ts_open;
        idev->close      = ucb1x00_ts_close;
 
@@ -425,7 +404,6 @@ static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
 static struct ucb1x00_driver ucb1x00_ts_driver = {
        .add            = ucb1x00_ts_add,
        .remove         = ucb1x00_ts_remove,
-       .resume         = ucb1x00_ts_resume,
 };
 
 static int __init ucb1x00_ts_init(void)
index 6a1a092db1461f3413defc6d11ca74ce68b9d282..c7795096d43bc22c4450ba8b6c88a88a9be1c19e 100644 (file)
@@ -2,24 +2,14 @@
 # Misc strange devices
 #
 
-# This one has to live outside of the MISC_DEVICES conditional,
-# because it may be selected by drivers/platform/x86/hp_accel.
+menu "Misc devices"
+
 config SENSORS_LIS3LV02D
        tristate
        depends on INPUT
        select INPUT_POLLDEV
        default n
 
-menuconfig MISC_DEVICES
-       bool "Misc devices"
-       ---help---
-         Say Y here to get to see options for device drivers from various
-         different categories. This option alone does not add any kernel code.
-
-         If you say N, all options in this submenu will be skipped and disabled.
-
-if MISC_DEVICES
-
 config AD525X_DPOT
        tristate "Analog Devices Digital Potentiometers"
        depends on (I2C || SPI) && SYSFS
@@ -516,5 +506,4 @@ source "drivers/misc/ti-st/Kconfig"
 source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
-
-endif # MISC_DEVICES
+endmenu
index 778fc3fdfb9b98f9cee22b1f38748474658654f9..5484301d57d9f63ed8c56b5fcb49f5ae91de98b8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/ioport.h>
 #include <linux/c2port.h>
 
 #define DATA_PORT      0x325
index eb5cd28bc6d8d7a1917f7f15d82b267b692315f8..a2d25e4857e31387fc0457b5a47efc4c1e438bd0 100644 (file)
@@ -513,7 +513,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
         * transaction, and then put it under external control
         */
        memset(&config, 0, sizeof(config));
-       config.direction = DMA_TO_DEVICE;
+       config.direction = DMA_MEM_TO_DEV;
        config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        config.dst_maxburst = fpga_fifo_size(priv->regs) / 2 / 4;
        ret = chan->device->device_control(chan, DMA_SLAVE_CONFIG,
index 68cd05b6d829d1f3b7fa15f256f78b3bb6f82f82..85cc7710193c7bfe224bfa08f3a8b1df8f66295f 100644 (file)
@@ -245,6 +245,7 @@ static int __devinit cb710_probe(struct pci_dev *pdev,
        if (err)
                return err;
 
+       spin_lock_init(&chip->irq_lock);
        chip->pdev = pdev;
        chip->iobase = pcim_iomap_table(pdev)[0];
 
index bc685bfc4c33aaacf89a5dc7205943bd69f14f8d..87a390de054ce5fe8437fbe225700b4ba6849fd9 100644 (file)
@@ -262,7 +262,7 @@ static void __init reset_all_timers(void)
  * In other cases (such as with VSAless OpenFirmware), the system firmware
  * leaves timers available for us to use.
  */
-static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
 {
        struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
        unsigned long flags;
index 150cd7061b808019d4a775ab29fc287558d7508e..28adefe70f96274c93198ee50acc9ee65adec1ae 100644 (file)
@@ -354,6 +354,7 @@ static void lkdtm_do_action(enum ctype which)
 static void lkdtm_handler(void)
 {
        unsigned long flags;
+       bool do_it = false;
 
        spin_lock_irqsave(&count_lock, flags);
        count--;
@@ -361,10 +362,13 @@ static void lkdtm_handler(void)
                        cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
 
        if (count == 0) {
-               lkdtm_do_action(cptype);
+               do_it = true;
                count = cpoint_count;
        }
        spin_unlock_irqrestore(&count_lock, flags);
+
+       if (do_it)
+               lkdtm_do_action(cptype);
 }
 
 static int lkdtm_register_cpoint(enum cname which)
index cd41d403c9dfa1ffbc8f46563ba8017d35e2c327..cb56e270da111ba68c11625133804032f9f0831e 100644 (file)
@@ -314,7 +314,7 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)
  * fear that guest will need it. Host may reject some pages, we need to
  * check the return value and maybe submit a different page.
  */
-static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
+static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
                                     unsigned int *hv_status)
 {
        unsigned long status, dummy;
@@ -322,17 +322,17 @@ static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
 
        pfn32 = (u32)pfn;
        if (pfn32 != pfn)
-               return false;
+               return -1;
 
        STATS_INC(b->stats.lock);
 
        *hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy);
        if (vmballoon_check_status(b, status))
-               return true;
+               return 0;
 
        pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
        STATS_INC(b->stats.lock_fail);
-       return false;
+       return 1;
 }
 
 /*
@@ -411,7 +411,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
        struct page *page;
        gfp_t flags;
        unsigned int hv_status;
-       bool locked = false;
+       int locked;
        flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
 
        do {
@@ -431,7 +431,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
 
                /* inform monitor */
                locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
-               if (!locked) {
+               if (locked > 0) {
                        STATS_INC(b->stats.refused_alloc);
 
                        if (hv_status == VMW_BALLOON_ERROR_RESET ||
@@ -449,7 +449,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
                        if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
                                return -EIO;
                }
-       } while (!locked);
+       } while (locked != 0);
 
        /* track allocated page */
        list_add(&page->lru, &b->pages);
index 0cad48a284a85366e6ad72aa607fd6d9f3da59ce..c6a383d0244dd6eafa8c87b290c54fac27b3640e 100644 (file)
@@ -1694,6 +1694,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)
 
                md->power_ro_lock.show = power_ro_lock_show;
                md->power_ro_lock.store = power_ro_lock_store;
+               sysfs_attr_init(&md->power_ro_lock.attr);
                md->power_ro_lock.attr.mode = mode;
                md->power_ro_lock.attr.name =
                                        "ro_lock_until_next_power_on";
index f545a3e6eb80587fa3995bbf1413e68b205c9cdf..690255c7d4dcc8c407e7b0852216edab75f4ef31 100644 (file)
@@ -290,8 +290,11 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
 static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
                 bool is_first_req)
 {
-       if (host->ops->pre_req)
+       if (host->ops->pre_req) {
+               mmc_host_clk_hold(host);
                host->ops->pre_req(host, mrq, is_first_req);
+               mmc_host_clk_release(host);
+       }
 }
 
 /**
@@ -306,8 +309,11 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
 static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
                         int err)
 {
-       if (host->ops->post_req)
+       if (host->ops->post_req) {
+               mmc_host_clk_hold(host);
                host->ops->post_req(host, mrq, err);
+               mmc_host_clk_release(host);
+       }
 }
 
 /**
@@ -620,7 +626,9 @@ int mmc_host_enable(struct mmc_host *host)
                int err;
 
                host->en_dis_recurs = 1;
+               mmc_host_clk_hold(host);
                err = host->ops->enable(host);
+               mmc_host_clk_release(host);
                host->en_dis_recurs = 0;
 
                if (err) {
@@ -640,7 +648,9 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy)
                int err;
 
                host->en_dis_recurs = 1;
+               mmc_host_clk_hold(host);
                err = host->ops->disable(host, lazy);
+               mmc_host_clk_release(host);
                host->en_dis_recurs = 0;
 
                if (err < 0) {
@@ -1121,6 +1131,10 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
                 * might not allow this operation
                 */
                voltage = regulator_get_voltage(supply);
+
+               if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE)
+                       min_uV = max_uV = voltage;
+
                if (voltage < 0)
                        result = voltage;
                else if (voltage < min_uV || voltage > max_uV)
@@ -1203,8 +1217,11 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11
 
        host->ios.signal_voltage = signal_voltage;
 
-       if (host->ops->start_signal_voltage_switch)
+       if (host->ops->start_signal_voltage_switch) {
+               mmc_host_clk_hold(host);
                err = host->ops->start_signal_voltage_switch(host, &host->ios);
+               mmc_host_clk_release(host);
+       }
 
        return err;
 }
@@ -1239,6 +1256,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
        int err = 0;
 
        card = host->card;
+       mmc_claim_host(host);
 
        /*
         * Send power notify command only if card
@@ -1269,6 +1287,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
                /* Set the card state to no notification after the poweroff */
                card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
        }
+       mmc_release_host(host);
 }
 
 /*
@@ -1327,12 +1346,28 @@ static void mmc_power_up(struct mmc_host *host)
 
 void mmc_power_off(struct mmc_host *host)
 {
+       int err = 0;
        mmc_host_clk_hold(host);
 
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
-       mmc_poweroff_notify(host);
+       /*
+        * For eMMC 4.5 device send AWAKE command before
+        * POWER_OFF_NOTIFY command, because in sleep state
+        * eMMC 4.5 devices respond to only RESET and AWAKE cmd
+        */
+       if (host->card && mmc_card_is_sleep(host->card) &&
+           host->bus_ops->resume) {
+               err = host->bus_ops->resume(host);
+
+               if (!err)
+                       mmc_poweroff_notify(host);
+               else
+                       pr_warning("%s: error %d during resume "
+                                  "(continue with poweroff sequence)\n",
+                                  mmc_hostname(host), err);
+       }
 
        /*
         * Reset ocr mask to be the highest possible voltage supported for
@@ -2386,12 +2421,6 @@ int mmc_suspend_host(struct mmc_host *host)
                 */
                if (mmc_try_claim_host(host)) {
                        if (host->bus_ops->suspend) {
-                               /*
-                                * For eMMC 4.5 device send notify command
-                                * before sleep, because in sleep state eMMC 4.5
-                                * devices respond to only RESET and AWAKE cmd
-                                */
-                               mmc_poweroff_notify(host);
                                err = host->bus_ops->suspend(host);
                        }
                        mmc_do_release_host(host);
index fb8a5cd2e4a1e87bfab9439f8c9e44a3d75ee4b4..08a7852ade448a126d56d0034ba9b0965206b7a5 100644 (file)
 
 int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
-
-#ifdef CONFIG_MMC_CLKGATE
-void mmc_host_clk_hold(struct mmc_host *host);
-void mmc_host_clk_release(struct mmc_host *host);
-unsigned int mmc_host_clk_rate(struct mmc_host *host);
-
-#else
-static inline void mmc_host_clk_hold(struct mmc_host *host)
-{
-}
-
-static inline void mmc_host_clk_release(struct mmc_host *host)
-{
-}
-
-static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
-{
-       return host->ios.clock;
-}
-#endif
-
 void mmc_host_deeper_disable(struct work_struct *work);
 
 #endif
index 59b9ba52e66a1fb420ae26f7da3350b0c8d1d592..a48066344fa87316997b0bcca501d0842ea7e8a1 100644 (file)
@@ -376,7 +376,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
        }
 
        card->ext_csd.raw_hc_erase_gap_size =
-               ext_csd[EXT_CSD_PARTITION_ATTRIBUTE];
+               ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
        card->ext_csd.raw_sec_trim_mult =
                ext_csd[EXT_CSD_SEC_TRIM_MULT];
        card->ext_csd.raw_sec_erase_mult =
@@ -551,7 +551,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
                goto out;
 
        /* only compare read only fields */
-       err = (!(card->ext_csd.raw_partition_support ==
+       err = !((card->ext_csd.raw_partition_support ==
                        bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) &&
                (card->ext_csd.raw_erased_mem_count ==
                        bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) &&
@@ -1006,7 +1006,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                        err = mmc_select_hs200(card);
                else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                        EXT_CSD_HS_TIMING, 1, 0);
+                                        EXT_CSD_HS_TIMING, 1,
+                                        card->ext_csd.generic_cmd6_time);
 
                if (err && err != -EBADMSG)
                        goto free_card;
@@ -1116,7 +1117,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         * Activate wide bus and DDR (if supported).
         */
        if (!mmc_card_hs200(card) &&
-           (card->csd.mmca_vsn >= CSD_SPEC_VER_3) &&
+           (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
            (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
                static unsigned ext_csd_bits[][2] = {
                        { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
@@ -1315,11 +1316,13 @@ static int mmc_suspend(struct mmc_host *host)
        BUG_ON(!host->card);
 
        mmc_claim_host(host);
-       if (mmc_card_can_sleep(host))
+       if (mmc_card_can_sleep(host)) {
                err = mmc_card_sleep(host);
-       else if (!mmc_host_is_spi(host))
+               if (!err)
+                       mmc_card_set_sleep(host->card);
+       } else if (!mmc_host_is_spi(host))
                mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
+       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
        mmc_release_host(host);
 
        return err;
@@ -1339,7 +1342,11 @@ static int mmc_resume(struct mmc_host *host)
        BUG_ON(!host->card);
 
        mmc_claim_host(host);
-       err = mmc_init_card(host, host->ocr, host->card);
+       if (mmc_card_is_sleep(host->card)) {
+               err = mmc_card_awake(host);
+               mmc_card_clr_sleep(host->card);
+       } else
+               err = mmc_init_card(host, host->ocr, host->card);
        mmc_release_host(host);
 
        return err;
@@ -1349,7 +1356,8 @@ static int mmc_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
+       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+       mmc_card_clr_sleep(host->card);
        mmc_claim_host(host);
        ret = mmc_init_card(host, host->ocr, host->card);
        mmc_release_host(host);
index c63ad03c29c7ff61065ec64d66ae28eeb90884cc..5017f9354ce28af6a67418d1ce0a2c438ed07edd 100644 (file)
@@ -451,9 +451,11 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
         * information and let the hardware specific code
         * return what is possible given the options
         */
+       mmc_host_clk_hold(card->host);
        drive_strength = card->host->ops->select_drive_strength(
                card->sw_caps.uhs_max_dtr,
                host_drv_type, card_drv_type);
+       mmc_host_clk_release(card->host);
 
        err = mmc_sd_switch(card, 1, 2, drive_strength, status);
        if (err)
@@ -660,9 +662,12 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
                goto out;
 
        /* SPI mode doesn't define CMD19 */
-       if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
+       if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) {
+               mmc_host_clk_hold(card->host);
                err = card->host->ops->execute_tuning(card->host,
                                                      MMC_SEND_TUNING_BLOCK);
+               mmc_host_clk_release(card->host);
+       }
 
 out:
        kfree(status);
@@ -850,8 +855,11 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
        if (!reinit) {
                int ro = -1;
 
-               if (host->ops->get_ro)
+               if (host->ops->get_ro) {
+                       mmc_host_clk_hold(card->host);
                        ro = host->ops->get_ro(host);
+                       mmc_host_clk_release(card->host);
+               }
 
                if (ro < 0) {
                        pr_warning("%s: host does not "
@@ -967,8 +975,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
                 * Since initialization is now complete, enable preset
                 * value registers for UHS-I cards.
                 */
-               if (host->ops->enable_preset_value)
+               if (host->ops->enable_preset_value) {
+                       mmc_host_clk_hold(card->host);
                        host->ops->enable_preset_value(host, true);
+                       mmc_host_clk_release(card->host);
+               }
        } else {
                /*
                 * Attempt to change to high-speed (if supported)
@@ -1151,8 +1162,11 @@ int mmc_attach_sd(struct mmc_host *host)
                return err;
 
        /* Disable preset value enable if already set since last time */
-       if (host->ops->enable_preset_value)
+       if (host->ops->enable_preset_value) {
+               mmc_host_clk_hold(host);
                host->ops->enable_preset_value(host, false);
+               mmc_host_clk_release(host);
+       }
 
        err = mmc_send_app_op_cond(host, 0, &ocr);
        if (err)
index bd7bacc950dc03b386d2a6907aff047f870bc14d..12cde6ee17f50732ac5cd05f6843928abf87d0c9 100644 (file)
@@ -98,10 +98,11 @@ fail:
        return ret;
 }
 
-static int sdio_read_cccr(struct mmc_card *card)
+static int sdio_read_cccr(struct mmc_card *card, u32 ocr)
 {
        int ret;
        int cccr_vsn;
+       int uhs = ocr & R4_18V_PRESENT;
        unsigned char data;
        unsigned char speed;
 
@@ -149,7 +150,7 @@ static int sdio_read_cccr(struct mmc_card *card)
                card->scr.sda_spec3 = 0;
                card->sw_caps.sd3_bus_mode = 0;
                card->sw_caps.sd3_drv_type = 0;
-               if (cccr_vsn >= SDIO_CCCR_REV_3_00) {
+               if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) {
                        card->scr.sda_spec3 = 1;
                        ret = mmc_io_rw_direct(card, 0, 0,
                                SDIO_CCCR_UHS, 0, &data);
@@ -712,7 +713,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Read the common registers.
         */
-       err = sdio_read_cccr(card);
+       err = sdio_read_cccr(card, ocr);
        if (err)
                goto remove;
 
index 68f81b9ee0fbe4eb10c962b0ddb088ee11f8e213..f573e7f9f74020dae69aa3ba861bbcadf66ffc4e 100644 (file)
@@ -146,15 +146,21 @@ static int sdio_irq_thread(void *_host)
                }
 
                set_current_state(TASK_INTERRUPTIBLE);
-               if (host->caps & MMC_CAP_SDIO_IRQ)
+               if (host->caps & MMC_CAP_SDIO_IRQ) {
+                       mmc_host_clk_hold(host);
                        host->ops->enable_sdio_irq(host, 1);
+                       mmc_host_clk_release(host);
+               }
                if (!kthread_should_stop())
                        schedule_timeout(period);
                set_current_state(TASK_RUNNING);
        } while (!kthread_should_stop());
 
-       if (host->caps & MMC_CAP_SDIO_IRQ)
+       if (host->caps & MMC_CAP_SDIO_IRQ) {
+               mmc_host_clk_hold(host);
                host->ops->enable_sdio_irq(host, 0);
+               mmc_host_clk_release(host);
+       }
 
        pr_debug("%s: IRQ thread exiting with code %d\n",
                 mmc_hostname(host), ret);
index cf444b0ca2cc8144367c8232a3075cd006e7d6ae..00fcbed1afd28b416bff41ec30c34ec0f69b1d91 100644 (file)
@@ -477,7 +477,6 @@ config MMC_SDHI
 config MMC_CB710
        tristate "ENE CB710 MMC/SD Interface support"
        depends on PCI
-       select MISC_DEVICES
        select CB710_CORE
        help
          This option enables support for MMC/SD part of ENE CB710/720 Flash
index a7ee5027146528aafc6b18fa8c2e55f32e32a174..6985cdb0bb26e641fb340c0218d331e48844614a 100644 (file)
@@ -823,6 +823,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
        struct scatterlist              *sg;
        unsigned int                    i;
        enum dma_data_direction         direction;
+       enum dma_transfer_direction     slave_dirn;
        unsigned int                    sglen;
        u32 iflags;
 
@@ -860,16 +861,19 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
        if (host->caps.has_dma)
                atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN);
 
-       if (data->flags & MMC_DATA_READ)
+       if (data->flags & MMC_DATA_READ) {
                direction = DMA_FROM_DEVICE;
-       else
+               slave_dirn = DMA_DEV_TO_MEM;
+       } else {
                direction = DMA_TO_DEVICE;
+               slave_dirn = DMA_MEM_TO_DEV;
+       }
 
        sglen = dma_map_sg(chan->device->dev, data->sg,
                        data->sg_len, direction);
 
        desc = chan->device->device_prep_slave_sg(chan,
-                       data->sg, sglen, direction,
+                       data->sg, sglen, slave_dirn,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc)
                goto unmap_exit;
@@ -965,11 +969,14 @@ static void atmci_start_request(struct atmel_mci *host,
        host->data_status = 0;
 
        if (host->need_reset) {
+               iflags = atmci_readl(host, ATMCI_IMR);
+               iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB);
                atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
                atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
                atmci_writel(host, ATMCI_MR, host->mode_reg);
                if (host->caps.has_cfg_reg)
                        atmci_writel(host, ATMCI_CFG, host->cfg_reg);
+               atmci_writel(host, ATMCI_IER, iflags);
                host->need_reset = false;
        }
        atmci_writel(host, ATMCI_SDCR, slot->sdc_reg);
index 0e342793ff142f2f2616da2a6bce85542e9e4cf7..8bec1c36b159159593bcad0263f0bca2787d4b92 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/scatterlist.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
@@ -502,8 +501,14 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
                host->dir_status = DW_MCI_SEND_STATUS;
 
        if (dw_mci_submit_data_dma(host, data)) {
+               int flags = SG_MITER_ATOMIC;
+               if (host->data->flags & MMC_DATA_READ)
+                       flags |= SG_MITER_TO_SG;
+               else
+                       flags |= SG_MITER_FROM_SG;
+
+               sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
                host->sg = data->sg;
-               host->pio_offset = 0;
                host->part_buf_start = 0;
                host->part_buf_count = 0;
 
@@ -972,6 +977,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                 * generates a block interrupt, hence setting
                                 * the scatter-gather pointer to NULL.
                                 */
+                               sg_miter_stop(&host->sg_miter);
                                host->sg = NULL;
                                ctrl = mci_readl(host, CTRL);
                                ctrl |= SDMMC_CTRL_FIFO_RESET;
@@ -1311,54 +1317,44 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
 
 static void dw_mci_read_data_pio(struct dw_mci *host)
 {
-       struct scatterlist *sg = host->sg;
-       void *buf = sg_virt(sg);
-       unsigned int offset = host->pio_offset;
+       struct sg_mapping_iter *sg_miter = &host->sg_miter;
+       void *buf;
+       unsigned int offset;
        struct mmc_data *data = host->data;
        int shift = host->data_shift;
        u32 status;
        unsigned int nbytes = 0, len;
+       unsigned int remain, fcnt;
 
        do {
-               len = host->part_buf_count +
-                       (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
-               if (offset + len <= sg->length) {
+               if (!sg_miter_next(sg_miter))
+                       goto done;
+
+               host->sg = sg_miter->__sg;
+               buf = sg_miter->addr;
+               remain = sg_miter->length;
+               offset = 0;
+
+               do {
+                       fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS))
+                                       << shift) + host->part_buf_count;
+                       len = min(remain, fcnt);
+                       if (!len)
+                               break;
                        dw_mci_pull_data(host, (void *)(buf + offset), len);
-
                        offset += len;
                        nbytes += len;
-
-                       if (offset == sg->length) {
-                               flush_dcache_page(sg_page(sg));
-                               host->sg = sg = sg_next(sg);
-                               if (!sg)
-                                       goto done;
-
-                               offset = 0;
-                               buf = sg_virt(sg);
-                       }
-               } else {
-                       unsigned int remaining = sg->length - offset;
-                       dw_mci_pull_data(host, (void *)(buf + offset),
-                                        remaining);
-                       nbytes += remaining;
-
-                       flush_dcache_page(sg_page(sg));
-                       host->sg = sg = sg_next(sg);
-                       if (!sg)
-                               goto done;
-
-                       offset = len - remaining;
-                       buf = sg_virt(sg);
-                       dw_mci_pull_data(host, buf, offset);
-                       nbytes += offset;
-               }
+                       remain -= len;
+               } while (remain);
+               sg_miter->consumed = offset;
 
                status = mci_readl(host, MINTSTS);
                mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
                if (status & DW_MCI_DATA_ERROR_FLAGS) {
                        host->data_status = status;
                        data->bytes_xfered += nbytes;
+                       sg_miter_stop(sg_miter);
+                       host->sg = NULL;
                        smp_wmb();
 
                        set_bit(EVENT_DATA_ERROR, &host->pending_events);
@@ -1367,65 +1363,66 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
                        return;
                }
        } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
-       host->pio_offset = offset;
        data->bytes_xfered += nbytes;
+
+       if (!remain) {
+               if (!sg_miter_next(sg_miter))
+                       goto done;
+               sg_miter->consumed = 0;
+       }
+       sg_miter_stop(sg_miter);
        return;
 
 done:
        data->bytes_xfered += nbytes;
+       sg_miter_stop(sg_miter);
+       host->sg = NULL;
        smp_wmb();
        set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
 }
 
 static void dw_mci_write_data_pio(struct dw_mci *host)
 {
-       struct scatterlist *sg = host->sg;
-       void *buf = sg_virt(sg);
-       unsigned int offset = host->pio_offset;
+       struct sg_mapping_iter *sg_miter = &host->sg_miter;
+       void *buf;
+       unsigned int offset;
        struct mmc_data *data = host->data;
        int shift = host->data_shift;
        u32 status;
        unsigned int nbytes = 0, len;
+       unsigned int fifo_depth = host->fifo_depth;
+       unsigned int remain, fcnt;
 
        do {
-               len = ((host->fifo_depth -
-                       SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift)
-                       - host->part_buf_count;
-               if (offset + len <= sg->length) {
+               if (!sg_miter_next(sg_miter))
+                       goto done;
+
+               host->sg = sg_miter->__sg;
+               buf = sg_miter->addr;
+               remain = sg_miter->length;
+               offset = 0;
+
+               do {
+                       fcnt = ((fifo_depth -
+                                SDMMC_GET_FCNT(mci_readl(host, STATUS)))
+                                       << shift) - host->part_buf_count;
+                       len = min(remain, fcnt);
+                       if (!len)
+                               break;
                        host->push_data(host, (void *)(buf + offset), len);
-
                        offset += len;
                        nbytes += len;
-                       if (offset == sg->length) {
-                               host->sg = sg = sg_next(sg);
-                               if (!sg)
-                                       goto done;
-
-                               offset = 0;
-                               buf = sg_virt(sg);
-                       }
-               } else {
-                       unsigned int remaining = sg->length - offset;
-
-                       host->push_data(host, (void *)(buf + offset),
-                                       remaining);
-                       nbytes += remaining;
-
-                       host->sg = sg = sg_next(sg);
-                       if (!sg)
-                               goto done;
-
-                       offset = len - remaining;
-                       buf = sg_virt(sg);
-                       host->push_data(host, (void *)buf, offset);
-                       nbytes += offset;
-               }
+                       remain -= len;
+               } while (remain);
+               sg_miter->consumed = offset;
 
                status = mci_readl(host, MINTSTS);
                mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
                if (status & DW_MCI_DATA_ERROR_FLAGS) {
                        host->data_status = status;
                        data->bytes_xfered += nbytes;
+                       sg_miter_stop(sg_miter);
+                       host->sg = NULL;
 
                        smp_wmb();
 
@@ -1435,12 +1432,20 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
                        return;
                }
        } while (status & SDMMC_INT_TXDR); /* if TXDR write again */
-       host->pio_offset = offset;
        data->bytes_xfered += nbytes;
+
+       if (!remain) {
+               if (!sg_miter_next(sg_miter))
+                       goto done;
+               sg_miter->consumed = 0;
+       }
+       sg_miter_stop(sg_miter);
        return;
 
 done:
        data->bytes_xfered += nbytes;
+       sg_miter_stop(sg_miter);
+       host->sg = NULL;
        smp_wmb();
        set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
 }
@@ -1643,6 +1648,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
                                 * block interrupt, hence setting the
                                 * scatter-gather pointer to NULL.
                                 */
+                               sg_miter_stop(&host->sg_miter);
                                host->sg = NULL;
 
                                ctrl = mci_readl(host, CTRL);
index ece03b491c7db824fe7a698353f2c14f9f0cb6d2..0d955ffaf44e2c3ec5961f966687da3e675819d9 100644 (file)
@@ -374,6 +374,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
        struct dma_chan *chan;
        struct dma_device *device;
        struct dma_async_tx_descriptor *desc;
+       enum dma_data_direction buffer_dirn;
        int nr_sg;
 
        /* Check if next job is already prepared */
@@ -387,10 +388,12 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
        }
 
        if (data->flags & MMC_DATA_READ) {
-               conf.direction = DMA_FROM_DEVICE;
+               conf.direction = DMA_DEV_TO_MEM;
+               buffer_dirn = DMA_FROM_DEVICE;
                chan = host->dma_rx_channel;
        } else {
-               conf.direction = DMA_TO_DEVICE;
+               conf.direction = DMA_MEM_TO_DEV;
+               buffer_dirn = DMA_TO_DEVICE;
                chan = host->dma_tx_channel;
        }
 
@@ -403,7 +406,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
                return -EINVAL;
 
        device = chan->device;
-       nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction);
+       nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
        if (nr_sg == 0)
                return -EINVAL;
 
@@ -426,7 +429,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
  unmap_exit:
        if (!next)
                dmaengine_terminate_all(chan);
-       dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
+       dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
        return -ENOMEM;
 }
 
index 7088b40f95797b00172edf0bdf4f50437b18947f..4184b7946bbf34fd459c671a921ae6baf659e4d2 100644 (file)
@@ -218,6 +218,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
        unsigned int blksz = data->blksz;
        unsigned int datasize = nob * blksz;
        struct scatterlist *sg;
+       enum dma_transfer_direction slave_dirn;
        int i, nents;
 
        if (data->flags & MMC_DATA_STREAM)
@@ -240,10 +241,13 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
                }
        }
 
-       if (data->flags & MMC_DATA_READ)
+       if (data->flags & MMC_DATA_READ) {
                host->dma_dir = DMA_FROM_DEVICE;
-       else
+               slave_dirn = DMA_DEV_TO_MEM;
+       } else {
                host->dma_dir = DMA_TO_DEVICE;
+               slave_dirn = DMA_MEM_TO_DEV;
+       }
 
        nents = dma_map_sg(host->dma->device->dev, data->sg,
                                     data->sg_len,  host->dma_dir);
@@ -251,7 +255,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
                return -EINVAL;
 
        host->desc = host->dma->device->device_prep_slave_sg(host->dma,
-               data->sg, data->sg_len, host->dma_dir,
+               data->sg, data->sg_len, slave_dirn,
                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
        if (!host->desc) {
index 4e2e019dd5c94e02a8a6b54b413dcf2e162e7777..382c835d217cf23372594b230dcd7923971288d5 100644 (file)
@@ -154,6 +154,7 @@ struct mxs_mmc_host {
        struct dma_chan                 *dmach;
        struct mxs_dma_data             dma_data;
        unsigned int                    dma_dir;
+       enum dma_transfer_direction     slave_dirn;
        u32                             ssp_pio_words[SSP_PIO_NUM];
 
        unsigned int                    version;
@@ -324,7 +325,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
        }
 
        desc = host->dmach->device->device_prep_slave_sg(host->dmach,
-                               sgl, sg_len, host->dma_dir, append);
+                               sgl, sg_len, host->slave_dirn, append);
        if (desc) {
                desc->callback = mxs_mmc_dma_irq_callback;
                desc->callback_param = host;
@@ -356,6 +357,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
        host->ssp_pio_words[1] = cmd0;
        host->ssp_pio_words[2] = cmd1;
        host->dma_dir = DMA_NONE;
+       host->slave_dirn = DMA_TRANS_NONE;
        desc = mxs_mmc_prep_dma(host, 0);
        if (!desc)
                goto out;
@@ -395,6 +397,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
        host->ssp_pio_words[1] = cmd0;
        host->ssp_pio_words[2] = cmd1;
        host->dma_dir = DMA_NONE;
+       host->slave_dirn = DMA_TRANS_NONE;
        desc = mxs_mmc_prep_dma(host, 0);
        if (!desc)
                goto out;
@@ -433,6 +436,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
        int i;
 
        unsigned short dma_data_dir, timeout;
+       enum dma_transfer_direction slave_dirn;
        unsigned int data_size = 0, log2_blksz;
        unsigned int blocks = data->blocks;
 
@@ -448,9 +452,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 
        if (data->flags & MMC_DATA_WRITE) {
                dma_data_dir = DMA_TO_DEVICE;
+               slave_dirn = DMA_MEM_TO_DEV;
                read = 0;
        } else {
                dma_data_dir = DMA_FROM_DEVICE;
+               slave_dirn = DMA_DEV_TO_MEM;
                read = BM_SSP_CTRL0_READ;
        }
 
@@ -510,6 +516,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
        host->ssp_pio_words[1] = cmd0;
        host->ssp_pio_words[2] = cmd1;
        host->dma_dir = DMA_NONE;
+       host->slave_dirn = DMA_TRANS_NONE;
        desc = mxs_mmc_prep_dma(host, 0);
        if (!desc)
                goto out;
@@ -518,6 +525,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
        WARN_ON(host->data != NULL);
        host->data = data;
        host->dma_dir = dma_data_dir;
+       host->slave_dirn = slave_dirn;
        desc = mxs_mmc_prep_dma(host, 1);
        if (!desc)
                goto out;
index ab66f2454dc48fbc5fe2d68fe51b1d2611de1f7c..1534b582c41990d0e824f705db98b2c97bfe3c83 100644 (file)
@@ -113,8 +113,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
                const int j = i * 2;
                u32 mask;
 
-               mask = mmc_vddrange_to_ocrmask(voltage_ranges[j],
-                                              voltage_ranges[j + 1]);
+               mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
+                                              be32_to_cpu(voltage_ranges[j + 1]));
                if (!mask) {
                        ret = -EINVAL;
                        dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
index ff4adc0180418578ff10594f3f80cb2c0564d756..5d876ff86f377b5ec5b1a77a6cfcafc1ffca59e3 100644 (file)
@@ -38,6 +38,23 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
        int base = reg & ~0x3;
        int shift = (reg & 0x3) * 8;
        u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
+
+       /*
+        * "DMA select" locates at offset 0x28 in SD specification, but on
+        * P5020 or P3041, it locates at 0x29.
+        */
+       if (reg == SDHCI_HOST_CONTROL) {
+               u32 dma_bits;
+
+               dma_bits = in_be32(host->ioaddr + reg);
+               /* DMA select is 22,23 bits in Protocol Control Register */
+               dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK;
+
+               /* fixup the result */
+               ret &= ~SDHCI_CTRL_DMA_MASK;
+               ret |= dma_bits;
+       }
+
        return ret;
 }
 
@@ -56,6 +73,21 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
 
 static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
 {
+       /*
+        * "DMA select" location is offset 0x28 in SD specification, but on
+        * P5020 or P3041, it's located at 0x29.
+        */
+       if (reg == SDHCI_HOST_CONTROL) {
+               u32 dma_bits;
+
+               /* DMA select is 22,23 bits in Protocol Control Register */
+               dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5;
+               clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5,
+                       dma_bits);
+               val &= ~SDHCI_CTRL_DMA_MASK;
+               val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK;
+       }
+
        /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
        if (reg == SDHCI_HOST_CONTROL)
                val &= ~ESDHC_HOST_CONTROL_RES;
index 7165e6a092742e82f9b7cf108ad9f034a1173304..6ebdc4010e7ccb46e6f1052357fcdaca5dc3ecc9 100644 (file)
@@ -250,7 +250,7 @@ static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
 
 static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
-       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD;
+       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
        return 0;
 }
 
index 03970bcb3495ee7f542a12fc118074635dcd78ff..c5c2a48bdd943166bff4e15ddf59718f3fbffa9a 100644 (file)
@@ -2,7 +2,7 @@
  * sdhci-pltfm.c Support for SDHCI platform devices
  * Copyright (c) 2009 Intel Corporation
  *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
  *
  * Authors: Xiaobo Xie <X.Xie@freescale.com>
@@ -71,6 +71,14 @@ void sdhci_get_of_property(struct platform_device *pdev)
                if (sdhci_of_wp_inverted(np))
                        host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
 
+               if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
+                       host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+
+               if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
+                   of_device_is_compatible(np, "fsl,p1010-esdhc") ||
+                   of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
+                       host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
                clk = of_get_property(np, "clock-frequency", &size);
                if (clk && size == sizeof(*clk) && *clk)
                        pltfm_host->clock = be32_to_cpup(clk);
index 4a2c5b2355f21d81887e0f92d7f3350c1c51f288..352d4797865b4a9b76d58781cf80117c680e17c2 100644 (file)
@@ -286,7 +286,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
        if (ret > 0) {
                host->dma_active = true;
                desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-                       DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                       DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        }
 
        if (desc) {
@@ -335,7 +335,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
        if (ret > 0) {
                host->dma_active = true;
                desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-                       DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                       DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        }
 
        if (desc) {
@@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        if (ret < 0)
                goto clean_up2;
 
-       mmc_add_host(mmc);
+       INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
 
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
@@ -1338,22 +1338,24 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        }
        ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
        if (ret) {
-               free_irq(irq[0], host);
                dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
-               goto clean_up3;
+               goto clean_up4;
        }
 
-       INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
-
-       mmc_detect_change(host->mmc, 0);
+       ret = mmc_add_host(mmc);
+       if (ret < 0)
+               goto clean_up5;
 
        dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
        dev_dbg(&pdev->dev, "chip ver H'%04x\n",
                sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
        return ret;
 
+clean_up5:
+       free_irq(irq[1], host);
+clean_up4:
+       free_irq(irq[0], host);
 clean_up3:
-       mmc_remove_host(mmc);
        pm_runtime_suspend(&pdev->dev);
 clean_up2:
        pm_runtime_disable(&pdev->dev);
index a95e6d901726031275066ca7b394fc9be7b6a96c..f96c536d130a287768c6317d1dfa9611d30297ac 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/mmc/tmio.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
-#include <linux/spinlock.h>
 #include <linux/scatterlist.h>
+#include <linux/spinlock.h>
 
 /* Definitions for values the CTRL_SDIO_STATUS register can take. */
 #define TMIO_SDIO_STAT_IOIRQ   0x0001
@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
 void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable);
 void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
 void tmio_mmc_release_dma(struct tmio_mmc_host *host);
+void tmio_mmc_abort_dma(struct tmio_mmc_host *host);
 #else
 static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
                               struct mmc_data *data)
@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
 static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
 {
 }
+
+static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
+{
+}
 #endif
 
 #ifdef CONFIG_PM
index 86f259cdfcbcbe620206cc1c479395759fb2b2ad..8253ec12003ed3c9001cdd7b8fed889179350d9b 100644 (file)
@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
 #endif
 }
 
+void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
+{
+       tmio_mmc_enable_dma(host, false);
+
+       if (host->chan_rx)
+               dmaengine_terminate_all(host->chan_rx);
+       if (host->chan_tx)
+               dmaengine_terminate_all(host->chan_tx);
+
+       tmio_mmc_enable_dma(host, true);
+}
+
 static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
 {
        struct scatterlist *sg = host->sg_ptr, *sg_tmp;
@@ -77,7 +89,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
        ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
        if (ret > 0)
                desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-                       DMA_FROM_DEVICE, DMA_CTRL_ACK);
+                       DMA_DEV_TO_MEM, DMA_CTRL_ACK);
 
        if (desc) {
                cookie = dmaengine_submit(desc);
@@ -158,7 +170,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
        ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
        if (ret > 0)
                desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-                       DMA_TO_DEVICE, DMA_CTRL_ACK);
+                       DMA_MEM_TO_DEV, DMA_CTRL_ACK);
 
        if (desc) {
                cookie = dmaengine_submit(desc);
index abad01b37cfbbab50761cafda285d40e67346b3b..5f9ad74fbf80b3a4a3556c5c5919c9ba525c610d 100644 (file)
@@ -41,8 +41,8 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
-#include <linux/workqueue.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 
 #include "tmio_mmc.h"
 
@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)
        /* Ready for new calls */
        host->mrq = NULL;
 
+       tmio_mmc_abort_dma(host);
        mmc_request_done(host->mmc, mrq);
 }
 
@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
        host->mrq = NULL;
        spin_unlock_irqrestore(&host->lock, flags);
 
+       if (mrq->cmd->error || (mrq->data && mrq->data->error))
+               tmio_mmc_abort_dma(host);
+
        mmc_request_done(host->mmc, mrq);
 }
 
index 6ae9ca01388b76b06798749aba0a35cae34f8b9c..9a9ce71a71fcbb2e004c0c0eb2f9a680202ee30d 100644 (file)
@@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state)
 {
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
-       return mtd_suspend(mtd);
+       return mtd ? mtd_suspend(mtd) : 0;
 }
 
 static int mtd_cls_resume(struct device *dev)
index 4dd056e2e16ac3e6798300e4b1cb13dde0948fb1..35b4fb55dbd6569dad6d4c927c9807698804b882 100644 (file)
@@ -161,6 +161,37 @@ 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);
@@ -235,27 +266,33 @@ 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 no DMA operation possible, use PIO */
-       memcpy_fromio(buf, chip->IO_ADDR_R, len);
+       if (host->board->bus_width_16)
+               atmel_read_buf16(mtd, buf, len);
+       else
+               atmel_read_buf8(mtd, buf, 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 no DMA operation possible, use PIO */
-       memcpy_toio(chip->IO_ADDR_W, buf, len);
+       if (host->board->bus_width_16)
+               atmel_write_buf16(mtd, buf, len);
+       else
+               atmel_write_buf8(mtd, buf, len);
 }
 
 /*
index 2a56fc6f399a871d2794445324a920eff5a0b228..7db6555ed3ba630f2935ce65b25200295b1754db 100644 (file)
@@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
  *  [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.
+ * In most of the cases, it's ok.
+ * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
  * 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.
+ * You will see a DMA timeout in this case. The bug has been fixed
+ * in the following chips, such as MX28.
  *
  * 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)
+static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
 {
        int ret;
        int timeout = 0x400;
@@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        if (ret)
                goto err_out;
 
-       ret = gpmi_reset_block(r->bch_regs, true);
+       /*
+       * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
+       * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
+       * On the other hand, the MX28 needs the reset, because one case has been
+       * seen where the BCH produced ECC errors constantly after 10000
+       * consecutive reboots. The latter case has not been seen on the MX23 yet,
+       * still we don't know if it could happen there as well.
+       */
+       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
        if (ret)
                goto err_out;
 
@@ -827,7 +837,7 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        pio[1] = pio[2] = 0;
        desc = channel->device->device_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
-                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+                                       ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 1 error\n");
                return -1;
@@ -839,7 +849,7 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        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);
+                                       sgl, 1, DMA_MEM_TO_DEV, 1);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -872,7 +882,7 @@ int gpmi_send_data(struct gpmi_nand_data *this)
        pio[1] = 0;
        desc = channel->device->device_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
-                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+                                       ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 1 error\n");
                return -1;
@@ -881,7 +891,7 @@ int gpmi_send_data(struct gpmi_nand_data *this)
        /* [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);
+                                               1, DMA_MEM_TO_DEV, 1);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -908,7 +918,7 @@ int gpmi_read_data(struct gpmi_nand_data *this)
        pio[1] = 0;
        desc = channel->device->device_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
-                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+                                       ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 1 error\n");
                return -1;
@@ -917,7 +927,7 @@ int gpmi_read_data(struct gpmi_nand_data *this)
        /* [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);
+                                               1, DMA_DEV_TO_MEM, 1);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -964,7 +974,7 @@ int gpmi_send_page(struct gpmi_nand_data *this,
 
        desc = channel->device->device_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
-                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+                                       ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -998,7 +1008,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                | BF_GPMI_CTRL0_XFER_COUNT(0);
        pio[1] = 0;
        desc = channel->device->device_prep_slave_sg(channel,
-                               (struct scatterlist *)pio, 2, DMA_NONE, 0);
+                               (struct scatterlist *)pio, 2,
+                               DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 1 error\n");
                return -1;
@@ -1027,7 +1038,7 @@ int gpmi_read_page(struct gpmi_nand_data *this,
        pio[5] = auxiliary;
        desc = channel->device->device_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
-                                       ARRAY_SIZE(pio), DMA_NONE, 1);
+                                       ARRAY_SIZE(pio), DMA_TRANS_NONE, 1);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -1045,7 +1056,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                | 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);
+                               (struct scatterlist *)pio, 2,
+                               DMA_TRANS_NONE, 1);
        if (!desc) {
                pr_err("step 3 error\n");
                return -1;
index 35b4565050f1430d425ed3615d3c4a806cda4b7a..8a393f9e6027d1be3dcf3d149dfc277e8941fca2 100644 (file)
@@ -2588,7 +2588,7 @@ 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! */
+               /* Check 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)) {
                        pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
index 342626f4bc4641d197f1c322bbdfebb0619d289c..f820b26b9db3562e7878feffceeba32f13a0d4f3 100644 (file)
@@ -909,16 +909,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
        }
 }
 
-/* hw is a boolean parameter that determines whether we should try and
- * set the hw address of the device as well as the hw address of the
- * net_device
- */
-static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
 {
        struct net_device *dev = slave->dev;
        struct sockaddr s_addr;
 
-       if (!hw) {
+       if (slave->bond->params.mode == BOND_MODE_TLB) {
                memcpy(dev->dev_addr, addr, dev->addr_len);
                return 0;
        }
@@ -948,8 +944,8 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct
        u8 tmp_mac_addr[ETH_ALEN];
 
        memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
-       alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
-       alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+       alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
+       alb_set_slave_mac_addr(slave2, tmp_mac_addr);
 
 }
 
@@ -1096,8 +1092,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 
                /* Try setting slave mac to bond address and fall-through
                   to code handling that situation below... */
-               alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
-                                      bond->alb_info.rlb_enabled);
+               alb_set_slave_mac_addr(slave, bond->dev->dev_addr);
        }
 
        /* The slave's address is equal to the address of the bond.
@@ -1133,8 +1128,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
        }
 
        if (free_mac_slave) {
-               alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
-                                      bond->alb_info.rlb_enabled);
+               alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
 
                pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
                           bond->dev->name, slave->dev->name,
@@ -1491,8 +1485,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
 {
        int res;
 
-       res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
-                                    bond->alb_info.rlb_enabled);
+       res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
        if (res) {
                return res;
        }
@@ -1643,8 +1636,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
                alb_swap_mac_addr(bond, swap_slave, new_slave);
        } else {
                /* set the new_slave to the bond mac address */
-               alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
-                                      bond->alb_info.rlb_enabled);
+               alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
        }
 
        if (swap_slave) {
@@ -1704,8 +1696,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
                alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
                alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
        } else {
-               alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
-                                      bond->alb_info.rlb_enabled);
+               alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
 
                read_lock(&bond->lock);
                alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
index 766896747643d95c96889f01b4315559f3a0b2e7..c30f0e6f104875a3b5fad4789904d0e048504da6 100644 (file)
@@ -440,12 +440,14 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
        for (i = 0; i < dlc; i++)
                cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
 
+       /* Store echo skb before starting the transfer */
+       can_put_echo_skb(skb, dev, 0);
+
        cc770_write_reg(priv, msgobj[mo].ctrl1,
                        RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
 
        stats->tx_bytes += dlc;
 
-       can_put_echo_skb(skb, dev, 0);
 
        /*
         * HM: We had some cases of repeated IRQs so make sure the
index 4be5fe2c40a5dda284f3669b9f19d456ad858dfa..9f3a25ccd665368b182ee9ed538cd10f3cc90922 100644 (file)
@@ -110,6 +110,11 @@ MODULE_PARM_DESC(bcr, "Bus configuration register (default=0x40 [CBY])");
 #define CC770_IOSIZE          0x20
 #define CC770_IOSIZE_INDIRECT 0x02
 
+/* Spinlock for cc770_isa_port_write_reg_indirect
+ * and cc770_isa_port_read_reg_indirect
+ */
+static DEFINE_SPINLOCK(cc770_isa_port_lock);
+
 static struct platform_device *cc770_isa_devs[MAXDEV];
 
 static u8 cc770_isa_mem_read_reg(const struct cc770_priv *priv, int reg)
@@ -138,18 +143,27 @@ static u8 cc770_isa_port_read_reg_indirect(const struct cc770_priv *priv,
                                             int reg)
 {
        unsigned long base = (unsigned long)priv->reg_base;
+       unsigned long flags;
+       u8 val;
 
+       spin_lock_irqsave(&cc770_isa_port_lock, flags);
        outb(reg, base);
-       return inb(base + 1);
+       val = inb(base + 1);
+       spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
+
+       return val;
 }
 
 static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
                                                int reg, u8 val)
 {
        unsigned long base = (unsigned long)priv->reg_base;
+       unsigned long flags;
 
+       spin_lock_irqsave(&cc770_isa_port_lock, flags);
        outb(reg, base);
        outb(val, base + 1);
+       spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
 }
 
 static int __devinit cc770_isa_probe(struct platform_device *pdev)
index 7fd8089946fb960ae84e65a28e232c3cf4a50f42..96d235799ec1f294a3a692a8a1273b42ab8bc154 100644 (file)
        (FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | FLEXCAN_ESR_BOFF_INT)
 #define FLEXCAN_ESR_ERR_ALL \
        (FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
+#define FLEXCAN_ESR_ALL_INT \
+       (FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
+        FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
 
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 #define FLEXCAN_TX_BUF_ID              8
@@ -577,7 +580,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 
        reg_iflag1 = flexcan_read(&regs->iflag1);
        reg_esr = flexcan_read(&regs->esr);
-       flexcan_write(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
+       /* ACK all bus error and state change IRQ sources */
+       if (reg_esr & FLEXCAN_ESR_ALL_INT)
+               flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
 
        /*
         * schedule NAPI in case of:
index d11fbb2b95ffe3d5e76378924c5b907f774327cf..6edc25e0dd15250286919650c8f575f9cb334b02 100644 (file)
@@ -66,6 +66,7 @@
 #define PCH_IF_CREQ_BUSY       BIT(15)
 
 #define PCH_STATUS_INT         0x8000
+#define PCH_RP                 0x00008000
 #define PCH_REC                        0x00007f00
 #define PCH_TEC                        0x000000ff
 
@@ -527,7 +528,7 @@ static void pch_can_error(struct net_device *ndev, u32 status)
                priv->can.can_stats.error_passive++;
                state = CAN_STATE_ERROR_PASSIVE;
                cf->can_id |= CAN_ERR_CRTL;
-               if (((errc & PCH_REC) >> 8) > 127)
+               if (errc & PCH_RP)
                        cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
                if ((errc & PCH_TEC) > 127)
                        cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
index 2c7f5036f570fd70d1078c1fabef3b7336d2d89e..214795945bc449d79329bbf2b82500eb9e1f19a3 100644 (file)
@@ -39,9 +39,9 @@ MODULE_LICENSE("GPL v2");
 #define DRV_NAME  "peak_pci"
 
 struct peak_pci_chan {
-       void __iomem *cfg_base;      /* Common for all channels */
-       struct net_device *next_dev; /* Chain of network devices */
-       u16 icr_mask;                /* Interrupt mask for fast ack */
+       void __iomem *cfg_base;         /* Common for all channels */
+       struct net_device *prev_dev;    /* Chain of network devices */
+       u16 icr_mask;                   /* Interrupt mask for fast ack */
 };
 
 #define PEAK_PCI_CAN_CLOCK     (16000000 / 2)
@@ -98,7 +98,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
 {
        struct sja1000_priv *priv;
        struct peak_pci_chan *chan;
-       struct net_device *dev, *dev0 = NULL;
+       struct net_device *dev;
        void __iomem *cfg_base, *reg_base;
        u16 sub_sys_id, icr;
        int i, err, channels;
@@ -196,18 +196,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
                }
 
                /* Create chain of SJA1000 devices */
-               if (i == 0)
-                       dev0 = dev;
-               else
-                       chan->next_dev = dev;
+               chan->prev_dev = pci_get_drvdata(pdev);
+               pci_set_drvdata(pdev, dev);
 
                dev_info(&pdev->dev,
                         "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
                         dev->name, priv->reg_base, chan->cfg_base, dev->irq);
        }
 
-       pci_set_drvdata(pdev, dev0);
-
        /* Enable interrupts */
        writew(icr, cfg_base + PITA_ICR + 2);
 
@@ -217,12 +213,11 @@ failure_remove_channels:
        /* Disable interrupts */
        writew(0x0, cfg_base + PITA_ICR + 2);
 
-       for (dev = dev0; dev; dev = chan->next_dev) {
+       for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
                unregister_sja1000dev(dev);
                free_sja1000dev(dev);
                priv = netdev_priv(dev);
                chan = priv->priv;
-               dev = chan->next_dev;
        }
 
        pci_iounmap(pdev, reg_base);
@@ -241,7 +236,7 @@ failure_disable_pci:
 
 static void __devexit peak_pci_remove(struct pci_dev *pdev)
 {
-       struct net_device *dev = pci_get_drvdata(pdev); /* First device */
+       struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
        struct sja1000_priv *priv = netdev_priv(dev);
        struct peak_pci_chan *chan = priv->priv;
        void __iomem *cfg_base = chan->cfg_base;
@@ -255,7 +250,7 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev)
                dev_info(&pdev->dev, "removing device %s\n", dev->name);
                unregister_sja1000dev(dev);
                free_sja1000dev(dev);
-               dev = chan->next_dev;
+               dev = chan->prev_dev;
                if (!dev)
                        break;
                priv = netdev_priv(dev);
index df809e3f130eed15f952323d0291ba6daa1661b8..5a2e1e3588a194a387660c0dd8715f5eb27fc39f 100644 (file)
@@ -745,9 +745,10 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
                }
        }
 
-       netif_receive_skb(skb);
+       netif_rx(skb);
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
+
        return 0;
 }
 
index 9697c14b8dc6b3dc4261894db49d59ec31a538dd..7dae64d44e83f70392ef13caad9cec152b480e5c 100644 (file)
@@ -627,9 +627,6 @@ static int ems_usb_start(struct ems_usb *dev)
 
                err = usb_submit_urb(urb, GFP_KERNEL);
                if (err) {
-                       if (err == -ENODEV)
-                               netif_device_detach(dev->netdev);
-
                        usb_unanchor_urb(urb);
                        usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
                                          urb->transfer_dma);
@@ -659,9 +656,6 @@ static int ems_usb_start(struct ems_usb *dev)
 
        err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
        if (err) {
-               if (err == -ENODEV)
-                       netif_device_detach(dev->netdev);
-
                dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n",
                         err);
 
@@ -692,9 +686,6 @@ static int ems_usb_start(struct ems_usb *dev)
        return 0;
 
 failed:
-       if (err == -ENODEV)
-               netif_device_detach(dev->netdev);
-
        dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err);
 
        return err;
index 7fc4e81d4d4353f6a85658d5be49ee6350264b8b..325391d19badb8366f27f726dbee042d1fe430ad 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <net/dsa.h>
index c0a458fc698fad1306641c03ba50c1567d964598..c17c75b9f531f49c661b132267653e2984212059 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <net/dsa.h>
@@ -20,12 +21,25 @@ static char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr)
 
        ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
        if (ret >= 0) {
-               ret &= 0xfff0;
-               if (ret == 0x1210)
+               if (ret == 0x1212)
+                       return "Marvell 88E6123 (A1)";
+               if (ret == 0x1213)
+                       return "Marvell 88E6123 (A2)";
+               if ((ret & 0xfff0) == 0x1210)
                        return "Marvell 88E6123";
-               if (ret == 0x1610)
+
+               if (ret == 0x1612)
+                       return "Marvell 88E6161 (A1)";
+               if (ret == 0x1613)
+                       return "Marvell 88E6161 (A2)";
+               if ((ret & 0xfff0) == 0x1610)
                        return "Marvell 88E6161";
-               if (ret == 0x1650)
+
+               if (ret == 0x1652)
+                       return "Marvell 88E6165 (A1)";
+               if (ret == 0x1653)
+                       return "Marvell 88e6165 (A2)";
+               if ((ret & 0xfff0) == 0x1650)
                        return "Marvell 88E6165";
        }
 
index e0eb682438343b774130769b24c42472c25e1af4..55888b06d8b47af7c90564027db08e2f54bf512d 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <net/dsa.h>
index 5467c040824a6d9d96c947f8a39c8e10e7afc753..a2c62c2f30ee40f7ecb11d460958cae0f5c94e80 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <net/dsa.h>
index 8153a3e0a1a4457a5c156508d7c605362bc76e37..f9b74c0a84926eb0cfb93dea482719a4be797202 100644 (file)
@@ -1842,7 +1842,7 @@ vortex_timer(unsigned long data)
                ok = 1;
        }
 
-       if (!netif_carrier_ok(dev))
+       if (dev->flags & IFF_SLAVE || !netif_carrier_ok(dev))
                next_tick = 5*HZ;
 
        if (vp->medialock)
index 986019b2c8490726f74ad31770aeece308117168..c7ca7ec065eeea7dfe164f96384ec3aaf464809d 100644 (file)
@@ -797,7 +797,7 @@ static int bcm_enet_open(struct net_device *dev)
        if (priv->has_phy) {
                /* connect to PHY */
                snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
-                        priv->mac_id ? "1" : "0", priv->phy_id);
+                        priv->mii_bus->id, priv->phy_id);
 
                phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
                                     PHY_INTERFACE_MODE_MII);
index 2b731b253598e9f94da434cdd322cfd197b0cb74..7aee46983be4329cb29b9f32a08fa7f441177808 100644 (file)
@@ -523,7 +523,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                skb = build_skb(data);
 
        if (likely(skb)) {
-
 #ifdef BNX2X_STOP_ON_ERROR
                if (pad + len > fp->rx_buf_size) {
                        BNX2X_ERR("skb_put is about to fail...  "
@@ -557,7 +556,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
                return;
        }
-
+       kfree(new_data);
 drop:
        /* drop the packet and keep the buffer in the bin */
        DP(NETIF_MSG_RX_STATUS,
@@ -3117,7 +3116,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
        int rx_ring_size = 0;
 
 #ifdef BCM_CNIC
-       if (IS_MF_ISCSI_SD(bp)) {
+       if (!bp->rx_ring_size && IS_MF_ISCSI_SD(bp)) {
                rx_ring_size = MIN_RX_SIZE_NONTPA;
                bp->rx_ring_size = rx_ring_size;
        } else
index a688b9d975a2576f5285417d3a23ed53a5c3fb5b..31a8b38ab15ebc2bff2bf19fa7110359827d0555 100644 (file)
@@ -365,13 +365,18 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx);
 
        if (cmd->autoneg == AUTONEG_ENABLE) {
+               u32 an_supported_speed = bp->port.supported[cfg_idx];
+               if (bp->link_params.phy[EXT_PHY1].type ==
+                   PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+                       an_supported_speed |= (SUPPORTED_100baseT_Half |
+                                              SUPPORTED_100baseT_Full);
                if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
                        DP(NETIF_MSG_LINK, "Autoneg not supported\n");
                        return -EINVAL;
                }
 
                /* advertise the requested speed and duplex if supported */
-               if (cmd->advertising & ~(bp->port.supported[cfg_idx])) {
+               if (cmd->advertising & ~an_supported_speed) {
                        DP(NETIF_MSG_LINK, "Advertisement parameters "
                                           "are not supported\n");
                        return -EINVAL;
@@ -1733,7 +1738,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
        struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
        u16 tx_start_idx, tx_idx;
        u16 rx_start_idx, rx_idx;
-       u16 pkt_prod, bd_prod, rx_comp_cons;
+       u16 pkt_prod, bd_prod;
        struct sw_tx_bd *tx_buf;
        struct eth_tx_start_bd *tx_start_bd;
        struct eth_tx_parse_bd_e1x  *pbd_e1x = NULL;
@@ -1868,8 +1873,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
        if (rx_idx != rx_start_idx + num_pkts)
                goto test_loopback_exit;
 
-       rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
-       cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
+       cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
        cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
        cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
        if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
@@ -2116,18 +2120,16 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
        case ETH_SS_STATS:
                if (is_multi(bp)) {
                        num_stats = bnx2x_num_stat_queues(bp) *
-                               BNX2X_NUM_Q_STATS;
-                       if (!IS_MF_MODE_STAT(bp))
-                               num_stats += BNX2X_NUM_STATS;
-               } else {
-                       if (IS_MF_MODE_STAT(bp)) {
-                               num_stats = 0;
-                               for (i = 0; i < BNX2X_NUM_STATS; i++)
-                                       if (IS_FUNC_STAT(i))
-                                               num_stats++;
-                       } else
-                               num_stats = BNX2X_NUM_STATS;
-               }
+                                               BNX2X_NUM_Q_STATS;
+               } else
+                       num_stats = 0;
+               if (IS_MF_MODE_STAT(bp)) {
+                       for (i = 0; i < BNX2X_NUM_STATS; i++)
+                               if (IS_FUNC_STAT(i))
+                                       num_stats++;
+               } else
+                       num_stats += BNX2X_NUM_STATS;
+
                return num_stats;
 
        case ETH_SS_TEST:
@@ -2146,8 +2148,8 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
 
        switch (stringset) {
        case ETH_SS_STATS:
+               k = 0;
                if (is_multi(bp)) {
-                       k = 0;
                        for_each_eth_queue(bp, i) {
                                memset(queue_name, 0, sizeof(queue_name));
                                sprintf(queue_name, "%d", i);
@@ -2158,20 +2160,17 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
                                                queue_name);
                                k += BNX2X_NUM_Q_STATS;
                        }
-                       if (IS_MF_MODE_STAT(bp))
-                               break;
-                       for (j = 0; j < BNX2X_NUM_STATS; j++)
-                               strcpy(buf + (k + j)*ETH_GSTRING_LEN,
-                                      bnx2x_stats_arr[j].string);
-               } else {
-                       for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-                               if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
-                                       continue;
-                               strcpy(buf + j*ETH_GSTRING_LEN,
-                                      bnx2x_stats_arr[i].string);
-                               j++;
-                       }
                }
+
+
+               for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+                       if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
+                               continue;
+                       strcpy(buf + (k + j)*ETH_GSTRING_LEN,
+                                  bnx2x_stats_arr[i].string);
+                       j++;
+               }
+
                break;
 
        case ETH_SS_TEST:
@@ -2185,10 +2184,9 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
 {
        struct bnx2x *bp = netdev_priv(dev);
        u32 *hw_stats, *offset;
-       int i, j, k;
+       int i, j, k = 0;
 
        if (is_multi(bp)) {
-               k = 0;
                for_each_eth_queue(bp, i) {
                        hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
                        for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
@@ -2209,46 +2207,28 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
                        }
                        k += BNX2X_NUM_Q_STATS;
                }
-               if (IS_MF_MODE_STAT(bp))
-                       return;
-               hw_stats = (u32 *)&bp->eth_stats;
-               for (j = 0; j < BNX2X_NUM_STATS; j++) {
-                       if (bnx2x_stats_arr[j].size == 0) {
-                               /* skip this counter */
-                               buf[k + j] = 0;
-                               continue;
-                       }
-                       offset = (hw_stats + bnx2x_stats_arr[j].offset);
-                       if (bnx2x_stats_arr[j].size == 4) {
-                               /* 4-byte counter */
-                               buf[k + j] = (u64) *offset;
-                               continue;
-                       }
-                       /* 8-byte counter */
-                       buf[k + j] = HILO_U64(*offset, *(offset + 1));
+       }
+
+       hw_stats = (u32 *)&bp->eth_stats;
+       for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+               if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
+                       continue;
+               if (bnx2x_stats_arr[i].size == 0) {
+                       /* skip this counter */
+                       buf[k + j] = 0;
+                       j++;
+                       continue;
                }
-       } else {
-               hw_stats = (u32 *)&bp->eth_stats;
-               for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-                       if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
-                               continue;
-                       if (bnx2x_stats_arr[i].size == 0) {
-                               /* skip this counter */
-                               buf[j] = 0;
-                               j++;
-                               continue;
-                       }
-                       offset = (hw_stats + bnx2x_stats_arr[i].offset);
-                       if (bnx2x_stats_arr[i].size == 4) {
-                               /* 4-byte counter */
-                               buf[j] = (u64) *offset;
-                               j++;
-                               continue;
-                       }
-                       /* 8-byte counter */
-                       buf[j] = HILO_U64(*offset, *(offset + 1));
+               offset = (hw_stats + bnx2x_stats_arr[i].offset);
+               if (bnx2x_stats_arr[i].size == 4) {
+                       /* 4-byte counter */
+                       buf[k + j] = (u64) *offset;
                        j++;
+                       continue;
                }
+               /* 8-byte counter */
+               buf[k + j] = HILO_U64(*offset, *(offset + 1));
+               j++;
        }
 }
 
index 4df9505b67b62e1d482460cc83fcfb6999a83746..2091e5dbbcdd9f50d0d0dec422cd2e1c3aac2d4f 100644 (file)
@@ -2502,7 +2502,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
                struct bnx2x_nig_brb_pfc_port_params *nig_params)
 {
        u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
-       u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
+       u32 llfc_enable = 0, xcm_out_en = 0, hwpfc_enable = 0;
        u32 pkt_priority_to_cos = 0;
        struct bnx2x *bp = params->bp;
        u8 port = params->port;
@@ -2516,9 +2516,8 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
         * MAC control frames (that are not pause packets)
         * will be forwarded to the XCM.
         */
-       xcm_mask = REG_RD(bp,
-                               port ? NIG_REG_LLH1_XCM_MASK :
-                               NIG_REG_LLH0_XCM_MASK);
+       xcm_mask = REG_RD(bp, port ? NIG_REG_LLH1_XCM_MASK :
+                         NIG_REG_LLH0_XCM_MASK);
        /*
         * nig params will override non PFC params, since it's possible to
         * do transition from PFC to SAFC
@@ -2533,8 +2532,8 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
                ppp_enable = 1;
                xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
                                     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
-               xcm0_out_en = 0;
-               p0_hwpfc_enable = 1;
+               xcm_out_en = 0;
+               hwpfc_enable = 1;
        } else  {
                if (nig_params) {
                        llfc_out_en = nig_params->llfc_out_en;
@@ -2545,7 +2544,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 
                xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
                        NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
-               xcm0_out_en = 1;
+               xcm_out_en = 1;
        }
 
        if (CHIP_IS_E3(bp))
@@ -2564,13 +2563,16 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
        REG_WR(bp, port ? NIG_REG_LLH1_XCM_MASK :
               NIG_REG_LLH0_XCM_MASK, xcm_mask);
 
-       REG_WR(bp,  NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
+       REG_WR(bp, port ? NIG_REG_LLFC_EGRESS_SRC_ENABLE_1 :
+              NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
 
        /* output enable for RX_XCM # IF */
-       REG_WR(bp, NIG_REG_XCM0_OUT_EN, xcm0_out_en);
+       REG_WR(bp, port ? NIG_REG_XCM1_OUT_EN :
+              NIG_REG_XCM0_OUT_EN, xcm_out_en);
 
        /* HW PFC TX enable */
-       REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
+       REG_WR(bp, port ? NIG_REG_P1_HWPFC_ENABLE :
+              NIG_REG_P0_HWPFC_ENABLE, hwpfc_enable);
 
        if (nig_params) {
                u8 i = 0;
@@ -3761,7 +3763,15 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        /* Advertise pause */
        bnx2x_ext_phy_set_pause(params, phy, vars);
 
-       vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+       /*
+        * Set KR Autoneg Work-Around flag for Warpcore version older than D108
+        */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
+       if (val16 < 0xd108) {
+               DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+               vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+       }
 
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                        MDIO_WC_REG_DIGITAL5_MISC7, &val16);
@@ -9266,62 +9276,68 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
 /*             BCM8481/BCM84823/BCM84833 PHY SECTION             */
 /******************************************************************/
 static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
-                                          struct link_params *params)
+                                           struct bnx2x *bp,
+                                           u8 port)
 {
        u16 val, fw_ver1, fw_ver2, cnt;
-       u8 port;
-       struct bnx2x *bp = params->bp;
 
-       port = params->port;
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+               bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
+               bnx2x_save_spirom_version(bp, port,
+                               ((fw_ver1 & 0xf000)>>5) | (fw_ver1 & 0x7f),
+                               phy->ver_addr);
+       } else {
+               /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
+               /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+
+               for (cnt = 0; cnt < 100; cnt++) {
+                       bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+                       if (val & 1)
+                               break;
+                       udelay(5);
+               }
+               if (cnt == 100) {
+                       DP(NETIF_MSG_LINK, "Unable to read 848xx "
+                                       "phy fw version(1)\n");
+                       bnx2x_save_spirom_version(bp, port, 0,
+                                                 phy->ver_addr);
+                       return;
+               }
 
-       /* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
-       /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
 
-       for (cnt = 0; cnt < 100; cnt++) {
-               bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
-               if (val & 1)
-                       break;
-               udelay(5);
-       }
-       if (cnt == 100) {
-               DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
-               bnx2x_save_spirom_version(bp, port, 0,
-                                         phy->ver_addr);
-               return;
-       }
+               /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
+               for (cnt = 0; cnt < 100; cnt++) {
+                       bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+                       if (val & 1)
+                               break;
+                       udelay(5);
+               }
+               if (cnt == 100) {
+                       DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw "
+                                       "version(2)\n");
+                       bnx2x_save_spirom_version(bp, port, 0,
+                                                 phy->ver_addr);
+                       return;
+               }
 
+               /* lower 16 bits of the register SPI_FW_STATUS */
+               bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
+               /* upper 16 bits of register SPI_FW_STATUS */
+               bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
 
-       /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
-       for (cnt = 0; cnt < 100; cnt++) {
-               bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
-               if (val & 1)
-                       break;
-               udelay(5);
-       }
-       if (cnt == 100) {
-               DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
-               bnx2x_save_spirom_version(bp, port, 0,
+               bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
                                          phy->ver_addr);
-               return;
        }
 
-       /* lower 16 bits of the register SPI_FW_STATUS */
-       bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
-       /* upper 16 bits of register SPI_FW_STATUS */
-       bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
-
-       bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
-                                 phy->ver_addr);
 }
-
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
                                struct bnx2x_phy *phy)
 {
@@ -9392,10 +9408,13 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
        u16 tmp_req_line_speed;
 
        tmp_req_line_speed = phy->req_line_speed;
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
                if (phy->req_line_speed == SPEED_10000)
                        phy->req_line_speed = SPEED_AUTO_NEG;
-
+       } else {
+               /* Save spirom version */
+               bnx2x_save_848xx_spirom_version(phy, bp, params->port);
+       }
        /*
         * This phy uses the NIG latch mechanism since link indication
         * arrives through its LED4 and not via its LASI signal, so we
@@ -9443,13 +9462,10 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                         an_1000_val);
 
        /* set 100 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+       if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
             (phy->speed_cap_mask &
              (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-              PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
-            (phy->supported &
-             (SUPPORTED_100baseT_Half |
-              SUPPORTED_100baseT_Full)))) {
+              PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))) {
                an_10_100_val |= (1<<7);
                /* Enable autoneg and restart autoneg for legacy speeds */
                autoneg_val |= (1<<9 | 1<<12);
@@ -9539,9 +9555,6 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                                 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
                                 1);
 
-       /* Save spirom version */
-       bnx2x_save_848xx_spirom_version(phy, params);
-
        phy->req_line_speed = tmp_req_line_speed;
 
        return 0;
@@ -9749,17 +9762,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 
        /* Wait for GPHY to come out of reset */
        msleep(50);
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
-               /* Bring PHY out of super isolate mode */
-               bnx2x_cl45_read(bp, phy,
-                               MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
-               val &= ~MDIO_84833_SUPER_ISOLATE;
-               bnx2x_cl45_write(bp, phy,
-                               MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
-               bnx2x_84833_pair_swap_cfg(phy, params, vars);
-       } else {
+       if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
                /*
                 * BCM84823 requires that XGXS links up first @ 10G for normal
                 * behavior.
@@ -9816,24 +9819,23 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
        DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
                   params->multi_phy_config, val);
 
-       /* AutogrEEEn */
-       if (params->feature_config_flags &
-               FEATURE_CONFIG_AUTOGREEEN_ENABLED)
-               cmd_args[0] = 0x2;
-       else
-               cmd_args[0] = 0x0;
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+               bnx2x_84833_pair_swap_cfg(phy, params, vars);
 
-       cmd_args[1] = 0x0;
-       cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
-       cmd_args[3] = PHY84833_CONSTANT_LATENCY;
-       rc = bnx2x_84833_cmd_hdlr(phy, params,
-               PHY84833_CMD_SET_EEE_MODE, cmd_args);
-       if (rc != 0)
-               DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
+               /* Keep AutogrEEEn disabled. */
+               cmd_args[0] = 0x0;
+               cmd_args[1] = 0x0;
+               cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
+               cmd_args[3] = PHY84833_CONSTANT_LATENCY;
+               rc = bnx2x_84833_cmd_hdlr(phy, params,
+                       PHY84833_CMD_SET_EEE_MODE, cmd_args);
+               if (rc != 0)
+                       DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
+       }
        if (initialize)
                rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
        else
-               bnx2x_save_848xx_spirom_version(phy, params);
+               bnx2x_save_848xx_spirom_version(phy, bp, params->port);
        /* 84833 PHY has a better feature and doesn't need to support this. */
        if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
                cms_enable = REG_RD(bp, params->shmem_base +
@@ -9851,6 +9853,16 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                                 MDIO_CTL_REG_84823_USER_CTRL_REG, val);
        }
 
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+               /* Bring PHY out of super isolate mode as the final step. */
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_CTL_DEVAD,
+                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+               val &= ~MDIO_84833_SUPER_ISOLATE;
+               bnx2x_cl45_write(bp, phy,
+                               MDIO_CTL_DEVAD,
+                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+       }
        return rc;
 }
 
@@ -9988,10 +10000,11 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
        } else {
                bnx2x_cl45_read(bp, phy,
                                MDIO_CTL_DEVAD,
-                               0x400f, &val16);
+                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val16);
+               val16 |= MDIO_84833_SUPER_ISOLATE;
                bnx2x_cl45_write(bp, phy,
-                               MDIO_PMA_DEVAD,
-                               MDIO_PMA_REG_CTRL, 0x800);
+                                MDIO_CTL_DEVAD,
+                                MDIO_84833_TOP_CFG_XGPHY_STRAP1, val16);
        }
 }
 
@@ -11516,6 +11529,19 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
        }
        phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
 
+       if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+           (phy->ver_addr)) {
+               /*
+                * Remove 100Mb link supported for BCM84833 when phy fw
+                * version lower than or equal to 1.39
+                */
+               u32 raw_ver = REG_RD(bp, phy->ver_addr);
+               if (((raw_ver & 0x7F) <= 39) &&
+                   (((raw_ver & 0xF80) >> 7) <= 1))
+                       phy->supported &= ~(SUPPORTED_100baseT_Half |
+                                           SUPPORTED_100baseT_Full);
+       }
+
        /*
         * In case mdc/mdio_access of the external phy is different than the
         * mdc/mdio access of the XGXS, a HW lock must be taken in each access
@@ -12333,55 +12359,69 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
                                                u32 chip_id)
 {
        u8 reset_gpios;
-       struct bnx2x_phy phy;
-       u32 shmem_base, shmem2_base, cnt;
-       s8 port = 0;
-       u16 val;
-
        reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
        bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
        udelay(10);
        bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
        DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
                reset_gpios);
-       for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-               /* This PHY is for E2 and E3. */
-               shmem_base = shmem_base_path[port];
-               shmem2_base = shmem2_base_path[port];
-               /* Extract the ext phy address for the port */
-               if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-                                      0, &phy) !=
-                   0) {
-                       DP(NETIF_MSG_LINK, "populate_phy failed\n");
-                       return -EINVAL;
-               }
+       return 0;
+}
 
-               /* Wait for FW completing its initialization. */
-               for (cnt = 0; cnt < 1000; cnt++) {
-                       bnx2x_cl45_read(bp, &phy,
+static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
+                                              struct bnx2x_phy *phy)
+{
+       u16 val, cnt;
+       /* Wait for FW completing its initialization. */
+       for (cnt = 0; cnt < 1500; cnt++) {
+               bnx2x_cl45_read(bp, phy,
                                MDIO_PMA_DEVAD,
                                MDIO_PMA_REG_CTRL, &val);
-                       if (!(val & (1<<15)))
-                               break;
-                       msleep(1);
-               }
-               if (cnt >= 1000)
-                       DP(NETIF_MSG_LINK,
-                               "84833 Cmn reset timeout (%d)\n", port);
-
-               /* Put the port in super isolate mode. */
-               bnx2x_cl45_read(bp, &phy,
-                               MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
-               val |= MDIO_84833_SUPER_ISOLATE;
-               bnx2x_cl45_write(bp, &phy,
-                               MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+               if (!(val & (1<<15)))
+                       break;
+               msleep(1);
+       }
+       if (cnt >= 1500) {
+               DP(NETIF_MSG_LINK, "84833 reset timeout\n");
+               return -EINVAL;
        }
 
+       /* Put the port in super isolate mode. */
+       bnx2x_cl45_read(bp, phy,
+                       MDIO_CTL_DEVAD,
+                       MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+       val |= MDIO_84833_SUPER_ISOLATE;
+       bnx2x_cl45_write(bp, phy,
+                        MDIO_CTL_DEVAD,
+                        MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+
+       /* Save spirom version */
+       bnx2x_save_848xx_spirom_version(phy, bp, PORT_0);
        return 0;
 }
 
+int bnx2x_pre_init_phy(struct bnx2x *bp,
+                                 u32 shmem_base,
+                                 u32 shmem2_base,
+                                 u32 chip_id)
+{
+       int rc = 0;
+       struct bnx2x_phy phy;
+       bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
+       if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base,
+                              PORT_0, &phy)) {
+               DP(NETIF_MSG_LINK, "populate_phy failed\n");
+               return -EINVAL;
+       }
+       switch (phy.type) {
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+               rc = bnx2x_84833_pre_init_phy(bp, &phy);
+               break;
+       default:
+               break;
+       }
+       return rc;
+}
 
 static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
                                     u32 shmem2_base_path[], u8 phy_index,
index ffeaaa95ed96eb983cfd60d5c5c2395a92b3b952..254521319150e5cb74541a3973434497900dc8d5 100644 (file)
@@ -117,10 +117,6 @@ static int dropless_fc;
 module_param(dropless_fc, int, 0);
 MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring");
 
-static int poll;
-module_param(poll, int, 0);
-MODULE_PARM_DESC(poll, " Use polling (for debug)");
-
 static int mrrs = -1;
 module_param(mrrs, int, 0);
 MODULE_PARM_DESC(mrrs, " Force Max Read Req Size (0..3) (for debug)");
@@ -941,7 +937,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
                        struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j];
 
                        BNX2X_ERR("fp%d: rx_bd[%x]=[%x:%x]  sw_bd=[%p]\n",
-                                 i, j, rx_bd[1], rx_bd[0], sw_bd->skb);
+                                 i, j, rx_bd[1], rx_bd[0], sw_bd->data);
                }
 
                start = RX_SGE(fp->rx_sge_prod);
@@ -4834,20 +4830,11 @@ void bnx2x_drv_pulse(struct bnx2x *bp)
 
 static void bnx2x_timer(unsigned long data)
 {
-       u8 cos;
        struct bnx2x *bp = (struct bnx2x *) data;
 
        if (!netif_running(bp->dev))
                return;
 
-       if (poll) {
-               struct bnx2x_fastpath *fp = &bp->fp[0];
-
-               for_each_cos_in_tx_queue(fp, cos)
-                       bnx2x_tx_int(bp, &fp->txdata[cos]);
-               bnx2x_rx_int(fp, 1000);
-       }
-
        if (!BP_NOMCP(bp)) {
                int mb_idx = BP_FW_MB_IDX(bp);
                u32 drv_pulse;
@@ -10063,7 +10050,6 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
 static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 {
        int func;
-       int timer_interval;
        int rc;
 
        mutex_init(&bp->port.phy_mutex);
@@ -10139,8 +10125,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
        bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR;
 
-       timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
-       bp->current_interval = (poll ? poll : timer_interval);
+       bp->current_interval = CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ;
 
        init_timer(&bp->timer);
        bp->timer.expires = jiffies + bp->current_interval;
@@ -10536,6 +10521,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
 {
        struct bnx2x *bp;
        int rc;
+       bool chip_is_e1x = (board_type == BCM57710 ||
+                           board_type == BCM57711 ||
+                           board_type == BCM57711E);
 
        SET_NETDEV_DEV(dev, &pdev->dev);
        bp = netdev_priv(dev);
@@ -10624,7 +10612,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
        REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
        REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0);
 
-       if (CHIP_IS_E1x(bp)) {
+       if (chip_is_e1x) {
                REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0);
                REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0);
                REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0);
@@ -10635,9 +10623,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
         * Enable internal target-read (in case we are probed after PF FLR).
         * Must be done prior to any BAR read access. Only for 57712 and up
         */
-       if (board_type != BCM57710 &&
-           board_type != BCM57711 &&
-           board_type != BCM57711E)
+       if (!chip_is_e1x)
                REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
 
        /* Reset the load counter */
index 44609de4e5dc59f7ecbe41d3ea8c0e01f17d837e..dddbcf6e154ec58d8d1f0720706df5ad0076c338 100644 (file)
  * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
  * accommodate the 9 input clients to ETS arbiter. */
 #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB                  0x18684
+#define NIG_REG_P1_HWPFC_ENABLE                                         0x181d0
 #define NIG_REG_P1_MAC_IN_EN                                    0x185c0
 /* [RW 1] Output enable for TX MAC interface */
 #define NIG_REG_P1_MAC_OUT_EN                                   0x185c4
index 5ac616093f9f7d4c4dfd5696dd966ff614091c45..cb6339c35571f6a9d86b85d92324fb4680b80406 100644 (file)
@@ -50,6 +50,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
                                        int exe_len,
                                        union bnx2x_qable_obj *owner,
                                        exe_q_validate validate,
+                                       exe_q_remove remove,
                                        exe_q_optimize optimize,
                                        exe_q_execute exec,
                                        exe_q_get get)
@@ -66,6 +67,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
 
        /* Owner specific callbacks */
        o->validate      = validate;
+       o->remove        = remove;
        o->optimize      = optimize;
        o->execute       = exec;
        o->get           = get;
@@ -1340,6 +1342,35 @@ static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
        }
 }
 
+static int bnx2x_remove_vlan_mac(struct bnx2x *bp,
+                                 union bnx2x_qable_obj *qo,
+                                 struct bnx2x_exeq_elem *elem)
+{
+       int rc = 0;
+
+       /* If consumption wasn't required, nothing to do */
+       if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+                    &elem->cmd_data.vlan_mac.vlan_mac_flags))
+               return 0;
+
+       switch (elem->cmd_data.vlan_mac.cmd) {
+       case BNX2X_VLAN_MAC_ADD:
+       case BNX2X_VLAN_MAC_MOVE:
+               rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
+               break;
+       case BNX2X_VLAN_MAC_DEL:
+               rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (rc != true)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
  *
@@ -1801,8 +1832,14 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
 
        list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
                if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
-                   *vlan_mac_flags)
+                   *vlan_mac_flags) {
+                       rc = exeq->remove(bp, exeq->owner, exeq_pos);
+                       if (rc) {
+                               BNX2X_ERR("Failed to remove command\n");
+                               return rc;
+                       }
                        list_del(&exeq_pos->link);
+               }
        }
 
        spin_unlock_bh(&exeq->lock);
@@ -1908,6 +1945,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp,
                bnx2x_exe_queue_init(bp,
                                     &mac_obj->exe_queue, 1, qable_obj,
                                     bnx2x_validate_vlan_mac,
+                                    bnx2x_remove_vlan_mac,
                                     bnx2x_optimize_vlan_mac,
                                     bnx2x_execute_vlan_mac,
                                     bnx2x_exeq_get_mac);
@@ -1924,6 +1962,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp,
                bnx2x_exe_queue_init(bp,
                                     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
                                     qable_obj, bnx2x_validate_vlan_mac,
+                                    bnx2x_remove_vlan_mac,
                                     bnx2x_optimize_vlan_mac,
                                     bnx2x_execute_vlan_mac,
                                     bnx2x_exeq_get_mac);
@@ -1963,6 +2002,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
                bnx2x_exe_queue_init(bp,
                                     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
                                     qable_obj, bnx2x_validate_vlan_mac,
+                                    bnx2x_remove_vlan_mac,
                                     bnx2x_optimize_vlan_mac,
                                     bnx2x_execute_vlan_mac,
                                     bnx2x_exeq_get_vlan);
@@ -2009,6 +2049,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
                bnx2x_exe_queue_init(bp,
                                     &vlan_mac_obj->exe_queue, 1, qable_obj,
                                     bnx2x_validate_vlan_mac,
+                                    bnx2x_remove_vlan_mac,
                                     bnx2x_optimize_vlan_mac,
                                     bnx2x_execute_vlan_mac,
                                     bnx2x_exeq_get_vlan_mac);
@@ -2025,6 +2066,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
                                     &vlan_mac_obj->exe_queue,
                                     CLASSIFY_RULES_COUNT,
                                     qable_obj, bnx2x_validate_vlan_mac,
+                                    bnx2x_remove_vlan_mac,
                                     bnx2x_optimize_vlan_mac,
                                     bnx2x_execute_vlan_mac,
                                     bnx2x_exeq_get_vlan_mac);
index 992308ff82e845b8698f1647a258b8bdc968aa7e..66da39f0c84a4f4b476eaaea82af8afcc21b0fe9 100644 (file)
@@ -161,6 +161,10 @@ typedef int (*exe_q_validate)(struct bnx2x *bp,
                              union bnx2x_qable_obj *o,
                              struct bnx2x_exeq_elem *elem);
 
+typedef int (*exe_q_remove)(struct bnx2x *bp,
+                           union bnx2x_qable_obj *o,
+                           struct bnx2x_exeq_elem *elem);
+
 /**
  * @return positive is entry was optimized, 0 - if not, negative
  *         in case of an error.
@@ -203,11 +207,18 @@ struct bnx2x_exe_queue_obj {
         */
        exe_q_validate          validate;
 
+       /**
+        * Called before removing pending commands, cleaning allocated
+        * resources (e.g., credits from validate)
+        */
+        exe_q_remove           remove;
 
        /**
         * This will try to cancel the current pending commands list
         * considering the new command.
         *
+        * Returns the number of optimized commands or a negative error code
+        *
         * Must run under exe_queue->lock
         */
        exe_q_optimize          optimize;
index bc0121ac291e249f0f21876dc01127fc46c256d4..1adef266fcd50252deb5f8684d6708656a577765 100644 (file)
@@ -1081,17 +1081,17 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
               estats->rx_stat_ifhcinbadoctets_lo);
 
        ADD_64(fstats->total_bytes_received_hi,
-              tfunc->rcv_error_bytes.hi,
+              le32_to_cpu(tfunc->rcv_error_bytes.hi),
               fstats->total_bytes_received_lo,
-              tfunc->rcv_error_bytes.lo);
+              le32_to_cpu(tfunc->rcv_error_bytes.lo));
 
        memcpy(estats, &(fstats->total_bytes_received_hi),
               sizeof(struct host_func_stats) - 2*sizeof(u32));
 
        ADD_64(estats->error_bytes_received_hi,
-              tfunc->rcv_error_bytes.hi,
+              le32_to_cpu(tfunc->rcv_error_bytes.hi),
               estats->error_bytes_received_lo,
-              tfunc->rcv_error_bytes.lo);
+              le32_to_cpu(tfunc->rcv_error_bytes.lo));
 
        ADD_64(estats->etherstatsoverrsizepkts_hi,
               estats->rx_stat_dot3statsframestoolong_hi,
index 076e02a415a09d09878db3ea1c0071c03ac4a685..a1f2e0fed78bc2b23b7caa2c1457255e6eae9b89 100644 (file)
@@ -6667,14 +6667,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                iph = ip_hdr(skb);
                tcp_opt_len = tcp_optlen(skb);
 
-               if (skb_is_gso_v6(skb)) {
-                       hdr_len = skb_headlen(skb) - ETH_HLEN;
-               } else {
-                       u32 ip_tcp_len;
-
-                       ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-                       hdr_len = ip_tcp_len + tcp_opt_len;
+               hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;
 
+               if (!skb_is_gso_v6(skb)) {
                        iph->check = 0;
                        iph->tot_len = htons(mss + hdr_len);
                }
@@ -8846,9 +8841,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
        udelay(100);
 
-       if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1) {
+       if (tg3_flag(tp, USING_MSIX)) {
                val = tr32(MSGINT_MODE);
-               val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
+               val |= MSGINT_MODE_ENABLE;
+               if (tp->irq_cnt > 1)
+                       val |= MSGINT_MODE_MULTIVEC_EN;
                if (!tg3_flag(tp, 1SHOT_MSI))
                        val |= MSGINT_MODE_ONE_SHOT_DISABLE;
                tw32(MSGINT_MODE, val);
@@ -9548,19 +9545,18 @@ static int tg3_request_firmware(struct tg3 *tp)
 
 static bool tg3_enable_msix(struct tg3 *tp)
 {
-       int i, rc, cpus = num_online_cpus();
+       int i, rc;
        struct msix_entry msix_ent[tp->irq_max];
 
-       if (cpus == 1)
-               /* Just fallback to the simpler MSI mode. */
-               return false;
-
-       /*
-        * We want as many rx rings enabled as there are cpus.
-        * The first MSIX vector only deals with link interrupts, etc,
-        * so we add one to the number of vectors we are requesting.
-        */
-       tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max);
+       tp->irq_cnt = num_online_cpus();
+       if (tp->irq_cnt > 1) {
+               /* We want as many rx rings enabled as there are cpus.
+                * In multiqueue MSI-X mode, the first MSI-X vector
+                * only deals with link interrupts, etc, so we add
+                * one to the number of vectors we are requesting.
+                */
+               tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max);
+       }
 
        for (i = 0; i < tp->irq_max; i++) {
                msix_ent[i].entry  = i;
index 9b44ec8096baa270272f0e991df470221532c310..803ea32aa99d31c2e6545ab9e86374154a657cdf 100644 (file)
@@ -946,7 +946,7 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
 
        flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL);
        if (!flash_attr)
-               return -ENOMEM;
+               return 0;
 
        fcomp.bnad = bnad;
        fcomp.comp_status = 0;
@@ -958,7 +958,7 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
        if (ret != BFA_STATUS_OK) {
                spin_unlock_irqrestore(&bnad->bna_lock, flags);
                kfree(flash_attr);
-               goto out_err;
+               return 0;
        }
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
        wait_for_completion(&fcomp.comp);
@@ -978,8 +978,6 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
        }
        kfree(flash_attr);
        return flash_part;
-out_err:
-       return -EINVAL;
 }
 
 static int
@@ -1006,7 +1004,7 @@ bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
        /* Query the flash partition based on the offset */
        flash_part = bnad_get_flash_partition_by_offset(bnad,
                                eeprom->offset, &base_offset);
-       if (flash_part <= 0)
+       if (flash_part == 0)
                return -EFAULT;
 
        fcomp.bnad = bnad;
@@ -1048,7 +1046,7 @@ bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
        /* Query the flash partition based on the offset */
        flash_part = bnad_get_flash_partition_by_offset(bnad,
                                eeprom->offset, &base_offset);
-       if (flash_part <= 0)
+       if (flash_part == 0)
                return -EFAULT;
 
        fcomp.bnad = bnad;
index fe0c29acdbe6da46bd99386a13c528b57f19c04b..ee93a2087fe6c0cfd116dcf3f4536185480ba362 100644 (file)
@@ -32,7 +32,7 @@
 
 #define DRV_NAME               "enic"
 #define DRV_DESCRIPTION                "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION            "2.1.1.28"
+#define DRV_VERSION            "2.1.1.31"
 #define DRV_COPYRIGHT          "Copyright 2008-2011 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX          6
index 2fd9db4b1be57b440b1d07ab5d8e582c49625d05..ab3f67f980d8c3f7554d19bf3fdbaf275deefed3 100644 (file)
 
 #define PCI_DEVICE_ID_CISCO_VIC_ENET         0x0043  /* ethernet vnic */
 #define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN     0x0044  /* enet dynamic vnic */
+#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF      0x0071  /* enet SRIOV VF */
 
 /* Supported devices */
 static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
        { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
        { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
+       { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
        { 0, }  /* end of table */
 };
 
@@ -132,6 +134,11 @@ int enic_sriov_enabled(struct enic *enic)
        return (enic->priv_flags & ENIC_SRIOV_ENABLED) ? 1 : 0;
 }
 
+static int enic_is_sriov_vf(struct enic *enic)
+{
+       return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
+}
+
 int enic_is_valid_vf(struct enic *enic, int vf)
 {
 #ifdef CONFIG_PCI_IOV
@@ -437,7 +444,7 @@ static void enic_mtu_check(struct enic *enic)
 
        if (mtu && mtu != enic->port_mtu) {
                enic->port_mtu = mtu;
-               if (enic_is_dynamic(enic)) {
+               if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
                        mtu = max_t(int, ENIC_MIN_MTU,
                                min_t(int, ENIC_MAX_MTU, mtu));
                        if (mtu != netdev->mtu)
@@ -849,7 +856,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
 {
        struct enic *enic = netdev_priv(netdev);
 
-       if (enic_is_dynamic(enic)) {
+       if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
                if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr))
                        return -EADDRNOTAVAIL;
        } else {
@@ -1608,7 +1615,7 @@ static int enic_open(struct net_device *netdev)
        for (i = 0; i < enic->rq_count; i++)
                vnic_rq_enable(&enic->rq[i]);
 
-       if (!enic_is_dynamic(enic))
+       if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
                enic_dev_add_station_addr(enic);
 
        enic_set_rx_mode(netdev);
@@ -1659,7 +1666,7 @@ static int enic_stop(struct net_device *netdev)
        netif_carrier_off(netdev);
        netif_tx_disable(netdev);
 
-       if (!enic_is_dynamic(enic))
+       if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
                enic_dev_del_station_addr(enic);
 
        for (i = 0; i < enic->wq_count; i++) {
@@ -1696,7 +1703,7 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
        if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
                return -EINVAL;
 
-       if (enic_is_dynamic(enic))
+       if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
                return -EOPNOTSUPP;
 
        if (running)
@@ -2263,10 +2270,10 @@ static int __devinit enic_probe(struct pci_dev *pdev,
        int using_dac = 0;
        unsigned int i;
        int err;
-       int num_pps = 1;
 #ifdef CONFIG_PCI_IOV
        int pos = 0;
 #endif
+       int num_pps = 1;
 
        /* Allocate net device structure and initialize.  Private
         * instance data is initialized to zero.
@@ -2376,14 +2383,14 @@ static int __devinit enic_probe(struct pci_dev *pdev,
                        num_pps = enic->num_vfs;
                }
        }
-
 #endif
+
        /* Allocate structure for port profiles */
        enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL);
        if (!enic->pp) {
                pr_err("port profile alloc failed, aborting\n");
                err = -ENOMEM;
-               goto err_out_disable_sriov;
+               goto err_out_disable_sriov_pp;
        }
 
        /* Issue device open to get device in known state
@@ -2392,7 +2399,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
        err = enic_dev_open(enic);
        if (err) {
                dev_err(dev, "vNIC dev open failed, aborting\n");
-               goto err_out_free_pp;
+               goto err_out_disable_sriov;
        }
 
        /* Setup devcmd lock
@@ -2426,7 +2433,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
         * called later by an upper layer.
         */
 
-       if (!enic_is_dynamic(enic)) {
+       if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) {
                err = vnic_dev_init(enic->vdev, 0);
                if (err) {
                        dev_err(dev, "vNIC dev init failed, aborting\n");
@@ -2460,8 +2467,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
        (void)enic_change_mtu(netdev, enic->port_mtu);
 
 #ifdef CONFIG_PCI_IOV
-       if (enic_is_dynamic(enic) && pdev->is_virtfn &&
-               is_zero_ether_addr(enic->mac_addr))
+       if (enic_is_sriov_vf(enic) && is_zero_ether_addr(enic->mac_addr))
                random_ether_addr(enic->mac_addr);
 #endif
 
@@ -2474,7 +2480,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
        enic->tx_coalesce_usecs = enic->config.intr_timer_usec;
        enic->rx_coalesce_usecs = enic->tx_coalesce_usecs;
 
-       if (enic_is_dynamic(enic))
+       if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
                netdev->netdev_ops = &enic_netdev_dynamic_ops;
        else
                netdev->netdev_ops = &enic_netdev_ops;
@@ -2516,17 +2522,17 @@ err_out_dev_deinit:
        enic_dev_deinit(enic);
 err_out_dev_close:
        vnic_dev_close(enic->vdev);
-err_out_free_pp:
-       kfree(enic->pp);
 err_out_disable_sriov:
+       kfree(enic->pp);
+err_out_disable_sriov_pp:
 #ifdef CONFIG_PCI_IOV
        if (enic_sriov_enabled(enic)) {
                pci_disable_sriov(pdev);
                enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
        }
 err_out_vnic_unregister:
-       vnic_dev_unregister(enic->vdev);
 #endif
+       vnic_dev_unregister(enic->vdev);
 err_out_iounmap:
        enic_iounmap(enic);
 err_out_release_regions:
index 6db6b6ae5e9b1f66e733f7ff530784fa2237fd11..802e5ddef8a8c48aa48ad4ae2adafc35ff8b5f84 100644 (file)
@@ -716,12 +716,8 @@ static int
 be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
-       char file_name[ETHTOOL_FLASH_MAX_FILENAME];
 
-       file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
-       strcpy(file_name, efl->data);
-
-       return be_load_fw(adapter, file_name);
+       return be_load_fw(adapter, efl->data);
 }
 
 static int
index a6bcdb5cd2be4a0b3880cfbe8d72dfb3b07045ce..e703d64434f89cec738cf2a28fc3b37167fb4c11 100644 (file)
@@ -1786,8 +1786,7 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
 static u32 be_num_rxqs_want(struct be_adapter *adapter)
 {
        if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
-            !sriov_enabled(adapter) && be_physfn(adapter) &&
-            !be_is_mc(adapter)) {
+            !sriov_enabled(adapter) && be_physfn(adapter)) {
                return 1 + MAX_RSS_QS; /* one default non-RSS queue */
        } else {
                dev_warn(&adapter->pdev->dev,
index fb5579a3b19d60f5e38dd995bcaad6dc384a0633..47f85c337cf75cac6034990e68e978367886a0db 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
index a127cb2476c71ff89f0e343134421ada4b52911e..bb336a0959c9147624ff6c23d63ee71138f7663d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mii.h>
 #include <linux/module.h>
index 7b25e9cf13f6ff5a6c141cd6c6bd478fe5e5c6fb..e92ef1bd732a4fe9cf4f0ad8569117bb711eea31 100644 (file)
@@ -986,11 +986,11 @@ static int fec_enet_mii_probe(struct net_device *ndev)
                printk(KERN_INFO
                        "%s: no PHY, assuming direct connection to switch\n",
                        ndev->name);
-               strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
+               strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
                phy_id = 0;
        }
 
-       snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+       snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
        phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
                              fep->phy_interface);
        if (IS_ERR(phy_dev)) {
index 05b7359bde8da1931ac53ebc6fc95310bd398e11..6bdd8e36e564c4868eac9259b63a81c23f345337 100644 (file)
@@ -263,7 +263,7 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
                data[i++] = atomic_read(&port->port_res[k].swqe_avail);
 }
 
-const struct ethtool_ops ehea_ethtool_ops = {
+static const struct ethtool_ops ehea_ethtool_ops = {
        .get_settings = ehea_get_settings,
        .get_drvinfo = ehea_get_drvinfo,
        .get_msglevel = ehea_get_msglevel,
index 3554414eb5e289287e3a9ab174320c7e9fa1bf30..5d5fb2627184f9b7f303d64c22875182c63d88e6 100644 (file)
@@ -94,8 +94,8 @@ static int port_name_cnt;
 static LIST_HEAD(adapter_list);
 static unsigned long ehea_driver_flags;
 static DEFINE_MUTEX(dlpar_mem_lock);
-struct ehea_fw_handle_array ehea_fw_handles;
-struct ehea_bcmc_reg_array ehea_bcmc_regs;
+static struct ehea_fw_handle_array ehea_fw_handles;
+static struct ehea_bcmc_reg_array ehea_bcmc_regs;
 
 
 static int __devinit ehea_probe_adapter(struct platform_device *dev,
@@ -133,7 +133,7 @@ void ehea_dump(void *adr, int len, char *msg)
        }
 }
 
-void ehea_schedule_port_reset(struct ehea_port *port)
+static void ehea_schedule_port_reset(struct ehea_port *port)
 {
        if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
                schedule_work(&port->reset_task);
@@ -1404,7 +1404,7 @@ out:
        return ret;
 }
 
-int ehea_gen_smrs(struct ehea_port_res *pr)
+static int ehea_gen_smrs(struct ehea_port_res *pr)
 {
        int ret;
        struct ehea_adapter *adapter = pr->port->adapter;
@@ -1426,7 +1426,7 @@ out:
        return -EIO;
 }
 
-int ehea_rem_smrs(struct ehea_port_res *pr)
+static int ehea_rem_smrs(struct ehea_port_res *pr)
 {
        if ((ehea_rem_mr(&pr->send_mr)) ||
            (ehea_rem_mr(&pr->recv_mr)))
@@ -2190,7 +2190,7 @@ out:
        return err;
 }
 
-int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
+static int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
 {
        int ret = -EIO;
        u64 hret;
@@ -2531,7 +2531,7 @@ static void ehea_flush_sq(struct ehea_port *port)
        }
 }
 
-int ehea_stop_qps(struct net_device *dev)
+static int ehea_stop_qps(struct net_device *dev)
 {
        struct ehea_port *port = netdev_priv(dev);
        struct ehea_adapter *adapter = port->adapter;
@@ -2600,7 +2600,7 @@ out:
        return ret;
 }
 
-void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
+static void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
 {
        struct ehea_qp qp = *orig_qp;
        struct ehea_qp_init_attr *init_attr = &qp.init_attr;
@@ -2633,7 +2633,7 @@ void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
        }
 }
 
-int ehea_restart_qps(struct net_device *dev)
+static int ehea_restart_qps(struct net_device *dev)
 {
        struct ehea_port *port = netdev_priv(dev);
        struct ehea_adapter *adapter = port->adapter;
@@ -2824,7 +2824,7 @@ static void ehea_tx_watchdog(struct net_device *dev)
                ehea_schedule_port_reset(port);
 }
 
-int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
+static int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
 {
        struct hcp_query_ehea *cb;
        u64 hret;
@@ -2852,7 +2852,7 @@ out:
        return ret;
 }
 
-int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
+static int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
 {
        struct hcp_ehea_port_cb4 *cb4;
        u64 hret;
@@ -2966,7 +2966,7 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_tx_timeout         = ehea_tx_watchdog,
 };
 
-struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
+static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                                         u32 logical_port_id,
                                         struct device_node *dn)
 {
@@ -3237,7 +3237,7 @@ static ssize_t ehea_remove_port(struct device *dev,
 static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
 static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
 
-int ehea_create_device_sysfs(struct platform_device *dev)
+static int ehea_create_device_sysfs(struct platform_device *dev)
 {
        int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
        if (ret)
@@ -3248,7 +3248,7 @@ out:
        return ret;
 }
 
-void ehea_remove_device_sysfs(struct platform_device *dev)
+static void ehea_remove_device_sysfs(struct platform_device *dev)
 {
        device_remove_file(&dev->dev, &dev_attr_probe_port);
        device_remove_file(&dev->dev, &dev_attr_remove_port);
@@ -3379,7 +3379,7 @@ static int __devexit ehea_remove(struct platform_device *dev)
        return 0;
 }
 
-void ehea_crash_handler(void)
+static void ehea_crash_handler(void)
 {
        int i;
 
@@ -3491,7 +3491,7 @@ static ssize_t ehea_show_capabilities(struct device_driver *drv,
 static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
                   ehea_show_capabilities, NULL);
 
-int __init ehea_module_init(void)
+static int __init ehea_module_init(void)
 {
        int ret;
 
index 95b9f4fa811e7102cc6db2248dbabf1af7e3d1e9..c25b05b94daae698e0b8640e40da8614ea9ad4f7 100644 (file)
@@ -34,9 +34,7 @@
 #include "ehea_phyp.h"
 #include "ehea_qmr.h"
 
-struct ehea_bmap *ehea_bmap = NULL;
-
-
+static struct ehea_bmap *ehea_bmap;
 
 static void *hw_qpageit_get_inc(struct hw_queue *queue)
 {
@@ -212,7 +210,7 @@ out_nomem:
        return NULL;
 }
 
-u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
+static u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
 {
        u64 hret;
        u64 adapter_handle = cq->adapter->handle;
@@ -337,7 +335,7 @@ struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)
        return eqe;
 }
 
-u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force)
+static u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force)
 {
        u64 hret;
        unsigned long flags;
@@ -381,7 +379,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
 /**
  * allocates memory for a queue and registers pages in phyp
  */
-int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue,
+static int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue,
                           int nr_pages, int wqe_size, int act_nr_sges,
                           struct ehea_adapter *adapter, int h_call_q_selector)
 {
@@ -516,7 +514,7 @@ out_freemem:
        return NULL;
 }
 
-u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
+static u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
 {
        u64 hret;
        struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
@@ -976,7 +974,7 @@ int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr,
        return 0;
 }
 
-void print_error_data(u64 *data)
+static void print_error_data(u64 *data)
 {
        int length;
        u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
index 669ca3800c01a15ced19745c9af8f6312b651f4e..d94d64b5d695d1fccd5ec22aef09805d046dc4b9 100644 (file)
@@ -4740,12 +4740,14 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
                e1000_setup_rctl(adapter);
                e1000_set_rx_mode(netdev);
 
+               rctl = er32(RCTL);
+
                /* turn on all-multi mode if wake on multicast is enabled */
-               if (wufc & E1000_WUFC_MC) {
-                       rctl = er32(RCTL);
+               if (wufc & E1000_WUFC_MC)
                        rctl |= E1000_RCTL_MPE;
-                       ew32(RCTL, rctl);
-               }
+
+               /* enable receives in the hardware */
+               ew32(RCTL, rctl | E1000_RCTL_EN);
 
                if (hw->mac_type >= e1000_82540) {
                        ctrl = er32(CTRL);
index c6e4621b62624991ec1e0f32a0bbfee410f9f55c..6565c463185c2a8f705ceee712005643f9a7389d 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2011 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
index b8e20f037d0a8314789f236a31b4f723ef549b72..08bdc33715eeabbb793b778fd98a4aafdc8c5bc5 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 08a757eb6608c73bc05e4a8569301e71c4ba05cf..b927d79ab536c19a09ce0fdf8ac00b6ebb18a47a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index f5fc5725ea94b33c81480fab0fa200498513b013..aed217449f0dd459eebd13dfff3006a5dd414b06 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 4519a13671708c0ba493a3e3e3c332a8b75a3431..f67cbd3fa307a966a377f6f7b9a089b3b7163c92 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 73aac082c44dbe5b3cbbbbca2d01a225c3440df0..f57338afd71f47681a3436ee769d6fb02cd14b06 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -151,7 +151,7 @@ void igb_clear_vfta_i350(struct e1000_hw *hw)
  *  Writes value at the given offset in the register array which stores
  *  the VLAN filter table.
  **/
-void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
 {
        int i;
 
index e45996b4ea346e299070bafe20fd73931c1dd0c3..cbddc4e51e30d9c304b11c75250d04ddde39c5b7 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 469d95eaa1547ae5136c4c8f2e1cf8b14e0396c5..5988b8958baff22cfb0f2de6f71eae4fc578681a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index eddb0f83dceac6a3ad82e7ad2e9dd0541bb6ca36..dbcfa3d5caeca753cf22a4f37e9cb313d9c30fa7 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 40407124e7222090c364aa960cfc303115a9571f..fa2c6ba6213941d31824d594f30b9ed9c08ba5b5 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index a2a7ca9fa733148fbfc5f42eb7c49df35f7e0bad..825b0228cac0ac5c17dcd9a903240b9a17d95e6b 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2011 Intel Corporation.
+  Copyright(c) 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index b17d7c20f8177816434f914f15635b3624361d5e..789de5b83aad94071aec54f04e7979e9cfd82d7c 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 8510797b9d810a95007c129f591f3c239acc2ef7..4c32ac66ff39413e78eaeb214ff0a55de259cfee 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 0a860bc1198ef977f984579a2f9dd0656e1d6ae2..ccdf36d503fdc54ea753e02bfa780c9c1b9055d9 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 3d12e67eebb4af328b03f00196841a228cfca65e..8e33bdd33eea5663c208dc6db16ca7f5371102ae 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 7998bf4d594683b73aa476a1ee9156dc1a220511..aa399a8a8f0df2ba23bc8cf0e1ae0b04f58f9469 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 01e5e89ef959eb9317be078f2f3a0e50607d9abc..94be6c32fa7d9359c984349dce845720acefe795 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -68,7 +68,7 @@ char igb_driver_name[] = "igb";
 char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
                                "Intel(R) Gigabit Ethernet Network Driver";
-static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation.";
+static const char igb_copyright[] = "Copyright (c) 2007-2012 Intel Corporation.";
 
 static const struct e1000_info *igb_info_tbl[] = {
        [board_82575] = &e1000_82575_info,
@@ -4003,8 +4003,8 @@ set_itr_now:
        }
 }
 
-void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
-                    u32 type_tucmd, u32 mss_l4len_idx)
+static void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
+                           u32 type_tucmd, u32 mss_l4len_idx)
 {
        struct e1000_adv_tx_context_desc *context_desc;
        u16 i = tx_ring->next_to_use;
@@ -5012,7 +5012,8 @@ static int igb_find_enabled_vfs(struct igb_adapter *adapter)
        vf_devfn = pdev->devfn + 0x80;
        pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);
        while (pvfdev) {
-               if (pvfdev->devfn == vf_devfn)
+               if (pvfdev->devfn == vf_devfn &&
+                   (pvfdev->bus->number >= pdev->bus->number))
                        vfs_found++;
                vf_devfn += vf_stride;
                pvfdev = pci_get_device(hw->vendor_id,
@@ -5623,7 +5624,7 @@ static irqreturn_t igb_intr(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-void igb_ring_irq_enable(struct igb_q_vector *q_vector)
+static void igb_ring_irq_enable(struct igb_q_vector *q_vector)
 {
        struct igb_adapter *adapter = q_vector->adapter;
        struct e1000_hw *hw = &adapter->hw;
index 0fa3db3dd8b664d133c80902e09e7bca2aacbcc9..044b0ad5fcb948298861bdafb905b9797a7f1f3f 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel(R) 82576 Virtual Function Linux driver
-# Copyright(c) 2009 - 2010 Intel Corporation.
+# Copyright(c) 2009 - 2012 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
index 79f2604673feaa8a40c306b559eeff1adb3f2e6c..33f40d3474ae46ef5f4e932c86296a591bbb6301 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 7b600a1f6366f811d31ae38fd12cab1c6d452505..db7dce2351c2ca706e22fe93a478224e5bb54720 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -468,6 +468,5 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
 
 void igbvf_set_ethtool_ops(struct net_device *netdev)
 {
-       /* have to "undeclare" const on this struct to remove warnings */
-       SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
+       SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops);
 }
index fd4a7b780fdde3ebf198324c146a28a5b5b53f5b..2c6d87e4d3d98d87b1eba31b9904de2a2fab9bd4 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 048aae248d06ab469a6ba6dcd6e2a365784f85b4..b4b65bc9fc5dd0852969eb1942d347bc2994cef4 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index c2883c45d477434aed8ecfaacd51b5e3503be009..24370bcb0e22dd3d1b386d2404903840e08c37f3 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index fd3da3076c2f3bc6b10032defa1a838d0b5c59ef..4e9141cfe81d835078508e5c69bdeea948f6af65 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -53,7 +53,7 @@ const char igbvf_driver_version[] = DRV_VERSION;
 static const char igbvf_driver_string[] =
                  "Intel(R) Gigabit Virtual Function Network Driver";
 static const char igbvf_copyright[] =
-                 "Copyright (c) 2009 - 2011 Intel Corporation.";
+                 "Copyright (c) 2009 - 2012 Intel Corporation.";
 
 static int igbvf_poll(struct napi_struct *napi, int budget);
 static void igbvf_reset(struct igbvf_adapter *);
@@ -1194,11 +1194,6 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
        struct igbvf_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
 
-       igbvf_irq_disable(adapter);
-
-       if (!test_bit(__IGBVF_DOWN, &adapter->state))
-               igbvf_irq_enable(adapter);
-
        if (hw->mac.ops.set_vfta(hw, vid, false)) {
                dev_err(&adapter->pdev->dev,
                        "Failed to remove vlan id %d\n", vid);
index 77e18d3d6b1537303dd2b8599a023d9caeed99b4..7dc6341715dcd948d01adbd7fc032c5576be04ee 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index af3822f9ea9a28c1dc8c058cf5e4ef9e7f634ccf..19551977b352c1a2ceb8ed9a2864d7300cab52e1 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index d7ed58fcd9bbb326c564cb7c923406dac07f4e48..57db3c68dfcd2f5a8fca5a06de4aa52aa901b1eb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 - 2010 Intel Corporation.
+  Copyright(c) 2009 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 7d7387fbdecd33e2c589857cbe5f375b576b0d21..7a16177a12a5c15b298ecd4b0caf19005bd397f2 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 10 Gigabit PCI Express Linux driver
-# Copyright(c) 1999 - 2010 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
index 258164d6d45a1d1bda1f33e7afe3b84b30afe710..e6aeb64105a49ab0a78ad097a0af45aa3140886d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index ef2afefb0cd49dc13e9dcafd3abde34d8e795d4a..b406c367b19074a8efee8aea07d4ece207f2d625 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 772072147bea6fac57d0a6d0a0056fd6d42a78d0..4e59083a3de2404766b1357c7dcb6890d79988dd 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index a3aa6333073f0727b67d5c4bb0ea4fe0ef31e6ee..383b9413292e8b3f1e3fcad83716f0adafb6ac4d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 863f9c1f145baa46684537bb405394ad389e4680..2c834c46bba15ab85e7583e3156b6e53264bb389 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -75,7 +75,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
 s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
 s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packtetbuf_num);
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
 s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
 
 s32 ixgbe_validate_mac_addr(u8 *mac_addr);
index 318caf4bf623cbeff04d4c9881ee4347fe26c0ac..8bfaaee5ac5b58964a70e54f39c7e21d041178b6 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index e162775064da356b39e4e4bd81f20f2b5d6aef9c..24333b7181665132d49f754aa46ce0a179add250 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index fcd0e479721f793a975fe4ae3b2d374ac733f330..d3695edfcb8b7ce6f10bfd5fcf722d55235714cd 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 2f318935561a75e16051b9037178060f20def1c6..ba835708fcace01dec3e34d3bb09b43ffe5376fc 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 32cd97bc794d1e5f726ed99adc0f1f63b59f841e..888a419dc3d9736ed8c1abfe9ea26e94a4e1c91a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index a59d5dc59d046fcd959621a2744456e7a3aca768..4dec47faeb00566beb5dabe3715f0304d1a7d3d1 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index da31735311f137091e9447e189491e4b223a40ed..79a92fe987b997d203d6afde03f428bed78bb7fb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -112,6 +112,8 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
 static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 {
        u8 err = 0;
+       u8 prio_tc[MAX_USER_PRIORITY] = {0};
+       int i;
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
        /* Fail command if not in CEE mode */
@@ -122,10 +124,15 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
        if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
                return err;
 
-       if (state > 0)
+       if (state > 0) {
                err = ixgbe_setup_tc(netdev, adapter->dcb_cfg.num_tcs.pg_tcs);
-       else
+               ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc);
+       } else {
                err = ixgbe_setup_tc(netdev, 0);
+       }
+
+       for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+               netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
 
        return err;
 }
index da7e580f517ae03528fed27eb2af79ea3df81aaa..a62975480e37b0c53b1908e531e216eed41f1308 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -58,7 +58,7 @@ struct ixgbe_stats {
                                sizeof(((struct rtnl_link_stats64 *)0)->m), \
                                offsetof(struct rtnl_link_stats64, m)
 
-static struct ixgbe_stats ixgbe_gstrings_stats[] = {
+static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
        {"rx_packets", IXGBE_NETDEV_STAT(rx_packets)},
        {"tx_packets", IXGBE_NETDEV_STAT(tx_packets)},
        {"rx_bytes", IXGBE_NETDEV_STAT(rx_bytes)},
@@ -120,19 +120,23 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
 #endif /* IXGBE_FCOE */
 };
 
-#define IXGBE_QUEUE_STATS_LEN \
-       ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \
-       ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \
+/* ixgbe allocates num_tx_queues and num_rx_queues symmetrically so
+ * we set the num_rx_queues to evaluate to num_tx_queues. This is
+ * used because we do not have a good way to get the max number of
+ * rx queues with CONFIG_RPS disabled.
+ */
+#define IXGBE_NUM_RX_QUEUES netdev->num_tx_queues
+
+#define IXGBE_QUEUE_STATS_LEN ( \
+       (netdev->num_tx_queues + IXGBE_NUM_RX_QUEUES) * \
        (sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
 #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)
 #define IXGBE_PB_STATS_LEN ( \
-                 (((struct ixgbe_adapter *)netdev_priv(netdev))->flags & \
-                 IXGBE_FLAG_DCB_ENABLED) ? \
-                 (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \
-                  sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \
-                  sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \
-                  sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \
-                  / sizeof(u64) : 0)
+                       (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \
+                        sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \
+                        sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \
+                        sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \
+                       / sizeof(u64))
 #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \
                          IXGBE_PB_STATS_LEN + \
                          IXGBE_QUEUE_STATS_LEN)
@@ -1078,8 +1082,15 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                data[i] = (ixgbe_gstrings_stats[i].sizeof_stat ==
                           sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
        }
-       for (j = 0; j < adapter->num_tx_queues; j++) {
+       for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {
                ring = adapter->tx_ring[j];
+               if (!ring) {
+                       data[i] = 0;
+                       data[i+1] = 0;
+                       i += 2;
+                       continue;
+               }
+
                do {
                        start = u64_stats_fetch_begin_bh(&ring->syncp);
                        data[i]   = ring->stats.packets;
@@ -1087,8 +1098,15 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
                i += 2;
        }
-       for (j = 0; j < adapter->num_rx_queues; j++) {
+       for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {
                ring = adapter->rx_ring[j];
+               if (!ring) {
+                       data[i] = 0;
+                       data[i+1] = 0;
+                       i += 2;
+                       continue;
+               }
+
                do {
                        start = u64_stats_fetch_begin_bh(&ring->syncp);
                        data[i]   = ring->stats.packets;
@@ -1096,22 +1114,20 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
                i += 2;
        }
-       if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-               for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
-                       data[i++] = adapter->stats.pxontxc[j];
-                       data[i++] = adapter->stats.pxofftxc[j];
-               }
-               for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) {
-                       data[i++] = adapter->stats.pxonrxc[j];
-                       data[i++] = adapter->stats.pxoffrxc[j];
-               }
+
+       for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) {
+               data[i++] = adapter->stats.pxontxc[j];
+               data[i++] = adapter->stats.pxofftxc[j];
+       }
+       for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) {
+               data[i++] = adapter->stats.pxonrxc[j];
+               data[i++] = adapter->stats.pxoffrxc[j];
        }
 }
 
 static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
                               u8 *data)
 {
-       struct ixgbe_adapter *adapter = netdev_priv(netdev);
        char *p = (char *)data;
        int i;
 
@@ -1126,31 +1142,29 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
                               ETH_GSTRING_LEN);
                        p += ETH_GSTRING_LEN;
                }
-               for (i = 0; i < adapter->num_tx_queues; i++) {
+               for (i = 0; i < netdev->num_tx_queues; i++) {
                        sprintf(p, "tx_queue_%u_packets", i);
                        p += ETH_GSTRING_LEN;
                        sprintf(p, "tx_queue_%u_bytes", i);
                        p += ETH_GSTRING_LEN;
                }
-               for (i = 0; i < adapter->num_rx_queues; i++) {
+               for (i = 0; i < IXGBE_NUM_RX_QUEUES; i++) {
                        sprintf(p, "rx_queue_%u_packets", i);
                        p += ETH_GSTRING_LEN;
                        sprintf(p, "rx_queue_%u_bytes", i);
                        p += ETH_GSTRING_LEN;
                }
-               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-                       for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
-                               sprintf(p, "tx_pb_%u_pxon", i);
-                               p += ETH_GSTRING_LEN;
-                               sprintf(p, "tx_pb_%u_pxoff", i);
-                               p += ETH_GSTRING_LEN;
-                       }
-                       for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) {
-                               sprintf(p, "rx_pb_%u_pxon", i);
-                               p += ETH_GSTRING_LEN;
-                               sprintf(p, "rx_pb_%u_pxoff", i);
-                               p += ETH_GSTRING_LEN;
-                       }
+               for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
+                       sprintf(p, "tx_pb_%u_pxon", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "tx_pb_%u_pxoff", i);
+                       p += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
+                       sprintf(p, "rx_pb_%u_pxon", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "rx_pb_%u_pxoff", i);
+                       p += ETH_GSTRING_LEN;
                }
                /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */
                break;
index d18d6157dd2c4850acce62c3a6137c1cee609ca5..4bc794249801eed3dd5ce16d0cb7e9b163ed6849 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 261fd62dda1861950e5a43bbe41c68665d5f214e..1dbed17c8107bf1b6eb78f1331957b120dd28815 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 1ee5d0fbb905ba0ad1b89210c264a246b4553e99..3dc6cef58107f9cb260d4b35be65df8a7652c87d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -64,7 +64,7 @@ char ixgbe_default_device_descr[] =
        __stringify(BUILD) "-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
-                               "Copyright (c) 1999-2011 Intel Corporation.";
+                               "Copyright (c) 1999-2012 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
        [board_82598] = &ixgbe_82598_info,
@@ -2633,22 +2633,22 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
        /*
         * we must limit the number of descriptors so that the
         * total size of max desc * buf_len is not greater
-        * than 65535
+        * than 65536
         */
        if (ring_is_ps_enabled(ring)) {
-#if (MAX_SKB_FRAGS > 16)
+#if (PAGE_SIZE < 8192)
                rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-#elif (MAX_SKB_FRAGS > 8)
+#elif (PAGE_SIZE < 16384)
                rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
-#elif (MAX_SKB_FRAGS > 4)
+#elif (PAGE_SIZE < 32768)
                rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
 #else
                rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
 #endif
        } else {
-               if (rx_buf_len < IXGBE_RXBUFFER_4K)
+               if (rx_buf_len <= IXGBE_RXBUFFER_4K)
                        rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-               else if (rx_buf_len < IXGBE_RXBUFFER_8K)
+               else if (rx_buf_len <= IXGBE_RXBUFFER_8K)
                        rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
                else
                        rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
@@ -2830,7 +2830,7 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
        IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
 
        vf_shift = adapter->num_vfs % 32;
-       reg_offset = (adapter->num_vfs > 32) ? 1 : 0;
+       reg_offset = (adapter->num_vfs >= 32) ? 1 : 0;
 
        /* Enable only the PF's pool for Tx/Rx */
        IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
@@ -4330,6 +4330,10 @@ static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
        adapter->num_tx_queues = 1;
 
 done:
+       if ((adapter->netdev->reg_state == NETREG_UNREGISTERED) ||
+           (adapter->netdev->reg_state == NETREG_UNREGISTERING))
+               return 0;
+
        /* Notify the stack of the (possibly) reduced queue counts. */
        netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
        return netif_set_real_num_rx_queues(adapter->netdev,
index 3f725d48336d121ec962b2f7839e6eca07ae19ce..1f3e32b576a56f255a0fcf22805b051ada16304e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index b239bdac38da734ebf1de50c5ae8c3409d40a53a..310bdd9610757558827d31155ad1bc839d617bfb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 7cf1e1f56c69664d9397c46f554dc38701bdb81e..b91773551a381bf223b0b91c4837b581acd93d42 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 197bdd13106a5398804ea0f083c088815470d9ee..cc18165b4c05b55ce1bd01c51ca8b81f36aa4ca9 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index cf6812dd1436116ab23beb0cf57b1ab7732c8b38..b01ecb4d2bb1aaea3cc94f6ad64cd66bada6c38e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -67,7 +67,8 @@ static int ixgbe_find_enabled_vfs(struct ixgbe_adapter *adapter)
        vf_devfn = pdev->devfn + 0x80;
        pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);
        while (pvfdev) {
-               if (pvfdev->devfn == vf_devfn)
+               if (pvfdev->devfn == vf_devfn &&
+                   (pvfdev->bus->number >= pdev->bus->number))
                        vfs_found++;
                vf_devfn += 2;
                pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID,
@@ -646,6 +647,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
                        ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
                retval = ixgbe_set_vf_macvlan(adapter, vf, index,
                                              (unsigned char *)(&msgbuf[1]));
+               if (retval == -ENOSPC)
+                       e_warn(drv, "VF %d has requested a MACVLAN filter "
+                                   "but there is no space for it\n", vf);
                break;
        default:
                e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
index e8badab033590179ff5056c2c0a8f61cce69b9c4..2ab38d5fda92a16a00908053f270ee3f1a26a39d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 802bfa0f62cc022c34965c32343719749e1c4ca7..9b95bef6097006e07b18d49fe0ae90a825c5d100 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
 
 /* Receive DMA Registers */
 #define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \
-                         (0x0D000 + ((_i - 64) * 0x40)))
+                        (0x0D000 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \
-                         (0x0D004 + ((_i - 64) * 0x40)))
+                        (0x0D004 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \
-                         (0x0D008 + ((_i - 64) * 0x40)))
+                        (0x0D008 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDH(_i)   (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \
-                         (0x0D010 + ((_i - 64) * 0x40)))
+                        (0x0D010 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDT(_i)   (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \
-                         (0x0D018 + ((_i - 64) * 0x40)))
+                        (0x0D018 + (((_i) - 64) * 0x40)))
 #define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \
-                          (0x0D028 + ((_i - 64) * 0x40)))
+                        (0x0D028 + (((_i) - 64) * 0x40)))
 #define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
-                          (0x0D02C + ((_i - 64) * 0x40)))
+                        (0x0D02C + (((_i) - 64) * 0x40)))
 #define IXGBE_RSCDBU     0x03028
 #define IXGBE_RDDCC      0x02F20
 #define IXGBE_RXMEMWRAP  0x03190
  */
 #define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
                           (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
-                          (0x0D014 + ((_i - 64) * 0x40))))
+                         (0x0D014 + (((_i) - 64) * 0x40))))
 /*
  * Rx DCA Control Register:
  * 00-15 : 0x02200 + n*4
  */
 #define IXGBE_DCA_RXCTRL(_i)    (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
                                  (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
-                                 (0x0D00C + ((_i - 64) * 0x40))))
+                                (0x0D00C + (((_i) - 64) * 0x40))))
 #define IXGBE_RDRXCTL           0x02F00
 #define IXGBE_RXPBSIZE(_i)      (0x03C00 + ((_i) * 4))
                                              /* 8 of these 0x03C00 - 0x03C1C */
 
 #define IXGBE_WUPL      0x05900
 #define IXGBE_WUPM      0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */
-#define IXGBE_FHFT(_n)     (0x09000 + (_n * 0x100)) /* Flex host filter table */
-#define IXGBE_FHFT_EXT(_n) (0x09800 + (_n * 0x100)) /* Ext Flexible Host
-                                                     * Filter Table */
+#define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */
+#define IXGBE_FHFT_EXT(_n)     (0x09800 + ((_n) * 0x100)) /* Ext Flexible Host
+                                                           * Filter Table */
 
 #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX         4
 #define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX     2
@@ -1485,7 +1485,7 @@ enum {
 #define IXGBE_LED_BLINK_BASE     0x00000080
 #define IXGBE_LED_MODE_MASK_BASE 0x0000000F
 #define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i)))
-#define IXGBE_LED_MODE_SHIFT(_i) (8*(_i))
+#define IXGBE_LED_MODE_SHIFT(_i) (8 * (_i))
 #define IXGBE_LED_IVRT(_i)       IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i)
 #define IXGBE_LED_BLINK(_i)      IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i)
 #define IXGBE_LED_MODE_MASK(_i)  IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i)
@@ -2068,9 +2068,9 @@ enum {
 
 /* SR-IOV specific macros */
 #define IXGBE_MBVFICR_INDEX(vf_number)   (vf_number >> 4)
-#define IXGBE_MBVFICR(_i)                (0x00710 + (_i * 4))
-#define IXGBE_VFLRE(_i)                  (((_i & 1) ? 0x001C0 : 0x00600))
-#define IXGBE_VFLREC(_i)                 (0x00700 + (_i * 4))
+#define IXGBE_MBVFICR(_i)              (0x00710 + ((_i) * 4))
+#define IXGBE_VFLRE(_i)                ((((_i) & 1) ? 0x001C0 : 0x00600))
+#define IXGBE_VFLREC(_i)               (0x00700 + ((_i) * 4))
 
 enum ixgbe_fdir_pballoc_type {
        IXGBE_FDIR_PBALLOC_NONE = 0,
index 8cc5eccfd65194a0a738b969f0f9b97529842d9f..f838a2be8cfb912a61fd72424e763c1d887067c8 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 1f35d229e71ad4a3fca37105361a2c0adef10fd6..4ce4c97ef5ad441c78afc8ceaf35fa34dfefb162 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 82599 Virtual Function driver
-# Copyright(c) 1999 - 2010 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
index 2eb89cb94a0d4c45a14831cda8e875878a4679e0..947b5c830735f6a26057d585a5042d31e20ccbcb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index dc8e6511c64068debdb4cec9887b321e348a9ea9..2bfe0d1d7958cba80d5396aa3a64178ed5e028ae 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -56,7 +56,8 @@ struct ixgbe_stats {
                            offsetof(struct ixgbevf_adapter, m),         \
                            offsetof(struct ixgbevf_adapter, b),         \
                            offsetof(struct ixgbevf_adapter, r)
-static struct ixgbe_stats ixgbe_gstrings_stats[] = {
+
+static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
        {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc,
                                    stats.saved_reset_vfgprc)},
        {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc,
@@ -671,7 +672,7 @@ static int ixgbevf_nway_reset(struct net_device *netdev)
        return 0;
 }
 
-static struct ethtool_ops ixgbevf_ethtool_ops = {
+static const struct ethtool_ops ixgbevf_ethtool_ops = {
        .get_settings           = ixgbevf_get_settings,
        .get_drvinfo            = ixgbevf_get_drvinfo,
        .get_regs_len           = ixgbevf_get_regs_len,
index e6c9d1a927a9d0e06b003341b78f9b44620ed8c5..dfed420a1bf6e6fe7fa05a5f32b306f81ec00220 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -279,12 +279,12 @@ enum ixgbevf_boards {
        board_X540_vf,
 };
 
-extern struct ixgbevf_info ixgbevf_82599_vf_info;
-extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
+extern const struct ixgbevf_info ixgbevf_82599_vf_info;
+extern const struct ixgbevf_info ixgbevf_X540_vf_info;
+extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
 
 /* needed by ethtool.c */
-extern char ixgbevf_driver_name[];
+extern const char ixgbevf_driver_name[];
 extern const char ixgbevf_driver_version[];
 
 extern int ixgbevf_up(struct ixgbevf_adapter *adapter);
index 891162d1610ca6e21eaf88ab41cd07c918292327..e51d552410ae1426e8cdcaaf5f327f4bd95009fe 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
 
 #include "ixgbevf.h"
 
-char ixgbevf_driver_name[] = "ixgbevf";
+const char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
        "Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
 #define DRV_VERSION "2.2.0-k"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
-       "Copyright (c) 2009 - 2010 Intel Corporation.";
+       "Copyright (c) 2009 - 2012 Intel Corporation.";
 
 static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
        [board_82599_vf] = &ixgbevf_82599_vf_info,
@@ -917,32 +917,39 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
        struct ixgbe_hw *hw = &adapter->hw;
        u32 eicr;
        u32 msg;
+       bool got_ack = false;
 
        eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS);
        IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr);
 
-       if (!hw->mbx.ops.check_for_ack(hw)) {
+       if (!hw->mbx.ops.check_for_ack(hw))
+               got_ack = true;
+
+       if (!hw->mbx.ops.check_for_msg(hw)) {
+               hw->mbx.ops.read(hw, &msg, 1);
+
+               if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
+                       mod_timer(&adapter->watchdog_timer,
+                                 round_jiffies(jiffies + 1));
+
+               if (msg & IXGBE_VT_MSGTYPE_NACK)
+                       pr_warn("Last Request of type %2.2x to PF Nacked\n",
+                               msg & 0xFF);
                /*
-                * checking for the ack clears the PFACK bit.  Place
-                * it back in the v2p_mailbox cache so that anyone
-                * polling for an ack will not miss it.  Also
-                * avoid the read below because the code to read
-                * the mailbox will also clear the ack bit.  This was
-                * causing lost acks.  Just cache the bit and exit
-                * the IRQ handler.
+                * Restore the PFSTS bit in case someone is polling for a
+                * return message from the PF
                 */
-               hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
-               goto out;
+               hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFSTS;
        }
 
-       /* Not an ack interrupt, go ahead and read the message */
-       hw->mbx.ops.read(hw, &msg, 1);
-
-       if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
-               mod_timer(&adapter->watchdog_timer,
-                         round_jiffies(jiffies + 1));
+       /*
+        * checking for the ack clears the PFACK bit.  Place
+        * it back in the v2p_mailbox cache so that anyone
+        * polling for an ack will not miss it
+        */
+       if (got_ack)
+               hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
 
-out:
        return IRQ_HANDLED;
 }
 
index 930fa83f256881eb1bebbe29ad4c1f60fc20af9e..9c955900fe649deb1b7287443f2f2a5d9f21728a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -26,6 +26,7 @@
 *******************************************************************************/
 
 #include "mbx.h"
+#include "ixgbevf.h"
 
 /**
  *  ixgbevf_poll_for_msg - Wait for message notification
@@ -328,7 +329,7 @@ static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
        return 0;
 }
 
-struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
+const struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
        .init_params   = ixgbevf_init_mbx_params_vf,
        .read          = ixgbevf_read_mbx_vf,
        .write         = ixgbevf_write_mbx_vf,
index 9d38a94a348aed51fa6abdeae320155eb8fcde7a..cf9131c5c1150aa6746e5201f280ec5a87c9bf91 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 5e4d5e5cdf38dc794f791fdc95b9e2ade58566db..debd8c0e1f28df74db51c04809beeff3f2a9855c 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
index 21533e300367f78dd4058ee2df7ba31c7df1122c..74be7411242a25de2662e84756fa8656e411465e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -26,6 +26,7 @@
 *******************************************************************************/
 
 #include "vf.h"
+#include "ixgbevf.h"
 
 /**
  *  ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
@@ -282,6 +283,17 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
        return ret_val;
 }
 
+static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,
+                                       u32 *msg, u16 size)
+{
+       struct ixgbe_mbx_info *mbx = &hw->mbx;
+       u32 retmsg[IXGBE_VFMAILBOX_SIZE];
+       s32 retval = mbx->ops.write_posted(hw, msg, size);
+
+       if (!retval)
+               mbx->ops.read_posted(hw, retmsg, size);
+}
+
 /**
  *  ixgbevf_update_mc_addr_list_vf - Update Multicast addresses
  *  @hw: pointer to the HW structure
@@ -293,7 +305,6 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
                                          struct net_device *netdev)
 {
        struct netdev_hw_addr *ha;
-       struct ixgbe_mbx_info *mbx = &hw->mbx;
        u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
        u16 *vector_list = (u16 *)&msgbuf[1];
        u32 cnt, i;
@@ -320,7 +331,7 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
                vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
        }
 
-       mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);
+       ixgbevf_write_msg_read_ack(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);
 
        return 0;
 }
@@ -335,7 +346,6 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
 static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
                               bool vlan_on)
 {
-       struct ixgbe_mbx_info *mbx = &hw->mbx;
        u32 msgbuf[2];
 
        msgbuf[0] = IXGBE_VF_SET_VLAN;
@@ -343,7 +353,9 @@ static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
        /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
        msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT;
 
-       return mbx->ops.write_posted(hw, msgbuf, 2);
+       ixgbevf_write_msg_read_ack(hw, msgbuf, 2);
+
+       return 0;
 }
 
 /**
@@ -401,7 +413,7 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
        return 0;
 }
 
-static struct ixgbe_mac_operations ixgbevf_mac_ops = {
+static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
        .init_hw             = ixgbevf_init_hw_vf,
        .reset_hw            = ixgbevf_reset_hw_vf,
        .start_hw            = ixgbevf_start_hw_vf,
@@ -415,12 +427,12 @@ static struct ixgbe_mac_operations ixgbevf_mac_ops = {
        .set_vfta            = ixgbevf_set_vfta_vf,
 };
 
-struct ixgbevf_info ixgbevf_82599_vf_info = {
+const struct ixgbevf_info ixgbevf_82599_vf_info = {
        .mac = ixgbe_mac_82599_vf,
        .mac_ops = &ixgbevf_mac_ops,
 };
 
-struct ixgbevf_info ixgbevf_X540_vf_info = {
+const struct ixgbevf_info ixgbevf_X540_vf_info = {
        .mac = ixgbe_mac_X540_vf,
        .mac_ops = &ixgbevf_mac_ops,
 };
index 10306b492ee61b5b9e686503839281b35b9df1fb..25c951daee5d3042c85e54b9944d0fda3fb855a0 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -167,7 +167,7 @@ struct ixgbevf_hw_stats {
 
 struct ixgbevf_info {
        enum ixgbe_mac_type             mac;
-       struct ixgbe_mac_operations     *mac_ops;
+       const struct ixgbe_mac_operations *mac_ops;
 };
 
 #endif /* __IXGBE_VF_H__ */
index 9c049d2cb97d00142b1fbfaa6a1b14b6f8fac580..9edecfa1f0f4ffb556d73cbda06db380f9bdeeb8 100644 (file)
@@ -136,6 +136,8 @@ static char mv643xx_eth_driver_version[] = "1.4";
 #define INT_MASK                       0x0068
 #define INT_MASK_EXT                   0x006c
 #define TX_FIFO_URGENT_THRESHOLD       0x0074
+#define RX_DISCARD_FRAME_CNT           0x0084
+#define RX_OVERRUN_FRAME_CNT           0x0088
 #define TXQ_FIX_PRIO_CONF_MOVED                0x00dc
 #define TX_BW_RATE_MOVED               0x00e0
 #define TX_BW_MTU_MOVED                        0x00e8
@@ -334,6 +336,9 @@ struct mib_counters {
        u32 bad_crc_event;
        u32 collision;
        u32 late_collision;
+       /* Non MIB hardware counters */
+       u32 rx_discard;
+       u32 rx_overrun;
 };
 
 struct lro_counters {
@@ -1225,6 +1230,10 @@ static void mib_counters_clear(struct mv643xx_eth_private *mp)
 
        for (i = 0; i < 0x80; i += 4)
                mib_read(mp, i);
+
+       /* Clear non MIB hw counters also */
+       rdlp(mp, RX_DISCARD_FRAME_CNT);
+       rdlp(mp, RX_OVERRUN_FRAME_CNT);
 }
 
 static void mib_counters_update(struct mv643xx_eth_private *mp)
@@ -1262,6 +1271,9 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
        p->bad_crc_event += mib_read(mp, 0x74);
        p->collision += mib_read(mp, 0x78);
        p->late_collision += mib_read(mp, 0x7c);
+       /* Non MIB hardware counters */
+       p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);
+       p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);
        spin_unlock_bh(&mp->mib_counters_lock);
 
        mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
@@ -1413,6 +1425,8 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
        MIBSTAT(bad_crc_event),
        MIBSTAT(collision),
        MIBSTAT(late_collision),
+       MIBSTAT(rx_discard),
+       MIBSTAT(rx_overrun),
        LROSTAT(lro_aggregated),
        LROSTAT(lro_flushed),
        LROSTAT(lro_no_desc),
index 18a87a57fc0aa4ca9ff3bb406a9633fc281bc308..33947ac595c04bb2c4e1977572c9c435d6d45b8c 100644 (file)
@@ -2576,6 +2576,7 @@ static int skge_up(struct net_device *dev)
        }
 
        /* Initialize MAC */
+       netif_carrier_off(dev);
        spin_lock_bh(&hw->phy_lock);
        if (is_genesis(hw))
                genesis_mac_init(hw, port);
@@ -2797,6 +2798,8 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
        td->control = BMU_OWN | BMU_SW | BMU_STF | control | len;
        wmb();
 
+       netdev_sent_queue(dev, skb->len);
+
        skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
 
        netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev,
@@ -2816,11 +2819,9 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
 
 
 /* Free resources associated with this reing element */
-static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
-                        u32 control)
+static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e,
+                                u32 control)
 {
-       struct pci_dev *pdev = skge->hw->pdev;
-
        /* skb header vs. fragment */
        if (control & BMU_STF)
                pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr),
@@ -2830,13 +2831,6 @@ static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
                pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr),
                               dma_unmap_len(e, maplen),
                               PCI_DMA_TODEVICE);
-
-       if (control & BMU_EOF) {
-               netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev,
-                            "tx done slot %td\n", e - skge->tx_ring.start);
-
-               dev_kfree_skb(e->skb);
-       }
 }
 
 /* Free all buffers in transmit ring */
@@ -2847,10 +2841,15 @@ static void skge_tx_clean(struct net_device *dev)
 
        for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
                struct skge_tx_desc *td = e->desc;
-               skge_tx_free(skge, e, td->control);
+
+               skge_tx_unmap(skge->hw->pdev, e, td->control);
+
+               if (td->control & BMU_EOF)
+                       dev_kfree_skb(e->skb);
                td->control = 0;
        }
 
+       netdev_reset_queue(dev);
        skge->tx_ring.to_clean = e;
 }
 
@@ -3111,6 +3110,7 @@ static void skge_tx_done(struct net_device *dev)
        struct skge_port *skge = netdev_priv(dev);
        struct skge_ring *ring = &skge->tx_ring;
        struct skge_element *e;
+       unsigned int bytes_compl = 0, pkts_compl = 0;
 
        skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
 
@@ -3120,8 +3120,20 @@ static void skge_tx_done(struct net_device *dev)
                if (control & BMU_OWN)
                        break;
 
-               skge_tx_free(skge, e, control);
+               skge_tx_unmap(skge->hw->pdev, e, control);
+
+               if (control & BMU_EOF) {
+                       netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev,
+                                    "tx done slot %td\n",
+                                    e - skge->tx_ring.start);
+
+                       pkts_compl++;
+                       bytes_compl += e->skb->len;
+
+                       dev_kfree_skb(e->skb);
+               }
        }
+       netdev_completed_queue(dev, pkts_compl, bytes_compl);
        skge->tx_ring.to_clean = e;
 
        /* Can run lockless until we need to synchronize to restart queue. */
index 978f593094c0402baa207d667c1c5b65a852f7c9..eaf09d4f02d08bb0e1ee41b78db6b83cc80287ea 100644 (file)
@@ -1247,6 +1247,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
        u32 reply;
        u32 slave_status = 0;
        u8 is_going_down = 0;
+       int i;
 
        slave_state[slave].comm_toggle ^= 1;
        reply = (u32) slave_state[slave].comm_toggle << 31;
@@ -1258,6 +1259,10 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
        if (cmd == MLX4_COMM_CMD_RESET) {
                mlx4_warn(dev, "Received reset from slave:%d\n", slave);
                slave_state[slave].active = false;
+               for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
+                               slave_state[slave].event_eq[i].eqn = -1;
+                               slave_state[slave].event_eq[i].token = 0;
+               }
                /*check if we are in the middle of FLR process,
                if so return "retry" status to the slave*/
                if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
@@ -1452,7 +1457,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_slave_state *s_state;
-       int i, err, port;
+       int i, j, err, port;
 
        priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
                                            &priv->mfunc.vhcr_dma,
@@ -1485,6 +1490,8 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                for (i = 0; i < dev->num_slaves; ++i) {
                        s_state = &priv->mfunc.master.slave_state[i];
                        s_state->last_cmd = MLX4_COMM_CMD_RESET;
+                       for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j)
+                               s_state->event_eq[j].eqn = -1;
                        __raw_writel((__force u32) 0,
                                     &priv->mfunc.comm[i].slave_write);
                        __raw_writel((__force u32) 0,
@@ -1609,12 +1616,12 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
                                kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
                }
                kfree(priv->mfunc.master.slave_state);
-               iounmap(priv->mfunc.comm);
-               dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
-                                                    priv->mfunc.vhcr,
-                                                    priv->mfunc.vhcr_dma);
-               priv->mfunc.vhcr = NULL;
        }
+
+       iounmap(priv->mfunc.comm);
+       dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
+                    priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
+       priv->mfunc.vhcr = NULL;
 }
 
 void mlx4_cmd_cleanup(struct mlx4_dev *dev)
index 475f9d6af9552b1c31c29bbcabc112653499d89e..7e64033d7de39ed7723c162c75e24cf49cd3d6fa 100644 (file)
@@ -96,7 +96,7 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
 static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
                         int cq_num)
 {
-       return mlx4_cmd(dev, mailbox->dma | dev->caps.function, cq_num, 0,
+       return mlx4_cmd(dev, mailbox->dma, cq_num, 0,
                        MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A,
                        MLX4_CMD_WRAPPED);
 }
@@ -111,7 +111,7 @@ static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
 static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
                         int cq_num)
 {
-       return mlx4_cmd_box(dev, dev->caps.function, mailbox ? mailbox->dma : 0,
+       return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
                            cq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ,
                            MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
 }
index 7dbc6a2307798a164b0e7f7520bcbfcb88634aa0..70346fd7f9c480d20bfd70ad90079fc99ae30181 100644 (file)
@@ -183,10 +183,11 @@ static int mlx4_en_set_wol(struct net_device *netdev,
 static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
+       int bit_count = hweight64(priv->stats_bitmap);
 
        switch (sset) {
        case ETH_SS_STATS:
-               return NUM_ALL_STATS +
+               return (priv->stats_bitmap ? bit_count : NUM_ALL_STATS) +
                        (priv->tx_ring_num + priv->rx_ring_num) * 2;
        case ETH_SS_TEST:
                return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
@@ -201,14 +202,34 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        int index = 0;
-       int i;
+       int i, j = 0;
 
        spin_lock_bh(&priv->stats_lock);
 
-       for (i = 0; i < NUM_MAIN_STATS; i++)
-               data[index++] = ((unsigned long *) &priv->stats)[i];
-       for (i = 0; i < NUM_PORT_STATS; i++)
-               data[index++] = ((unsigned long *) &priv->port_stats)[i];
+       if (!(priv->stats_bitmap)) {
+               for (i = 0; i < NUM_MAIN_STATS; i++)
+                       data[index++] =
+                               ((unsigned long *) &priv->stats)[i];
+               for (i = 0; i < NUM_PORT_STATS; i++)
+                       data[index++] =
+                               ((unsigned long *) &priv->port_stats)[i];
+               for (i = 0; i < NUM_PKT_STATS; i++)
+                       data[index++] =
+                               ((unsigned long *) &priv->pkstats)[i];
+       } else {
+               for (i = 0; i < NUM_MAIN_STATS; i++) {
+                       if ((priv->stats_bitmap >> j) & 1)
+                               data[index++] =
+                               ((unsigned long *) &priv->stats)[i];
+                       j++;
+               }
+               for (i = 0; i < NUM_PORT_STATS; i++) {
+                       if ((priv->stats_bitmap >> j) & 1)
+                               data[index++] =
+                               ((unsigned long *) &priv->port_stats)[i];
+                       j++;
+               }
+       }
        for (i = 0; i < priv->tx_ring_num; i++) {
                data[index++] = priv->tx_ring[i].packets;
                data[index++] = priv->tx_ring[i].bytes;
@@ -217,8 +238,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
                data[index++] = priv->rx_ring[i].packets;
                data[index++] = priv->rx_ring[i].bytes;
        }
-       for (i = 0; i < NUM_PKT_STATS; i++)
-               data[index++] = ((unsigned long *) &priv->pkstats)[i];
        spin_unlock_bh(&priv->stats_lock);
 
 }
@@ -247,11 +266,29 @@ static void mlx4_en_get_strings(struct net_device *dev,
 
        case ETH_SS_STATS:
                /* Add main counters */
-               for (i = 0; i < NUM_MAIN_STATS; i++)
-                       strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
-               for (i = 0; i< NUM_PORT_STATS; i++)
-                       strcpy(data + (index++) * ETH_GSTRING_LEN,
-                       main_strings[i + NUM_MAIN_STATS]);
+               if (!priv->stats_bitmap) {
+                       for (i = 0; i < NUM_MAIN_STATS; i++)
+                               strcpy(data + (index++) * ETH_GSTRING_LEN,
+                                       main_strings[i]);
+                       for (i = 0; i < NUM_PORT_STATS; i++)
+                               strcpy(data + (index++) * ETH_GSTRING_LEN,
+                                       main_strings[i +
+                                       NUM_MAIN_STATS]);
+                       for (i = 0; i < NUM_PKT_STATS; i++)
+                               strcpy(data + (index++) * ETH_GSTRING_LEN,
+                                       main_strings[i +
+                                       NUM_MAIN_STATS +
+                                       NUM_PORT_STATS]);
+               } else
+                       for (i = 0; i < NUM_MAIN_STATS + NUM_PORT_STATS; i++) {
+                               if ((priv->stats_bitmap >> i) & 1) {
+                                       strcpy(data +
+                                              (index++) * ETH_GSTRING_LEN,
+                                              main_strings[i]);
+                               }
+                               if (!(priv->stats_bitmap >> i))
+                                       break;
+                       }
                for (i = 0; i < priv->tx_ring_num; i++) {
                        sprintf(data + (index++) * ETH_GSTRING_LEN,
                                "tx%d_packets", i);
@@ -264,9 +301,6 @@ static void mlx4_en_get_strings(struct net_device *dev,
                        sprintf(data + (index++) * ETH_GSTRING_LEN,
                                "rx%d_bytes", i);
                }
-               for (i = 0; i< NUM_PKT_STATS; i++)
-                       strcpy(data + (index++) * ETH_GSTRING_LEN,
-                       main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
                break;
        }
 }
@@ -479,6 +513,95 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
        param->tx_pending = priv->tx_ring[0].size;
 }
 
+static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+
+       return priv->rx_ring_num;
+}
+
+static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+       int rss_rings;
+       size_t n = priv->rx_ring_num;
+       int err = 0;
+
+       rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
+
+       while (n--) {
+               ring_index[n] = rss_map->qps[n % rss_rings].qpn -
+                       rss_map->base_qpn;
+       }
+
+       return err;
+}
+
+static int mlx4_en_set_rxfh_indir(struct net_device *dev,
+               const u32 *ring_index)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_dev *mdev = priv->mdev;
+       int port_up = 0;
+       int err = 0;
+       int i;
+       int rss_rings = 0;
+
+       /* Calculate RSS table size and make sure flows are spread evenly
+        * between rings
+        */
+       for (i = 0; i < priv->rx_ring_num; i++) {
+               if (i > 0 && !ring_index[i] && !rss_rings)
+                       rss_rings = i;
+
+               if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
+                       return -EINVAL;
+       }
+
+       if (!rss_rings)
+               rss_rings = priv->rx_ring_num;
+
+       /* RSS table size must be an order of 2 */
+       if (!is_power_of_2(rss_rings))
+               return -EINVAL;
+
+       mutex_lock(&mdev->state_lock);
+       if (priv->port_up) {
+               port_up = 1;
+               mlx4_en_stop_port(dev);
+       }
+
+       priv->prof->rss_rings = rss_rings;
+
+       if (port_up) {
+               err = mlx4_en_start_port(dev);
+               if (err)
+                       en_err(priv, "Failed starting port\n");
+       }
+
+       mutex_unlock(&mdev->state_lock);
+       return err;
+}
+
+static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+                            u32 *rule_locs)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       int err = 0;
+
+       switch (cmd->cmd) {
+       case ETHTOOL_GRXRINGS:
+               cmd->data = priv->rx_ring_num;
+               break;
+       default:
+               err = -EOPNOTSUPP;
+               break;
+       }
+
+       return err;
+}
+
 const struct ethtool_ops mlx4_en_ethtool_ops = {
        .get_drvinfo = mlx4_en_get_drvinfo,
        .get_settings = mlx4_en_get_settings,
@@ -498,6 +621,10 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
        .set_pauseparam = mlx4_en_set_pauseparam,
        .get_ringparam = mlx4_en_get_ringparam,
        .set_ringparam = mlx4_en_set_ringparam,
+       .get_rxnfc = mlx4_en_get_rxnfc,
+       .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+       .get_rxfh_indir = mlx4_en_get_rxfh_indir,
+       .set_rxfh_indir = mlx4_en_set_rxfh_indir,
 };
 
 
index a06096fcc0b8bed5428b2b084fc2a66e94c10ad9..2097a7d3c5b82dabb482d9b670feef0ec1733d19 100644 (file)
@@ -62,10 +62,6 @@ static const char mlx4_en_version[] =
  * Device scope module parameters
  */
 
-
-/* Enable RSS TCP traffic */
-MLX4_EN_PARM_INT(tcp_rss, 1,
-                "Enable RSS for incomming TCP traffic or disabled (0)");
 /* Enable RSS UDP traffic */
 MLX4_EN_PARM_INT(udp_rss, 1,
                 "Enable RSS for incomming UDP traffic or disabled (0)");
@@ -104,7 +100,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
        struct mlx4_en_profile *params = &mdev->profile;
        int i;
 
-       params->tcp_rss = tcp_rss;
        params->udp_rss = udp_rss;
        if (params->udp_rss && !(mdev->dev->caps.flags
                                        & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
@@ -120,6 +115,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
                params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
                params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
                        (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+               params->prof[i].rss_rings = 0;
        }
 
        return 0;
index 72fa807b69ce1581ac62dea599ce121e19e74f9c..149e60da0a32870aa809d676856c971ee95ebf80 100644 (file)
@@ -702,6 +702,8 @@ int mlx4_en_start_port(struct net_device *dev)
        /* Schedule multicast task to populate multicast list */
        queue_work(mdev->workqueue, &priv->mcast_task);
 
+       mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap);
+
        priv->port_up = true;
        netif_tx_start_all_queues(dev);
        return 0;
@@ -807,38 +809,50 @@ static void mlx4_en_restart(struct work_struct *work)
        mutex_unlock(&mdev->state_lock);
 }
 
-
-static int mlx4_en_open(struct net_device *dev)
+static void mlx4_en_clear_stats(struct net_device *dev)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
        int i;
-       int err = 0;
-
-       mutex_lock(&mdev->state_lock);
-
-       if (!mdev->device_up) {
-               en_err(priv, "Cannot open - device down/disabled\n");
-               err = -EBUSY;
-               goto out;
-       }
 
-       /* Reset HW statistics and performance counters */
        if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
                en_dbg(HW, priv, "Failed dumping statistics\n");
 
        memset(&priv->stats, 0, sizeof(priv->stats));
        memset(&priv->pstats, 0, sizeof(priv->pstats));
+       memset(&priv->pkstats, 0, sizeof(priv->pkstats));
+       memset(&priv->port_stats, 0, sizeof(priv->port_stats));
 
        for (i = 0; i < priv->tx_ring_num; i++) {
                priv->tx_ring[i].bytes = 0;
                priv->tx_ring[i].packets = 0;
+               priv->tx_ring[i].tx_csum = 0;
        }
        for (i = 0; i < priv->rx_ring_num; i++) {
                priv->rx_ring[i].bytes = 0;
                priv->rx_ring[i].packets = 0;
+               priv->rx_ring[i].csum_ok = 0;
+               priv->rx_ring[i].csum_none = 0;
+       }
+}
+
+static int mlx4_en_open(struct net_device *dev)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_dev *mdev = priv->mdev;
+       int err = 0;
+
+       mutex_lock(&mdev->state_lock);
+
+       if (!mdev->device_up) {
+               en_err(priv, "Cannot open - device down/disabled\n");
+               err = -EBUSY;
+               goto out;
        }
 
+       /* Reset HW statistics and SW counters */
+       mlx4_en_clear_stats(dev);
+
        err = mlx4_en_start_port(dev);
        if (err)
                en_err(priv, "Failed starting port:%d\n", priv->port);
@@ -878,7 +892,8 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv)
 
        for (i = 0; i < priv->rx_ring_num; i++) {
                if (priv->rx_ring[i].rx_info)
-                       mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
+                       mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
+                               priv->prof->rx_ring_size, priv->stride);
                if (priv->rx_cq[i].buf)
                        mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
        }
index e8d6ad2dce0afaaa2ffd27017238cd0482334039..d4ad8c226b5115430066a4f41221f7ee41384e58 100644 (file)
@@ -168,8 +168,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
        return 0;
 
 err:
-       while (i--)
+       while (i--) {
+               dma_addr_t dma = be64_to_cpu(rx_desc->data[i].addr);
+               pci_unmap_single(priv->mdev->pdev, dma, skb_frags[i].size,
+                                PCI_DMA_FROMDEVICE);
                put_page(skb_frags[i].page);
+       }
        return -ENOMEM;
 }
 
@@ -380,12 +384,12 @@ err_allocator:
 }
 
 void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
-                            struct mlx4_en_rx_ring *ring)
+                            struct mlx4_en_rx_ring *ring, u32 size, u16 stride)
 {
        struct mlx4_en_dev *mdev = priv->mdev;
 
        mlx4_en_unmap_buffer(&ring->wqres.buf);
-       mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
+       mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
        vfree(ring->rx_info);
        ring->rx_info = NULL;
 }
@@ -853,6 +857,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        struct mlx4_en_rss_map *rss_map = &priv->rss_map;
        struct mlx4_qp_context context;
        struct mlx4_rss_context *rss_context;
+       int rss_rings;
        void *ptr;
        u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
                        MLX4_RSS_TCP_IPV6);
@@ -893,10 +898,15 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
                                priv->rx_ring[0].cqn, &context);
 
+       if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
+               rss_rings = priv->rx_ring_num;
+       else
+               rss_rings = priv->prof->rss_rings;
+
        ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
                                        + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
        rss_context = ptr;
-       rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
+       rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
                                            (rss_map->base_qpn));
        rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
        if (priv->mdev->profile.udp_rss) {
index 1e9b55eb7217a8c725c8e39b2880855e7f88c04a..8fa41f3082cf63c7cf22bd0a7442de1034d60df7 100644 (file)
@@ -513,25 +513,22 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave,
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_slave_event_eq_info *event_eq =
-               &priv->mfunc.master.slave_state[slave].event_eq;
+               priv->mfunc.master.slave_state[slave].event_eq;
        u32 in_modifier = vhcr->in_modifier;
        u32 eqn = in_modifier & 0x1FF;
        u64 in_param =  vhcr->in_param;
        int err = 0;
+       int i;
 
        if (slave == dev->caps.function)
                err = mlx4_cmd(dev, in_param, (in_modifier & 0x80000000) | eqn,
                               0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B,
                               MLX4_CMD_NATIVE);
-       if (!err) {
-               if (in_modifier >> 31) {
-                       /* unmap */
-                       event_eq->event_type &= ~in_param;
-               } else {
-                       event_eq->eqn = eqn;
-                       event_eq->event_type = in_param;
-               }
-       }
+       if (!err)
+               for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i)
+                       if (in_param & (1LL << i))
+                               event_eq[i].eqn = in_modifier >> 31 ? -1 : eqn;
+
        return err;
 }
 
@@ -546,7 +543,7 @@ static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap,
 static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
                         int eq_num)
 {
-       return mlx4_cmd(dev, mailbox->dma | dev->caps.function, eq_num, 0,
+       return mlx4_cmd(dev, mailbox->dma, eq_num, 0,
                        MLX4_CMD_SW2HW_EQ, MLX4_CMD_TIME_CLASS_A,
                        MLX4_CMD_WRAPPED);
 }
@@ -554,7 +551,7 @@ static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
 static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
                         int eq_num)
 {
-       return mlx4_cmd_box(dev, dev->caps.function, mailbox->dma, eq_num,
+       return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num,
                            0, MLX4_CMD_HW2SW_EQ, MLX4_CMD_TIME_CLASS_A,
                            MLX4_CMD_WRAPPED);
 }
@@ -818,8 +815,9 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
        int err;
        int i;
 
-       priv->eq_table.uar_map = kcalloc(sizeof *priv->eq_table.uar_map,
-                                        mlx4_num_eq_uar(dev), GFP_KERNEL);
+       priv->eq_table.uar_map = kcalloc(mlx4_num_eq_uar(dev),
+                                        sizeof *priv->eq_table.uar_map,
+                                        GFP_KERNEL);
        if (!priv->eq_table.uar_map) {
                err = -ENOMEM;
                goto err_out_free;
index a424a19280cc466eefba7ab08236f6306e505e12..8a21e10952ea23260ad503cee702ed31437ff1e1 100644 (file)
@@ -158,7 +158,6 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
 
 #define QUERY_FUNC_CAP_FLAGS_OFFSET            0x0
 #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET                0x1
-#define QUERY_FUNC_CAP_FUNCTION_OFFSET         0x3
 #define QUERY_FUNC_CAP_PF_BHVR_OFFSET          0x4
 #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET         0x10
 #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET         0x14
@@ -182,9 +181,6 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
                field = 1 << 7; /* enable only ethernet interface */
                MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
 
-               field = slave;
-               MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FUNCTION_OFFSET);
-
                field = dev->caps.num_ports;
                MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
 
@@ -249,9 +245,6 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap)
                goto out;
        }
 
-       MLX4_GET(field, outbox, QUERY_FUNC_CAP_FUNCTION_OFFSET);
-       func_cap->function = field;
-
        MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
        func_cap->num_ports = field;
 
index 119e0cc9fab3d852259e7f4df0651382511f9d68..e1a5fa56bcbc584e4a525dee3d1567a06ebdde8f 100644 (file)
@@ -119,7 +119,6 @@ struct mlx4_dev_cap {
 };
 
 struct mlx4_func_cap {
-       u8      function;
        u8      num_ports;
        u8      flags;
        u32     pf_context_behaviour;
index 6bb62c580e2d50eab48565e170650b25efac00c9..678558b502fc31e506633e0713805f58c8676108 100644 (file)
@@ -108,7 +108,7 @@ static struct mlx4_profile default_profile = {
        .num_cq         = 1 << 16,
        .num_mcg        = 1 << 13,
        .num_mpt        = 1 << 19,
-       .num_mtt        = 1 << 20,
+       .num_mtt        = 1 << 20, /* It is really num mtt segements */
 };
 
 static int log_num_mac = 7;
@@ -471,7 +471,6 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                return -ENOSYS;
        }
 
-       dev->caps.function              = func_cap.function;
        dev->caps.num_ports             = func_cap.num_ports;
        dev->caps.num_qps               = func_cap.qp_quota;
        dev->caps.num_srqs              = func_cap.srq_quota;
index 0785d9b2a265811838133550b72522867b34838e..ca574d850b39529eae4c7828fe8239e89ecbba50 100644 (file)
@@ -136,7 +136,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,
        u32 prot;
        int err;
 
-       s_steer = &mlx4_priv(dev)->steer[0];
+       s_steer = &mlx4_priv(dev)->steer[port - 1];
        new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
        if (!new_entry)
                return -ENOMEM;
@@ -220,7 +220,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
        struct mlx4_promisc_qp *pqp;
        struct mlx4_promisc_qp *dqp;
 
-       s_steer = &mlx4_priv(dev)->steer[0];
+       s_steer = &mlx4_priv(dev)->steer[port - 1];
 
        pqp = get_promisc_qp(dev, 0, steer, qpn);
        if (!pqp)
@@ -265,7 +265,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
        struct mlx4_steer_index *tmp_entry, *entry = NULL;
        struct mlx4_promisc_qp *dqp, *tmp_dqp;
 
-       s_steer = &mlx4_priv(dev)->steer[0];
+       s_steer = &mlx4_priv(dev)->steer[port - 1];
 
        /* if qp is not promisc, it cannot be duplicated */
        if (!get_promisc_qp(dev, 0, steer, qpn))
@@ -306,7 +306,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
        bool ret = false;
        int i;
 
-       s_steer = &mlx4_priv(dev)->steer[0];
+       s_steer = &mlx4_priv(dev)->steer[port - 1];
 
        mailbox = mlx4_alloc_cmd_mailbox(dev);
        if (IS_ERR(mailbox))
@@ -361,7 +361,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
        int err;
        struct mlx4_priv *priv = mlx4_priv(dev);
 
-       s_steer = &mlx4_priv(dev)->steer[0];
+       s_steer = &mlx4_priv(dev)->steer[port - 1];
 
        mutex_lock(&priv->mcg_table.mutex);
 
@@ -466,7 +466,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
        int loc, i;
        int err;
 
-       s_steer = &mlx4_priv(dev)->steer[0];
+       s_steer = &mlx4_priv(dev)->steer[port - 1];
        mutex_lock(&priv->mcg_table.mutex);
 
        pqp = get_promisc_qp(dev, 0, steer, qpn);
@@ -1004,7 +1004,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
 
 int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
 {
-       if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
+       if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
                return 0;
 
        if (mlx4_is_mfunc(dev))
@@ -1016,7 +1016,7 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
 
 int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
 {
-       if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
+       if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
                return 0;
 
        if (mlx4_is_mfunc(dev))
index a80121a2b5195cf245bd16842f3755c822646781..c92269f8c0570a5b7e6d374beb7ffb9f48e79877 100644 (file)
@@ -388,9 +388,8 @@ struct mlx4_slave_eqe {
 };
 
 struct mlx4_slave_event_eq_info {
-       u32 eqn;
+       int eqn;
        u16 token;
-       u64 event_type;
 };
 
 struct mlx4_profile {
@@ -449,6 +448,8 @@ struct mlx4_steer_index {
        struct list_head duplicates;
 };
 
+#define MLX4_EVENT_TYPES_NUM 64
+
 struct mlx4_slave_state {
        u8 comm_toggle;
        u8 last_cmd;
@@ -461,7 +462,8 @@ struct mlx4_slave_state {
        struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
        struct list_head mcast_filters[MLX4_MAX_PORTS + 1];
        struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1];
-       struct mlx4_slave_event_eq_info event_eq;
+       /* event type to eq number lookup */
+       struct mlx4_slave_event_eq_info event_eq[MLX4_EVENT_TYPES_NUM];
        u16 eq_pi;
        u16 eq_ci;
        spinlock_t lock;
index f2a8e65f5f88a4df9ff9861bddfbfeae458d6ec6..d60335f3c473382ea80f4a3f2c1c819a50391c33 100644 (file)
@@ -325,11 +325,11 @@ struct mlx4_en_port_profile {
        u8 rx_ppp;
        u8 tx_pause;
        u8 tx_ppp;
+       int rss_rings;
 };
 
 struct mlx4_en_profile {
        int rss_xor;
-       int tcp_rss;
        int udp_rss;
        u8 rss_mask;
        u32 active_ports;
@@ -476,6 +476,7 @@ struct mlx4_en_priv {
        struct mlx4_en_perf_stats pstats;
        struct mlx4_en_pkt_stats pkstats;
        struct mlx4_en_port_stats port_stats;
+       u64 stats_bitmap;
        char *mc_addrs;
        int mc_addrs_cnt;
        struct mlx4_en_stat_out_mbox hw_stats;
@@ -527,7 +528,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
                           struct mlx4_en_rx_ring *ring,
                           u32 size, u16 stride);
 void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
-                            struct mlx4_en_rx_ring *ring);
+                            struct mlx4_en_rx_ring *ring,
+                            u32 size, u16 stride);
 int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv);
 void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
                                struct mlx4_en_rx_ring *ring);
index 01df5567e16e48398c2a119d2c39de060934e712..8deeef98280c9a31358c9c0f8343c32f3d78329f 100644 (file)
@@ -291,7 +291,7 @@ static u32 key_to_hw_index(u32 key)
 static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
                          int mpt_index)
 {
-       return mlx4_cmd(dev, mailbox->dma | dev->caps.function , mpt_index,
+       return mlx4_cmd(dev, mailbox->dma, mpt_index,
                        0, MLX4_CMD_SW2HW_MPT, MLX4_CMD_TIME_CLASS_B,
                        MLX4_CMD_WRAPPED);
 }
index 5c9a54df17aba89d233926d9f37710ac84c0e504..db4746d0dca7e0edb91889446606a5bd2b96bbda 100644 (file)
@@ -52,8 +52,7 @@ int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn)
        *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap);
        if (*pdn == -1)
                return -ENOMEM;
-       if (mlx4_is_mfunc(dev))
-               *pdn |= (dev->caps.function + 1) << NOT_MASKED_PD_BITS;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
index 88b52e547524efaee71ffc67f00b4f44e7844f30..f44ae555bf43906bfba98cb25838542f5052c25d 100644 (file)
 #define MLX4_VLAN_VALID                (1u << 31)
 #define MLX4_VLAN_MASK         0xfff
 
+#define MLX4_STATS_TRAFFIC_COUNTERS_MASK       0xfULL
+#define MLX4_STATS_TRAFFIC_DROPS_MASK          0xc0ULL
+#define MLX4_STATS_ERROR_COUNTERS_MASK         0x1ffc30ULL
+#define MLX4_STATS_PORT_COUNTERS_MASK          0x1fe00000ULL
+
 void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
 {
        int i;
@@ -898,6 +903,24 @@ int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
                                struct mlx4_cmd_mailbox *outbox,
                                struct mlx4_cmd_info *cmd)
 {
+       if (slave != dev->caps.function)
+               return 0;
        return mlx4_common_dump_eth_stats(dev, slave,
                                          vhcr->in_modifier, outbox);
 }
+
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap)
+{
+       if (!mlx4_is_mfunc(dev)) {
+               *stats_bitmap = 0;
+               return;
+       }
+
+       *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK |
+                        MLX4_STATS_TRAFFIC_DROPS_MASK |
+                        MLX4_STATS_PORT_COUNTERS_MASK);
+
+       if (mlx4_is_master(dev))
+               *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK;
+}
+EXPORT_SYMBOL(mlx4_set_stats_bitmap);
index 66f91ca7a7c6c277778e58d5b4a59b749ab9becf..1129677daa62608e1ab18bfcd5da8dc20abf8101 100644 (file)
@@ -110,7 +110,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
        profile[MLX4_RES_EQ].num      = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
        profile[MLX4_RES_DMPT].num    = request->num_mpt;
        profile[MLX4_RES_CMPT].num    = MLX4_NUM_CMPTS;
-       profile[MLX4_RES_MTT].num     = request->num_mtt;
+       profile[MLX4_RES_MTT].num     = request->num_mtt * (1 << log_mtts_per_seg);
        profile[MLX4_RES_MCG].num     = request->num_mcg;
 
        for (i = 0; i < MLX4_RES_NUM; ++i) {
index 6b03ac8b9002bdb530b72969ccb0945f19f49c92..738f950a1ce59e69c6297517882913d90f22f784 100644 (file)
@@ -162,7 +162,7 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
        ((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn =
                cpu_to_be32(qp->qpn);
 
-       ret = mlx4_cmd(dev, mailbox->dma | dev->caps.function,
+       ret = mlx4_cmd(dev, mailbox->dma,
                       qp->qpn | (!!sqd_event << 31),
                       new_state == MLX4_QP_STATE_RST ? 2 : 0,
                       op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native);
index ed20751a057dde297a64cf25e8edc8d193ac0cb0..bfdb7af19e496285bdeff3ada8a302b71e746865 100644 (file)
@@ -73,6 +73,7 @@ struct res_gid {
        struct list_head        list;
        u8                      gid[16];
        enum mlx4_protocol      prot;
+       enum mlx4_steer_type    steer;
 };
 
 enum res_qp_states {
@@ -374,6 +375,7 @@ static struct res_common *alloc_qp_tr(int id)
 
        ret->com.res_id = id;
        ret->com.state = RES_QP_RESERVED;
+       ret->local_qpn = id;
        INIT_LIST_HEAD(&ret->mcg_list);
        spin_lock_init(&ret->mcg_spl);
 
@@ -1561,11 +1563,6 @@ static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
        return be32_to_cpu(mpt->mtt_sz);
 }
 
-static int mr_get_pdn(struct mlx4_mpt_entry *mpt)
-{
-       return be32_to_cpu(mpt->pd_flags) & 0xffffff;
-}
-
 static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
 {
        return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
@@ -1602,16 +1599,6 @@ static int qp_get_mtt_size(struct mlx4_qp_context *qpc)
        return total_pages;
 }
 
-static int qp_get_pdn(struct mlx4_qp_context *qpc)
-{
-       return be32_to_cpu(qpc->pd) & 0xffffff;
-}
-
-static int pdn2slave(int pdn)
-{
-       return (pdn >> NOT_MASKED_PD_BITS) - 1;
-}
-
 static int check_mtt_range(struct mlx4_dev *dev, int slave, int start,
                           int size, struct res_mtt *mtt)
 {
@@ -1656,11 +1643,6 @@ int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
                mpt->mtt = mtt;
        }
 
-       if (pdn2slave(mr_get_pdn(inbox->buf)) != slave) {
-               err = -EPERM;
-               goto ex_put;
-       }
-
        err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
        if (err)
                goto ex_put;
@@ -1792,11 +1774,6 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
        if (err)
                goto ex_put_mtt;
 
-       if (pdn2slave(qp_get_pdn(qpc)) != slave) {
-               err = -EPERM;
-               goto ex_put_mtt;
-       }
-
        err = get_res(dev, slave, rcqn, RES_CQ, &rcq);
        if (err)
                goto ex_put_mtt;
@@ -2048,10 +2025,10 @@ int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)
        if (!priv->mfunc.master.slave_state)
                return -EINVAL;
 
-       event_eq = &priv->mfunc.master.slave_state[slave].event_eq;
+       event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
 
        /* Create the event only if the slave is registered */
-       if ((event_eq->event_type & (1 << eqe->type)) == 0)
+       if (event_eq->eqn < 0)
                return 0;
 
        mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
@@ -2289,11 +2266,6 @@ ex_put:
        return err;
 }
 
-static int srq_get_pdn(struct mlx4_srq_context *srqc)
-{
-       return be32_to_cpu(srqc->pd) & 0xffffff;
-}
-
 static int srq_get_mtt_size(struct mlx4_srq_context *srqc)
 {
        int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;
@@ -2333,11 +2305,6 @@ int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
        if (err)
                goto ex_put_mtt;
 
-       if (pdn2slave(srq_get_pdn(srqc)) != slave) {
-               err = -EPERM;
-               goto ex_put_mtt;
-       }
-
        err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
        if (err)
                goto ex_put_mtt;
@@ -2514,7 +2481,8 @@ static struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
 }
 
 static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
-                      u8 *gid, enum mlx4_protocol prot)
+                      u8 *gid, enum mlx4_protocol prot,
+                      enum mlx4_steer_type steer)
 {
        struct res_gid *res;
        int err;
@@ -2530,6 +2498,7 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
        } else {
                memcpy(res->gid, gid, 16);
                res->prot = prot;
+               res->steer = steer;
                list_add_tail(&res->list, &rqp->mcg_list);
                err = 0;
        }
@@ -2539,14 +2508,15 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
 }
 
 static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
-                      u8 *gid, enum mlx4_protocol prot)
+                      u8 *gid, enum mlx4_protocol prot,
+                      enum mlx4_steer_type steer)
 {
        struct res_gid *res;
        int err;
 
        spin_lock_irq(&rqp->mcg_spl);
        res = find_gid(dev, slave, rqp, gid);
-       if (!res || res->prot != prot)
+       if (!res || res->prot != prot || res->steer != steer)
                err = -EINVAL;
        else {
                list_del(&res->list);
@@ -2573,7 +2543,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        int attach = vhcr->op_modifier;
        int block_loopback = vhcr->in_modifier >> 31;
        u8 steer_type_mask = 2;
-       enum mlx4_steer_type type = gid[7] & steer_type_mask;
+       enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
 
        qpn = vhcr->in_modifier & 0xffffff;
        err = get_res(dev, slave, qpn, RES_QP, &rqp);
@@ -2582,7 +2552,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
 
        qp.qpn = qpn;
        if (attach) {
-               err = add_mcg_res(dev, slave, rqp, gid, prot);
+               err = add_mcg_res(dev, slave, rqp, gid, prot, type);
                if (err)
                        goto ex_put;
 
@@ -2591,7 +2561,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                if (err)
                        goto ex_rem;
        } else {
-               err = rem_mcg_res(dev, slave, rqp, gid, prot);
+               err = rem_mcg_res(dev, slave, rqp, gid, prot, type);
                if (err)
                        goto ex_put;
                err = mlx4_qp_detach_common(dev, &qp, gid, prot, type);
@@ -2602,7 +2572,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
 
 ex_rem:
        /* ignore error return below, already in error */
-       err1 = rem_mcg_res(dev, slave, rqp, gid, prot);
+       err1 = rem_mcg_res(dev, slave, rqp, gid, prot, type);
 ex_put:
        put_res(dev, slave, qpn, RES_QP);
 
@@ -2641,7 +2611,7 @@ static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
        list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
                qp.qpn = rqp->local_qpn;
                err = mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
-                                           MLX4_MC_STEER);
+                                           rgid->steer);
                list_del(&rgid->list);
                kfree(rgid);
        }
index 2823fffc6383989c985e54884b826cdf69ca50fc..feda6c00829f391e0d5bd822db970c5d6a2f7ca2 100644 (file)
@@ -67,7 +67,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
 static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
                          int srq_num)
 {
-       return mlx4_cmd(dev, mailbox->dma | dev->caps.function, srq_num, 0,
+       return mlx4_cmd(dev, mailbox->dma, srq_num, 0,
                        MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A,
                        MLX4_CMD_WRAPPED);
 }
index 1ea811cf515bd11e9bd1fa0f6d46fd5bce444c0b..fe42fc00d8d314d6011d621c23c64370b93fe304 100644 (file)
@@ -42,7 +42,6 @@ config KS8851
        select NET_CORE
        select MII
        select CRC32
-       select MISC_DEVICES
        select EEPROM_93CX6
        ---help---
          SPI driver for Micrel KS8851 SPI attached network chip.
index 75ec87a822b8e2d1ee12486bc6cfcbf0f3e0a248..0a85690a1321ecc17cf24f2398f496d60dc8d175 100644 (file)
@@ -459,7 +459,7 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
                sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
 
        ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
-               &ctl->sg, 1, DMA_TO_DEVICE,
+               &ctl->sg, 1, DMA_MEM_TO_DEV,
                DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
        if (!ctl->adesc)
                return NETDEV_TX_BUSY;
@@ -571,7 +571,7 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev)
                sg_dma_len(sg) = DMA_BUFFER_SIZE;
 
                ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
-                       sg, 1, DMA_FROM_DEVICE,
+                       sg, 1, DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
 
                if (!ctl->adesc)
index 6b35e7da9a9c7a094f27ff725787865b7bd034e6..0c3e4005224d446d181c2656c3a04a95fceded28 100644 (file)
@@ -583,7 +583,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
                                        ks8851_dbg_dumpkkt(ks, rxpkt);
 
                                skb->protocol = eth_type_trans(skb, ks->netdev);
-                               netif_rx(skb);
+                               netif_rx_ni(skb);
 
                                ks->netdev->stats.rx_packets++;
                                ks->netdev->stats.rx_bytes += rxlen;
index e58e78e5c930048d0dccf4202478b7da4d227b91..231176fcd2ba390d55741d6d5fa82e7be2311823 100644 (file)
@@ -394,7 +394,6 @@ union ks_tx_hdr {
  * @msg_enable : The message flags controlling driver output (see ethtool).
  * @frame_cnt          : number of frames received.
  * @bus_width          : i/o bus width.
- * @irq        : irq number assigned to this device.
  * @rc_rxqcr   : Cached copy of KS_RXQCR.
  * @rc_txcr    : Cached copy of KS_TXCR.
  * @rc_ier     : Cached copy of KS_IER.
@@ -441,7 +440,6 @@ struct ks_net {
        u32                     msg_enable;
        u32                     frame_cnt;
        int                     bus_width;
-       int                     irq;
 
        u16                     rc_rxqcr;
        u16                     rc_txcr;
@@ -907,10 +905,10 @@ static int ks_net_open(struct net_device *netdev)
        netif_dbg(ks, ifup, ks->netdev, "%s - entry\n", __func__);
 
        /* reset the HW */
-       err = request_irq(ks->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev);
+       err = request_irq(netdev->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev);
 
        if (err) {
-               pr_err("Failed to request IRQ: %d: %d\n", ks->irq, err);
+               pr_err("Failed to request IRQ: %d: %d\n", netdev->irq, err);
                return err;
        }
 
@@ -955,7 +953,7 @@ static int ks_net_stop(struct net_device *netdev)
 
        /* set powermode to soft power down to save power */
        ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
-       free_irq(ks->irq, netdev);
+       free_irq(netdev->irq, netdev);
        mutex_unlock(&ks->lock);
        return 0;
 }
@@ -1545,10 +1543,10 @@ static int __devinit ks8851_probe(struct platform_device *pdev)
        if (!ks->hw_addr_cmd)
                goto err_ioremap1;
 
-       ks->irq = platform_get_irq(pdev, 0);
+       netdev->irq = platform_get_irq(pdev, 0);
 
-       if (ks->irq < 0) {
-               err = ks->irq;
+       if (netdev->irq < 0) {
+               err = netdev->irq;
                goto err_get_irq;
        }
 
index 212f43b308a3c27ed411b21768e160e0d899a571..cd827ff4a021f74284574f75cc27de97b4c3e7fe 100644 (file)
@@ -670,7 +670,7 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
 static int octeon_mgmt_init_phy(struct net_device *netdev)
 {
        struct octeon_mgmt *p = netdev_priv(netdev);
-       char phy_id[20];
+       char phy_id[MII_BUS_ID_SIZE + 3];
 
        if (octeon_is_simulation()) {
                /* No PHYs in the simulator. */
@@ -678,7 +678,7 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
                return 0;
        }
 
-       snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", p->port);
+       snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", p->port);
 
        p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
                                PHY_INTERFACE_MODE_MII);
index 964e9c0948bce19cf1a09ca5229575006ed1934f..3ead111111e1f1bec8eaa10e3f5c9dee0650f4a9 100644 (file)
@@ -1745,6 +1745,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
        int err;
 
+       /* Ensure we have a valid MAC */
+       if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+               pr_err("Error: Invalid MAC address\n");
+               return -EINVAL;
+       }
+
        /* hardware has been reset, we need to reload some things */
        pch_gbe_set_multi(netdev);
 
@@ -2468,9 +2474,14 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 
        memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
        if (!is_valid_ether_addr(netdev->dev_addr)) {
-               dev_err(&pdev->dev, "Invalid MAC Address\n");
-               ret = -EIO;
-               goto err_free_adapter;
+               /*
+                * If the MAC is invalid (or just missing), display a warning
+                * but do not abort setting up the device. pch_gbe_up will
+                * prevent the interface from being brought up until a valid MAC
+                * is set.
+                */
+               dev_err(&pdev->dev, "Invalid MAC address, "
+                                   "interface disabled.\n");
        }
        setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
                    (unsigned long)adapter);
index 6ece4295d78fd8cd16deafd28cf377f937b4aa92..87b650131774ae74646b80143045226ae3a217d1 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 #include <linux/sh_eth.h>
 
 #include "sh_eth.h"
@@ -817,7 +818,8 @@ static int sh_eth_dev_init(struct net_device *ndev)
                sh_eth_write(ndev, 0, TRIMD);
 
        /* Recv frame limit set register */
-       sh_eth_write(ndev, RFLR_VALUE, RFLR);
+       sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
+                    RFLR);
 
        sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
        sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
@@ -1703,7 +1705,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        mdp->mii_bus->name = "sh_mii";
        mdp->mii_bus->parent = &ndev->dev;
        snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
-               mdp->pdev->name, pdid);
+               mdp->pdev->name, id);
 
        /* PHY IRQ */
        mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
index 47877b13ffada62de5fb5575ae355cccd346a1ce..cdbd844662a76bdf7c5900c1d9043e164f82754b 100644 (file)
@@ -575,9 +575,6 @@ enum RPADIR_BIT {
        RPADIR_PADR = 0x0003f,
 };
 
-/* RFLR */
-#define RFLR_VALUE 0x1000
-
 /* FDR */
 #define DEFAULT_FDR_INIT       0x00000707
 
index d0b814ef0675396d56a1c5771f87ebe37689c09e..0319d640f72839cd47ad331718bc2ed2c6972539 100644 (file)
@@ -67,6 +67,7 @@ struct stmmac_extra_stats {
        unsigned long ipc_csum_error;
        unsigned long rx_collision;
        unsigned long rx_crc;
+       unsigned long dribbling_bit;
        unsigned long rx_length;
        unsigned long rx_mii;
        unsigned long rx_multicast;
index d87976364ec5a6a7a3bb1c4017917134abd1e74d..ad1b627f8ec2fe83607b6ef489f668825be645df 100644 (file)
@@ -201,7 +201,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 
        if (unlikely(p->des01.erx.dribbling)) {
                CHIP_DBG(KERN_ERR "GMAC RX: dribbling error\n");
-               ret = discard_frame;
+               x->dribbling_bit++;
        }
        if (unlikely(p->des01.erx.sa_filter_fail)) {
                CHIP_DBG(KERN_ERR "GMAC RX : Source Address filter fail\n");
index fda5d2b31d3ac5b139e9f5f2caf3b0c7d09123bb..25953bb45a736acdd517859b98c52850715765b8 100644 (file)
@@ -104,7 +104,7 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
                ret = discard_frame;
        }
        if (unlikely(p->des01.rx.dribbling))
-               ret = discard_frame;
+               x->dribbling_bit++;
 
        if (unlikely(p->des01.rx.length_error)) {
                x->rx_length++;
index 120740020e2ca4c68d304629bf5652dd7913ff0b..b4b095fdcf2964f87bdb433b223b940dcb683687 100644 (file)
@@ -21,7 +21,7 @@
 *******************************************************************************/
 
 #define STMMAC_RESOURCE_NAME   "stmmaceth"
-#define DRV_MODULE_VERSION     "Dec_2011"
+#define DRV_MODULE_VERSION     "Feb_2012"
 #include <linux/stmmac.h>
 #include <linux/phy.h>
 #include "common.h"
@@ -97,4 +97,5 @@ int stmmac_resume(struct net_device *ndev);
 int stmmac_suspend(struct net_device *ndev);
 int stmmac_dvr_remove(struct net_device *ndev);
 struct stmmac_priv *stmmac_dvr_probe(struct device *device,
-                               struct plat_stmmacenet_data *plat_dat);
+                                    struct plat_stmmacenet_data *plat_dat,
+                                    void __iomem *addr);
index 9573303a706b6ce882fac870ac50a4954dc2bad6..f98e1511660fe7c2136d345d7efa0bb12e05dec2 100644 (file)
@@ -47,23 +47,25 @@ struct stmmac_stats {
        offsetof(struct stmmac_priv, xstats.m)}
 
 static const struct stmmac_stats stmmac_gstrings_stats[] = {
+       /* Transmit errors */
        STMMAC_STAT(tx_underflow),
        STMMAC_STAT(tx_carrier),
        STMMAC_STAT(tx_losscarrier),
        STMMAC_STAT(vlan_tag),
        STMMAC_STAT(tx_deferred),
        STMMAC_STAT(tx_vlan),
-       STMMAC_STAT(rx_vlan),
        STMMAC_STAT(tx_jabber),
        STMMAC_STAT(tx_frame_flushed),
        STMMAC_STAT(tx_payload_error),
        STMMAC_STAT(tx_ip_header_error),
+       /* Receive errors */
        STMMAC_STAT(rx_desc),
        STMMAC_STAT(sa_filter_fail),
        STMMAC_STAT(overflow_error),
        STMMAC_STAT(ipc_csum_error),
        STMMAC_STAT(rx_collision),
        STMMAC_STAT(rx_crc),
+       STMMAC_STAT(dribbling_bit),
        STMMAC_STAT(rx_length),
        STMMAC_STAT(rx_mii),
        STMMAC_STAT(rx_multicast),
@@ -73,6 +75,8 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
        STMMAC_STAT(sa_rx_filter_fail),
        STMMAC_STAT(rx_missed_cntr),
        STMMAC_STAT(rx_overflow_cntr),
+       STMMAC_STAT(rx_vlan),
+       /* Tx/Rx IRQ errors */
        STMMAC_STAT(tx_undeflow_irq),
        STMMAC_STAT(tx_process_stopped_irq),
        STMMAC_STAT(tx_jabber_irq),
@@ -82,6 +86,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
        STMMAC_STAT(rx_watchdog_irq),
        STMMAC_STAT(tx_early_irq),
        STMMAC_STAT(fatal_bus_error_irq),
+       /* Extra info */
        STMMAC_STAT(threshold),
        STMMAC_STAT(tx_pkt_n),
        STMMAC_STAT(rx_pkt_n),
index 96fa2da307630f1e46df75441af10c91f0fd4c79..6ee593a55a64d9eabbf3238bfba28102257b8cc5 100644 (file)
@@ -241,7 +241,7 @@ static void stmmac_adjust_link(struct net_device *dev)
                        case 1000:
                                if (likely(priv->plat->has_gmac))
                                        ctrl &= ~priv->hw->link.port;
-                               stmmac_hw_fix_mac_speed(priv);
+                                       stmmac_hw_fix_mac_speed(priv);
                                break;
                        case 100:
                        case 10:
@@ -785,7 +785,7 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
                u32 uid = ((hwid & 0x0000ff00) >> 8);
                u32 synid = (hwid & 0x000000ff);
 
-               pr_info("STMMAC - user ID: 0x%x, Synopsys ID: 0x%x\n",
+               pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
                        uid, synid);
 
                return synid;
@@ -869,38 +869,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
        return hw_cap;
 }
 
-/**
- * stmmac_mac_device_setup
- * @dev : device pointer
- * Description: this is to attach the GMAC or MAC 10/100
- * main core structures that will be completed during the
- * open step.
- */
-static int stmmac_mac_device_setup(struct net_device *dev)
-{
-       struct stmmac_priv *priv = netdev_priv(dev);
-
-       struct mac_device_info *device;
-
-       if (priv->plat->has_gmac)
-               device = dwmac1000_setup(priv->ioaddr);
-       else
-               device = dwmac100_setup(priv->ioaddr);
-
-       if (!device)
-               return -ENOMEM;
-
-       priv->hw = device;
-       priv->hw->ring = &ring_mode_ops;
-
-       if (device_can_wakeup(priv->device)) {
-               priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
-               enable_irq_wake(priv->wol_irq);
-       }
-
-       return 0;
-}
-
 static void stmmac_check_ether_addr(struct stmmac_priv *priv)
 {
        /* verify if the MAC address is valid, in case of failures it
@@ -930,20 +898,8 @@ static int stmmac_open(struct net_device *dev)
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret;
 
-       /* MAC HW device setup */
-       ret = stmmac_mac_device_setup(dev);
-       if (ret < 0)
-               return ret;
-
        stmmac_check_ether_addr(priv);
 
-       stmmac_verify_args();
-
-       /* Override with kernel parameters if supplied XXX CRS XXX
-        * this needs to have multiple instances */
-       if ((phyaddr >= 0) && (phyaddr <= 31))
-               priv->plat->phy_addr = phyaddr;
-
        /* MDIO bus Registration */
        ret = stmmac_mdio_register(dev);
        if (ret < 0) {
@@ -976,44 +932,6 @@ 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);
@@ -1030,14 +948,14 @@ static int stmmac_open(struct net_device *dev)
 
        /* Copy the MAC addr into the HW  */
        priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+
        /* If required, perform hw setup of the bus. */
        if (priv->plat->bus_setup)
                priv->plat->bus_setup(priv->ioaddr);
+
        /* Initialize the MAC Core */
        priv->hw->mac->core_init(priv->ioaddr);
 
-       netdev_update_features(dev);
-
        /* Request the IRQ lines */
        ret = request_irq(dev->irq, stmmac_interrupt,
                         IRQF_SHARED, dev->name, dev);
@@ -1047,6 +965,17 @@ static int stmmac_open(struct net_device *dev)
                goto open_error;
        }
 
+       /* Request the Wake IRQ in case of another line is used for WoL */
+       if (priv->wol_irq != dev->irq) {
+               ret = request_irq(priv->wol_irq, stmmac_interrupt,
+                                 IRQF_SHARED, dev->name, dev);
+               if (unlikely(ret < 0)) {
+                       pr_err("%s: ERROR: allocating the ext WoL IRQ %d "
+                              "(error: %d)\n", __func__, priv->wol_irq, ret);
+                       goto open_error_wolirq;
+               }
+       }
+
        /* Enable the MAC Rx/Tx */
        stmmac_set_mac(priv->ioaddr, true);
 
@@ -1062,7 +991,7 @@ static int stmmac_open(struct net_device *dev)
 #ifdef CONFIG_STMMAC_DEBUG_FS
        ret = stmmac_init_fs(dev);
        if (ret < 0)
-               pr_warning("\tFailed debugFS registration");
+               pr_warning("%s: failed debugFS registration\n", __func__);
 #endif
        /* Start the ball rolling... */
        DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
@@ -1072,6 +1001,7 @@ static int stmmac_open(struct net_device *dev)
 #ifdef CONFIG_STMMAC_TIMER
        priv->tm->timer_start(tmrate);
 #endif
+
        /* Dump DMA/MAC registers */
        if (netif_msg_hw(priv)) {
                priv->hw->mac->dump_regs(priv->ioaddr);
@@ -1087,6 +1017,9 @@ static int stmmac_open(struct net_device *dev)
 
        return 0;
 
+open_error_wolirq:
+       free_irq(dev->irq, dev);
+
 open_error:
 #ifdef CONFIG_STMMAC_TIMER
        kfree(priv->tm);
@@ -1127,6 +1060,8 @@ static int stmmac_release(struct net_device *dev)
 
        /* Free the IRQ lines */
        free_irq(dev->irq, dev);
+       if (priv->wol_irq != dev->irq)
+               free_irq(priv->wol_irq, dev);
 
        /* Stop TX/RX DMA and clear the descriptors */
        priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1788,6 +1723,69 @@ static const struct net_device_ops stmmac_netdev_ops = {
        .ndo_set_mac_address = eth_mac_addr,
 };
 
+/**
+ *  stmmac_hw_init - Init the MAC device
+ *  @priv : pointer to the private device structure.
+ *  Description: this function detects which MAC device
+ *  (GMAC/MAC10-100) has to attached, checks the HW capability
+ *  (if supported) and sets the driver's features (for example
+ *  to use the ring or chaine mode or support the normal/enh
+ *  descriptor structure).
+ */
+static int stmmac_hw_init(struct stmmac_priv *priv)
+{
+       int ret = 0;
+       struct mac_device_info *mac;
+
+       /* Identify the MAC HW device */
+       if (priv->plat->has_gmac)
+               mac = dwmac1000_setup(priv->ioaddr);
+       else
+               mac = dwmac100_setup(priv->ioaddr);
+       if (!mac)
+               return -ENOMEM;
+
+       priv->hw = mac;
+
+       /* To use the chained or ring mode */
+       priv->hw->ring = &ring_mode_ops;
+
+       /* Get and dump the chip ID */
+       stmmac_get_synopsys_id(priv);
+
+       /* Get the HW capability (new GMAC newer than 3.50a) */
+       priv->hw_cap_support = stmmac_get_hw_features(priv);
+       if (priv->hw_cap_support) {
+               pr_info(" DMA HW capability register supported");
+
+               /* 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;
+       } else
+               pr_info(" No HW DMA feature register supported");
+
+       /* Select the enhnaced/normal descriptor structures */
+       stmmac_selec_desc_mode(priv);
+
+       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+       if (priv->rx_coe)
+               pr_info(" RX Checksum Offload Engine supported\n");
+       if (priv->plat->tx_coe)
+               pr_info(" TX Checksum insertion supported\n");
+
+       if (priv->plat->pmt) {
+               pr_info(" Wake-Up On Lan supported\n");
+               device_set_wakeup_capable(priv->device, 1);
+       }
+
+       return ret;
+}
+
 /**
  * stmmac_dvr_probe
  * @device: device pointer
@@ -1795,7 +1793,8 @@ static const struct net_device_ops stmmac_netdev_ops = {
  * call the alloc_etherdev, allocate the priv structure.
  */
 struct stmmac_priv *stmmac_dvr_probe(struct device *device,
-                                       struct plat_stmmacenet_data *plat_dat)
+                                    struct plat_stmmacenet_data *plat_dat,
+                                    void __iomem *addr)
 {
        int ret = 0;
        struct net_device *ndev = NULL;
@@ -1815,10 +1814,27 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 
        ether_setup(ndev);
 
-       ndev->netdev_ops = &stmmac_netdev_ops;
        stmmac_set_ethtool_ops(ndev);
+       priv->pause = pause;
+       priv->plat = plat_dat;
+       priv->ioaddr = addr;
+       priv->dev->base_addr = (unsigned long)addr;
+
+       /* Verify driver arguments */
+       stmmac_verify_args();
+
+       /* Override with kernel parameters if supplied XXX CRS XXX
+        * this needs to have multiple instances */
+       if ((phyaddr >= 0) && (phyaddr <= 31))
+               priv->plat->phy_addr = phyaddr;
+
+       /* Init MAC and get the capabilities */
+       stmmac_hw_init(priv);
+
+       ndev->netdev_ops = &stmmac_netdev_ops;
 
-       ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+       ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                           NETIF_F_RXCSUM;
        ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
        ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
@@ -1830,8 +1846,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
-       priv->pause = pause;
-       priv->plat = plat_dat;
        netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
 
        spin_lock_init(&priv->lock);
@@ -1839,15 +1853,10 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 
        ret = register_netdev(ndev);
        if (ret) {
-               pr_err("%s: ERROR %i registering the device\n",
-                      __func__, ret);
+               pr_err("%s: ERROR %i registering the device\n", __func__, ret);
                goto error;
        }
 
-       DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
-           ndev->name, (ndev->features & NETIF_F_SG) ? "on" : "off",
-           (ndev->features & NETIF_F_IP_CSUM) ? "on" : "off");
-
        return priv;
 
 error:
index da4a1042523a633e5781f86df7ffe4e123c09910..73195329aa464b8b5b9a7c4cadd2aaaa36f134ad 100644 (file)
@@ -154,7 +154,7 @@ int stmmac_mdio_register(struct net_device *ndev)
        else
                irqlist = priv->mii_irq;
 
-       new_bus->name = "STMMAC MII Bus";
+       new_bus->name = "stmmac";
        new_bus->read = &stmmac_mdio_read;
        new_bus->write = &stmmac_mdio_write;
        new_bus->reset = &stmmac_mdio_reset;
index 54a819a364871b458ab18559156d82369445156c..50ad5b80cfaf1885ae71c148543e5cf2c4f1ae36 100644 (file)
@@ -96,13 +96,11 @@ static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
 
        stmmac_default_data();
 
-       priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat);
+       priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
        if (!priv) {
-               pr_err("%s: main drivr probe failed", __func__);
+               pr_err("%s: main driver probe failed", __func__);
                goto err_out;
        }
-       priv->ioaddr = addr;
-       priv->dev->base_addr = (unsigned long)addr;
        priv->dev->irq = pdev->irq;
        priv->wol_irq = pdev->irq;
 
@@ -170,9 +168,9 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
 #define STMMAC_DEVICE_ID 0x1108
 
 static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
-       {
-       PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, {
-       }
+       {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+       {}
 };
 
 MODULE_DEVICE_TABLE(pci, stmmac_id_table);
index 1ac83243649a2d4c44ad4efa7fd0393c6869fbce..3aad9810237c0dedb8c23f39324f2db646009f1a 100644 (file)
@@ -59,16 +59,20 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
                goto out_release_region;
        }
        plat_dat = pdev->dev.platform_data;
-       priv = stmmac_dvr_probe(&(pdev->dev), plat_dat);
+
+       /* Custom initialisation (if needed)*/
+       if (plat_dat->init) {
+               ret = plat_dat->init(pdev);
+               if (unlikely(ret))
+                       goto out_unmap;
+       }
+
+       priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
        if (!priv) {
-               pr_err("%s: main drivr probe failed", __func__);
+               pr_err("%s: main driver probe failed", __func__);
                goto out_unmap;
        }
 
-       priv->ioaddr = addr;
-       /* Set the I/O base addr */
-       priv->dev->base_addr = (unsigned long)addr;
-
        /* Get the MAC information */
        priv->dev->irq = platform_get_irq_byname(pdev, "macirq");
        if (priv->dev->irq == -ENXIO) {
@@ -92,13 +96,6 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv->dev);
 
-       /* Custom initialisation */
-       if (priv->plat->init) {
-               ret = priv->plat->init(pdev);
-               if (unlikely(ret))
-                       goto out_unmap;
-       }
-
        pr_debug("STMMAC platform driver registration completed");
 
        return 0;
index 4d9a28ffd3c3ac20d2764ea72ada7e70cadc04f0..cbc8df78d84bf65ab45668b5b585bf1bd5d11d7f 100644 (file)
@@ -1122,7 +1122,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
        pdata = pdev->dev.platform_data;
 
        if (external_switch || dumb_switch) {
-               strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
+               strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
                phy_id = pdev->id;
        } else {
                for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
@@ -1138,7 +1138,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
        if (phy_id == PHY_MAX_ADDR) {
                dev_err(&pdev->dev, "no PHY present, falling back "
                                        "to switch on MDIO bus 0\n");
-               strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
+               strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
                phy_id = pdev->id;
        }
 
index 794ac30a577b61b1baaf8a1499c1e0f9ee41bcaf..4fa0bcb25dfc0d5dadeb175a4c36ada14c0f680d 100644 (file)
@@ -1600,8 +1600,9 @@ static int emac_dev_open(struct net_device *ndev)
                if (IS_ERR(priv->phydev)) {
                        dev_err(emac_dev, "could not connect to phy %s\n",
                                priv->phy_id);
+                       ret = PTR_ERR(priv->phydev);
                        priv->phydev = NULL;
-                       return PTR_ERR(priv->phydev);
+                       return ret;
                }
 
                priv->link = 0;
index ef7c9c17bfffccbebd94ba0530fc1643e947812e..af8b8fc39eb2c0d7702e760820759a1f6bac103c 100644 (file)
@@ -318,9 +318,9 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 
        data->clk = clk_get(dev, NULL);
        if (IS_ERR(data->clk)) {
-               data->clk = NULL;
                dev_err(dev, "failed to get device clock\n");
                ret = PTR_ERR(data->clk);
+               data->clk = NULL;
                goto bail_out;
        }
 
index 0517647045594c087b54070f2afaffc1f8e4be97..74acb5cf6099b262fa03549f7c15d2da533ad22d 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_TOSHIBA
        bool "Toshiba devices"
        default y
-       depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) || PPC_PS3
+       depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB || MIPS) || PPC_PS3
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 4128d6b8cc28d02bdd2c59a217d1376e54786451..cb35b14b73bb2480e10082db5a41a8558cedfe1a 100644 (file)
@@ -2491,9 +2491,6 @@ static int velocity_close(struct net_device *dev)
        if (dev->irq != 0)
                free_irq(dev->irq, dev);
 
-       /* Power down the chip */
-       pci_set_power_state(vptr->pdev, PCI_D3hot);
-
        velocity_free_rings(vptr);
 
        vptr->flags &= (~VELOCITY_FLAGS_OPENED);
index 72a854f05bb8042cf8392c518377652e8af62daf..41a8b5a9849e00f8e03cfa1c541f2134e3af6557 100644 (file)
@@ -1416,7 +1416,8 @@ static int __devinit eth_init_one(struct platform_device *pdev)
        __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
        udelay(50);
 
-       snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
+       snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
+               mdio_bus->id, plat->phy);
        port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
                                   PHY_INTERFACE_MODE_MII);
        if (IS_ERR(port->phydev)) {
index 462d05f05e84d85d558f036a58b3786768514b03..466c58a7353dba30e89d8986c58e7cf7550b7670 100644 (file)
@@ -68,11 +68,11 @@ static void do_set_multicast(struct work_struct *w)
 
        nvdev = hv_get_drvdata(ndevctx->device_ctx);
        if (nvdev == NULL)
-               return;
+               goto out;
 
        rdev = nvdev->extension;
        if (rdev == NULL)
-               return;
+               goto out;
 
        if (net->flags & IFF_PROMISC)
                rndis_filter_set_packet_filter(rdev,
@@ -83,6 +83,7 @@ static void do_set_multicast(struct work_struct *w)
                        NDIS_PACKET_TYPE_ALL_MULTICAST |
                        NDIS_PACKET_TYPE_DIRECTED);
 
+out:
        kfree(w);
 }
 
@@ -122,7 +123,7 @@ static int netvsc_close(struct net_device *net)
        struct hv_device *device_obj = net_device_ctx->device_ctx;
        int ret;
 
-       netif_stop_queue(net);
+       netif_tx_disable(net);
 
        ret = rndis_filter_close(device_obj);
        if (ret != 0)
@@ -150,10 +151,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
        int ret;
        unsigned int i, num_pages, npg_data;
 
-       /* Add multipage for skb->data and additional one for RNDIS */
+       /* Add multipages for skb->data and additional 2 for RNDIS */
        npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
                >> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
-       num_pages = skb_shinfo(skb)->nr_frags + npg_data + 1;
+       num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2;
 
        /* Allocate a netvsc packet based on # of frags. */
        packet = kzalloc(sizeof(struct hv_netvsc_packet) +
@@ -172,8 +173,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
                                sizeof(struct hv_netvsc_packet) +
                                    (num_pages * sizeof(struct hv_page_buffer));
 
-       /* Setup the rndis header */
-       packet->page_buf_cnt = num_pages;
+       /* If the rndis msg goes beyond 1 page, we will add 1 later */
+       packet->page_buf_cnt = num_pages - 1;
 
        /* Initialize it from the skb */
        packet->total_data_buflen = skb->len;
@@ -255,7 +256,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
                schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
        } else {
                netif_carrier_off(net);
-               netif_stop_queue(net);
+               netif_tx_disable(net);
        }
 }
 
@@ -297,7 +298,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        skb->ip_summed = CHECKSUM_NONE;
 
        net->stats.rx_packets++;
-       net->stats.rx_bytes += skb->len;
+       net->stats.rx_bytes += packet->total_data_buflen;
 
        /*
         * Pass the skb back up. Network stack will deallocate the skb when it
@@ -336,7 +337,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
 
        nvdev->start_remove = true;
        cancel_delayed_work_sync(&ndevctx->dwork);
-       netif_stop_queue(ndev);
+       netif_tx_disable(ndev);
        rndis_filter_device_remove(hdev);
 
        ndev->mtu = mtu;
@@ -459,7 +460,7 @@ static int netvsc_remove(struct hv_device *dev)
        cancel_delayed_work_sync(&ndev_ctx->dwork);
 
        /* Stop outbound asap */
-       netif_stop_queue(net);
+       netif_tx_disable(net);
 
        unregister_netdev(net);
 
index da181f9a49d1fcec5cfa599843f4524f1643b14c..133b7fbf8595b423792a675f3ff5b9317106ef78 100644 (file)
@@ -321,6 +321,25 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
        data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
 
        pkt->total_data_buflen -= data_offset;
+
+       /*
+        * Make sure we got a valid RNDIS message, now total_data_buflen
+        * should be the data packet size plus the trailer padding size
+        */
+       if (pkt->total_data_buflen < rndis_pkt->data_len) {
+               netdev_err(dev->net_dev->ndev, "rndis message buffer "
+                          "overflow detected (got %u, min %u)"
+                          "...dropping this message!\n",
+                          pkt->total_data_buflen, rndis_pkt->data_len);
+               return;
+       }
+
+       /*
+        * Remove the rndis trailer padding from rndis packet message
+        * rndis_pkt->data_len tell us the real data length, we only copy
+        * the data packet to the stack, without the rndis trailer padding
+        */
+       pkt->total_data_buflen = rndis_pkt->data_len;
        pkt->data = (void *)((unsigned long)pkt->data + data_offset);
 
        pkt->is_data_pkt = true;
@@ -778,6 +797,19 @@ int rndis_filter_send(struct hv_device *dev,
                        (unsigned long)rndisMessage & (PAGE_SIZE-1);
        pkt->page_buf[0].len = rndisMessageSize;
 
+       /* Add one page_buf if the rndis msg goes beyond page boundary */
+       if (pkt->page_buf[0].offset + rndisMessageSize > PAGE_SIZE) {
+               int i;
+               for (i = pkt->page_buf_cnt; i > 1; i--)
+                       pkt->page_buf[i] = pkt->page_buf[i-1];
+               pkt->page_buf_cnt++;
+               pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset;
+               pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong)
+                       rndisMessage + pkt->page_buf[0].len)) >> PAGE_SHIFT;
+               pkt->page_buf[1].offset = 0;
+               pkt->page_buf[1].len = rndisMessageSize - pkt->page_buf[0].len;
+       }
+
        /* Save the packet send completion and context */
        filterPacket->completion = pkt->completion.send.send_completion;
        filterPacket->completion_ctx =
index f2f820c4b40a4fd8c3384905fb30b35dbe7c61fc..9ea99217f11609176d56459c3e35f55185e6f2af 100644 (file)
@@ -173,6 +173,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
                skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
                if (!skb)
                        return RX_HANDLER_CONSUMED;
+               eth = eth_hdr(skb);
                src = macvlan_hash_lookup(port, eth->h_source);
                if (!src)
                        /* frame comes from an external address */
index 88cc5db9affd7a4923fe29de85c63cd98d80c3aa..8985cc62cf41c888ed5a31c9e0877bb2463c5555 100644 (file)
 
 /**
  * mdiobus_alloc_size - allocate a mii_bus structure
+ * @size: extra amount of memory to allocate for private storage.
+ * If non-zero, then bus->priv is points to that memory.
  *
  * Description: called by a bus driver to allocate an mii_bus
  * structure to fill in.
- *
- * 'size' is an an extra amount of memory to allocate for private storage.
- * If non-zero, then bus->priv is points to that memory.
  */
 struct mii_bus *mdiobus_alloc_size(size_t size)
 {
index ed2a862b835df3d9a50b43ac64544ca3e5911036..6b678f38e5ced5336cf81c632767e5e13100fe65 100644 (file)
@@ -92,9 +92,9 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name)
        return NULL;
 }
 
-int team_options_register(struct team *team,
-                         const struct team_option *option,
-                         size_t option_count)
+int __team_options_register(struct team *team,
+                           const struct team_option *option,
+                           size_t option_count)
 {
        int i;
        struct team_option **dst_opts;
@@ -116,8 +116,11 @@ int team_options_register(struct team *team,
                }
        }
 
-       for (i = 0; i < option_count; i++)
+       for (i = 0; i < option_count; i++) {
+               dst_opts[i]->changed = true;
+               dst_opts[i]->removed = false;
                list_add_tail(&dst_opts[i]->list, &team->option_list);
+       }
 
        kfree(dst_opts);
        return 0;
@@ -130,10 +133,22 @@ rollback:
        return err;
 }
 
-EXPORT_SYMBOL(team_options_register);
+static void __team_options_mark_removed(struct team *team,
+                                       const struct team_option *option,
+                                       size_t option_count)
+{
+       int i;
+
+       for (i = 0; i < option_count; i++, option++) {
+               struct team_option *del_opt;
 
-static void __team_options_change_check(struct team *team,
-                                       struct team_option *changed_option);
+               del_opt = __team_find_option(team, option->name);
+               if (del_opt) {
+                       del_opt->changed = true;
+                       del_opt->removed = true;
+               }
+       }
+}
 
 static void __team_options_unregister(struct team *team,
                                      const struct team_option *option,
@@ -152,12 +167,29 @@ static void __team_options_unregister(struct team *team,
        }
 }
 
+static void __team_options_change_check(struct team *team);
+
+int team_options_register(struct team *team,
+                         const struct team_option *option,
+                         size_t option_count)
+{
+       int err;
+
+       err = __team_options_register(team, option, option_count);
+       if (err)
+               return err;
+       __team_options_change_check(team);
+       return 0;
+}
+EXPORT_SYMBOL(team_options_register);
+
 void team_options_unregister(struct team *team,
                             const struct team_option *option,
                             size_t option_count)
 {
+       __team_options_mark_removed(team, option, option_count);
+       __team_options_change_check(team);
        __team_options_unregister(team, option, option_count);
-       __team_options_change_check(team, NULL);
 }
 EXPORT_SYMBOL(team_options_unregister);
 
@@ -176,7 +208,8 @@ static int team_option_set(struct team *team, struct team_option *option,
        if (err)
                return err;
 
-       __team_options_change_check(team, option);
+       option->changed = true;
+       __team_options_change_check(team);
        return err;
 }
 
@@ -653,6 +686,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
                return -ENOENT;
        }
 
+       port->removed = true;
        __team_port_change_check(port, false);
        team_port_list_del_port(team, port);
        team_adjust_ops(team);
@@ -1200,10 +1234,9 @@ err_fill:
        return err;
 }
 
-static int team_nl_fill_options_get_changed(struct sk_buff *skb,
-                                           u32 pid, u32 seq, int flags,
-                                           struct team *team,
-                                           struct team_option *changed_option)
+static int team_nl_fill_options_get(struct sk_buff *skb,
+                                   u32 pid, u32 seq, int flags,
+                                   struct team *team, bool fillall)
 {
        struct nlattr *option_list;
        void *hdr;
@@ -1223,12 +1256,19 @@ static int team_nl_fill_options_get_changed(struct sk_buff *skb,
                struct nlattr *option_item;
                long arg;
 
+               /* Include only changed options if fill all mode is not on */
+               if (!fillall && !option->changed)
+                       continue;
                option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
                if (!option_item)
                        goto nla_put_failure;
                NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name);
-               if (option == changed_option)
+               if (option->changed) {
                        NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED);
+                       option->changed = false;
+               }
+               if (option->removed)
+                       NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED);
                switch (option->type) {
                case TEAM_OPTION_TYPE_U32:
                        NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32);
@@ -1255,13 +1295,13 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int team_nl_fill_options_get(struct sk_buff *skb,
-                                   struct genl_info *info, int flags,
-                                   struct team *team)
+static int team_nl_fill_options_get_all(struct sk_buff *skb,
+                                       struct genl_info *info, int flags,
+                                       struct team *team)
 {
-       return team_nl_fill_options_get_changed(skb, info->snd_pid,
-                                               info->snd_seq, NLM_F_ACK,
-                                               team, NULL);
+       return team_nl_fill_options_get(skb, info->snd_pid,
+                                       info->snd_seq, NLM_F_ACK,
+                                       team, true);
 }
 
 static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
@@ -1273,7 +1313,7 @@ static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
        if (!team)
                return -EINVAL;
 
-       err = team_nl_send_generic(info, team, team_nl_fill_options_get);
+       err = team_nl_send_generic(info, team, team_nl_fill_options_get_all);
 
        team_nl_team_put(team);
 
@@ -1365,10 +1405,10 @@ team_put:
        return err;
 }
 
-static int team_nl_fill_port_list_get_changed(struct sk_buff *skb,
-                                             u32 pid, u32 seq, int flags,
-                                             struct team *team,
-                                             struct team_port *changed_port)
+static int team_nl_fill_port_list_get(struct sk_buff *skb,
+                                     u32 pid, u32 seq, int flags,
+                                     struct team *team,
+                                     bool fillall)
 {
        struct nlattr *port_list;
        void *hdr;
@@ -1387,12 +1427,19 @@ static int team_nl_fill_port_list_get_changed(struct sk_buff *skb,
        list_for_each_entry(port, &team->port_list, list) {
                struct nlattr *port_item;
 
+               /* Include only changed ports if fill all mode is not on */
+               if (!fillall && !port->changed)
+                       continue;
                port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT);
                if (!port_item)
                        goto nla_put_failure;
                NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex);
-               if (port == changed_port)
+               if (port->changed) {
                        NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED);
+                       port->changed = false;
+               }
+               if (port->removed)
+                       NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED);
                if (port->linkup)
                        NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP);
                NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed);
@@ -1408,13 +1455,13 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int team_nl_fill_port_list_get(struct sk_buff *skb,
-                                     struct genl_info *info, int flags,
-                                     struct team *team)
+static int team_nl_fill_port_list_get_all(struct sk_buff *skb,
+                                         struct genl_info *info, int flags,
+                                         struct team *team)
 {
-       return team_nl_fill_port_list_get_changed(skb, info->snd_pid,
-                                                 info->snd_seq, NLM_F_ACK,
-                                                 team, NULL);
+       return team_nl_fill_port_list_get(skb, info->snd_pid,
+                                         info->snd_seq, NLM_F_ACK,
+                                         team, true);
 }
 
 static int team_nl_cmd_port_list_get(struct sk_buff *skb,
@@ -1427,7 +1474,7 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb,
        if (!team)
                return -EINVAL;
 
-       err = team_nl_send_generic(info, team, team_nl_fill_port_list_get);
+       err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all);
 
        team_nl_team_put(team);
 
@@ -1464,8 +1511,7 @@ static struct genl_multicast_group team_change_event_mcgrp = {
        .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
 };
 
-static int team_nl_send_event_options_get(struct team *team,
-                                         struct team_option *changed_option)
+static int team_nl_send_event_options_get(struct team *team)
 {
        struct sk_buff *skb;
        int err;
@@ -1475,8 +1521,7 @@ static int team_nl_send_event_options_get(struct team *team,
        if (!skb)
                return -ENOMEM;
 
-       err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team,
-                                              changed_option);
+       err = team_nl_fill_options_get(skb, 0, 0, 0, team, false);
        if (err < 0)
                goto err_fill;
 
@@ -1489,18 +1534,17 @@ err_fill:
        return err;
 }
 
-static int team_nl_send_event_port_list_get(struct team_port *port)
+static int team_nl_send_event_port_list_get(struct team *team)
 {
        struct sk_buff *skb;
        int err;
-       struct net *net = dev_net(port->team->dev);
+       struct net *net = dev_net(team->dev);
 
        skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
 
-       err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0,
-                                                port->team, port);
+       err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false);
        if (err < 0)
                goto err_fill;
 
@@ -1544,12 +1588,11 @@ static void team_nl_fini(void)
  * Change checkers
  ******************/
 
-static void __team_options_change_check(struct team *team,
-                                       struct team_option *changed_option)
+static void __team_options_change_check(struct team *team)
 {
        int err;
 
-       err = team_nl_send_event_options_get(team, changed_option);
+       err = team_nl_send_event_options_get(team);
        if (err)
                netdev_warn(team->dev, "Failed to send options change via netlink\n");
 }
@@ -1559,9 +1602,10 @@ static void __team_port_change_check(struct team_port *port, bool linkup)
 {
        int err;
 
-       if (port->linkup == linkup)
+       if (!port->removed && port->linkup == linkup)
                return;
 
+       port->changed = true;
        port->linkup = linkup;
        if (linkup) {
                struct ethtool_cmd ecmd;
@@ -1577,7 +1621,7 @@ static void __team_port_change_check(struct team_port *port, bool linkup)
        port->duplex = 0;
 
 send_event:
-       err = team_nl_send_event_port_list_get(port);
+       err = team_nl_send_event_port_list_get(port->team);
        if (err)
                netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n",
                            port->dev->name);
index c7e0149d151462206eb86fd829e69a6b92218b25..45550d42b368084799a18b8ff7ad47b6ce6e38f2 100644 (file)
@@ -7,7 +7,6 @@ menuconfig TR
        bool "Token Ring driver support"
        depends on NETDEVICES && !UML
        depends on (PCI || ISA || MCA || CCW || PCMCIA)
-       select LLC
        help
          Token Ring is IBM's way of communication on a local network; the
          rest of the world uses Ethernet. To participate on a Token Ring
@@ -20,6 +19,10 @@ menuconfig TR
 
 if TR
 
+config WANT_LLC
+       def_bool y
+       select LLC
+
 config PCMCIA_IBMTR
        tristate "IBM PCMCIA tokenring adapter support"
        depends on IBMTR!=y && PCMCIA
index e84662db51ccd139d9fe7086ecd4f4a06513d203..dd78c4cbd45972a0bb7c342cefd08498ea827dfb 100644 (file)
@@ -60,6 +60,7 @@
 #define USB_PRODUCT_IPHONE_3GS  0x1294
 #define USB_PRODUCT_IPHONE_4   0x1297
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
+#define USB_PRODUCT_IPHONE_4S  0x12a0
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -103,6 +104,10 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
index 49f4667e1fa3c20342b1ca18240a93ece55f9016..4a3402898f2a1100fdae0b38d65d172a8c160da9 100644 (file)
@@ -422,7 +422,9 @@ static void veth_dellink(struct net_device *dev, struct list_head *head)
        unregister_netdevice_queue(peer, head);
 }
 
-static const struct nla_policy veth_policy[VETH_INFO_MAX + 1];
+static const struct nla_policy veth_policy[VETH_INFO_MAX + 1] = {
+       [VETH_INFO_PEER]        = { .len = sizeof(struct ifinfomsg) },
+};
 
 static struct rtnl_link_ops veth_link_ops = {
        .kind           = DRV_NAME,
index 88c81c5706b249a0e08a25c28217775463dd53dc..09b8c9dbf78f5e3267ebfadc2d4bed15f9562487 100644 (file)
@@ -557,10 +557,11 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
                        rxs->rs_status |= ATH9K_RXERR_DECRYPT;
                else if (rxsp->status11 & AR_MichaelErr)
                        rxs->rs_status |= ATH9K_RXERR_MIC;
-               if (rxsp->status11 & AR_KeyMiss)
-                       rxs->rs_status |= ATH9K_RXERR_KEYMISS;
        }
 
+       if (rxsp->status11 & AR_KeyMiss)
+               rxs->rs_status |= ATH9K_RXERR_KEYMISS;
+
        return 0;
 }
 EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma);
index ee77595750503db51e83ef90644f7884a5c529a5..87db1ee1c298ae32ac1434e7f3db58e25bfbee92 100644 (file)
@@ -1037,13 +1037,16 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
 
        /*
         * Workaround for early ACK timeouts, add an offset to match the
-        * initval's 64us ack timeout value.
+        * initval's 64us ack timeout value. Use 48us for the CTS timeout.
         * This was initially only meant to work around an issue with delayed
         * BA frames in some implementations, but it has been found to fix ACK
         * timeout issues in other cases as well.
         */
-       if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
+       if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {
                acktimeout += 64 - sifstime - ah->slottime;
+               ctstimeout += 48 - sifstime - ah->slottime;
+       }
+
 
        ath9k_hw_set_sifs_time(ah, sifstime);
        ath9k_hw_setslottime(ah, slottime);
index abf943557deeca279a82ca434cb4eb5032d6805b..53a005d288aa53949da6e1317c57e294a092a907 100644 (file)
@@ -822,6 +822,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
                ARRAY_SIZE(ath9k_tpt_blink));
 #endif
 
+       INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+       INIT_WORK(&sc->hw_check_work, ath_hw_check);
+       INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+       INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+
        /* Register with mac80211 */
        error = ieee80211_register_hw(hw);
        if (error)
@@ -840,10 +845,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
                        goto error_world;
        }
 
-       INIT_WORK(&sc->hw_reset_work, ath_reset_work);
-       INIT_WORK(&sc->hw_check_work, ath_hw_check);
-       INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
-       INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
        sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
 
        ath_init_leds(sc);
index fd3f19c2e550e4e9991c4adc9b430a91799c9bd4..e196aba77acf568387d7a4b2b5852e316d801e4f 100644 (file)
@@ -618,10 +618,11 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
                else if (ads.ds_rxstatus8 & AR_MichaelErr)
                        rs->rs_status |= ATH9K_RXERR_MIC;
-               if (ads.ds_rxstatus8 & AR_KeyMiss)
-                       rs->rs_status |= ATH9K_RXERR_KEYMISS;
        }
 
+       if (ads.ds_rxstatus8 & AR_KeyMiss)
+               rs->rs_status |= ATH9K_RXERR_KEYMISS;
+
        return 0;
 }
 EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
index b3c3798fe5130eaf4e4ea7e528a3e8c646f8711b..635b592ad96181478af45cb2697ea05dbd823077 100644 (file)
@@ -694,7 +694,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
                return rate;
 
        /* This should not happen */
-       WARN_ON(1);
+       WARN_ON_ONCE(1);
 
        rate = ath_rc_priv->valid_rate_index[0];
 
index 0e666fbe084279fd91921de34efccc20b814894e..7e1a91af149751b13a53ee9d6dab5c16fcd2f01f 100644 (file)
@@ -822,6 +822,14 @@ static bool ath9k_rx_accept(struct ath_common *common,
                (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
                 ATH9K_RXERR_KEYMISS));
 
+       /*
+        * Key miss events are only relevant for pairwise keys where the
+        * descriptor does contain a valid key index. This has been observed
+        * mostly with CCMP encryption.
+        */
+       if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID)
+               rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
        if (!rx_stats->rs_datalen)
                return false;
         /*
index b97a40ed5fff104864a9cfbe296a31c8a96bf170..3876c7ea54f49bd3a988d159f7f7bf66ab80fe69 100644 (file)
@@ -31,6 +31,12 @@ config B43_BCMA
        depends on B43 && BCMA
        default y
 
+config B43_BCMA_EXTRA
+       bool "Hardware support that overlaps with the brcmsmac driver"
+       depends on B43_BCMA
+       default n if BRCMSMAC || BRCMSMAC_MODULE
+       default y
+
 config B43_SSB
        bool
        depends on B43 && SSB
index 1c6f19393efa72037b7369993bf7af463a7bb51a..23ffb1b9a86f441f771c8f2ac200d823d76cf440 100644 (file)
@@ -116,8 +116,10 @@ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
 #ifdef CONFIG_B43_BCMA
 static const struct bcma_device_id b43_bcma_tbl[] = {
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+#ifdef CONFIG_B43_BCMA_EXTRA
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+#endif
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
        BCMA_CORETABLE_END
 };
@@ -4852,6 +4854,9 @@ static void b43_op_stop(struct ieee80211_hw *hw)
 
        cancel_work_sync(&(wl->beacon_update_trigger));
 
+       if (!dev)
+               goto out;
+
        mutex_lock(&wl->mutex);
        if (b43_status(dev) >= B43_STAT_STARTED) {
                dev = b43_wireless_core_stop(dev);
@@ -4863,7 +4868,7 @@ static void b43_op_stop(struct ieee80211_hw *hw)
 
 out_unlock:
        mutex_unlock(&wl->mutex);
-
+out:
        cancel_work_sync(&(wl->txpower_adjust_work));
 }
 
index f23b0c3e4ea3d94985cbdc4b61d6f2688ef52164..bf11850a20f11b1201179c7c7659a16397f2d4cc 100644 (file)
@@ -2475,7 +2475,7 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
        return err;
 }
 
-static void brcmf_delay(u32 ms)
+static __always_inline void brcmf_delay(u32 ms)
 {
        if (ms < 1000 / HZ) {
                cond_resched();
index d106576ce338980b4645ced6084139084f74fc21..448ab9c4eb47b00db5ff558db6a4ab978a4f4f77 100644 (file)
@@ -1128,14 +1128,7 @@ static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
        return 0;
 }
 
-static int brcms_pci_suspend(struct pci_dev *pdev)
-{
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       return pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static int brcms_suspend(struct bcma_device *pdev, pm_message_t state)
+static int brcms_suspend(struct bcma_device *pdev)
 {
        struct brcms_info *wl;
        struct ieee80211_hw *hw;
@@ -1153,40 +1146,15 @@ static int brcms_suspend(struct bcma_device *pdev, pm_message_t state)
        wl->pub->hw_up = false;
        spin_unlock_bh(&wl->lock);
 
-       /* temporarily do suspend ourselves */
-       return brcms_pci_suspend(pdev->bus->host_pci);
-}
-
-static int brcms_pci_resume(struct pci_dev *pdev)
-{
-       int err = 0;
-       uint val;
-
-       err = pci_set_power_state(pdev, PCI_D0);
-       if (err)
-               return err;
-
-       pci_restore_state(pdev);
-
-       err = pci_enable_device(pdev);
-       if (err)
-               return err;
-
-       pci_set_master(pdev);
-
-       pci_read_config_dword(pdev, 0x40, &val);
-       if ((val & 0x0000ff00) != 0)
-               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+       pr_debug("brcms_suspend ok\n");
 
        return 0;
 }
 
 static int brcms_resume(struct bcma_device *pdev)
 {
-       /*
-       *  just do pci resume for now until bcma supports it.
-       */
-       return brcms_pci_resume(pdev->bus->host_pci);
+       pr_debug("brcms_resume ok\n");
+       return 0;
 }
 
 static struct bcma_driver brcms_bcma_driver = {
index f7ed34034f88cf12ed53694edd6621e14cf26a44..f6affc6fd12a511831d07d7333ea0b45f0bb8d5f 100644 (file)
@@ -7981,13 +7981,21 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
 
 void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
 {
+       int timeout = 20;
+
        /* flush packet queue when requested */
        if (drop)
                brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
 
        /* wait for queue and DMA fifos to run dry */
-       while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+       while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) {
                brcms_msleep(wlc->wl, 1);
+
+               if (--timeout == 0)
+                       break;
+       }
+
+       WARN_ON_ONCE(timeout == 0);
 }
 
 void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
index 018a8deb88a83b5b2ab2febcc2487b89eeb4ba4f..4fcdac63a3007aff3822e8dd17ccd5db57ce69a6 100644 (file)
@@ -7848,7 +7848,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
         * more efficiently than we can parse it. ORDER MATTERS HERE */
        struct ipw_rt_hdr *ipw_rt;
 
-       short len = le16_to_cpu(pkt->u.frame.length);
+       unsigned short len = le16_to_cpu(pkt->u.frame.length);
 
        /* We received data from the HW, so stop the watchdog */
        dev->trans_start = jiffies;
@@ -8023,7 +8023,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
        s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM;
        s8 noise = (s8) le16_to_cpu(frame->noise);
        u8 rate = frame->rate;
-       short len = le16_to_cpu(pkt->u.frame.length);
+       unsigned short len = le16_to_cpu(pkt->u.frame.length);
        struct sk_buff *skb;
        int hdr_only = 0;
        u16 filter = priv->prom_priv->filter;
index c664c2726553f059b8e160c0552efc0b0b8e75b5..63bbc60be28e461ada4e173b5caafbd43f243c31 100644 (file)
@@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
                tx_cmd->tid_tspec = qc[0] & 0xf;
                tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
        } else {
+               tx_cmd->tid_tspec = IWL_TID_NON_QOS;
                if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
                        tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
                else
@@ -620,7 +621,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
        sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
                sta_priv->max_agg_bufsize;
 
-       IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+       IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
                 sta->addr, tid);
 
        return iwl_send_lq_cmd(priv, ctx,
@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
        u32 status = le16_to_cpu(tx_resp->status.status);
        int i;
 
+       WARN_ON(tid == IWL_TID_NON_QOS);
+
        if (agg->wait_for_ba)
                IWL_DEBUG_TX_REPLY(priv,
                        "got tx response w/o block-ack\n");
@@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
                }
 
                __skb_queue_head_init(&skbs);
-               priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed;
 
-               IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
-                                         next_reclaimed);
+               if (tid != IWL_TID_NON_QOS) {
+                       priv->tid_data[sta_id][tid].next_reclaimed =
+                               next_reclaimed;
+                       IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
+                                                 next_reclaimed);
+               }
 
                /*we can free until ssn % q.n_bd not inclusive */
                WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
index 265de39d394ca9ce7093b37f007e0fb2c3c94a85..f822ac447c3bcd484979d9ce5179a6064bb2e2f9 100644 (file)
@@ -815,6 +815,7 @@ struct iwl_qosparam_cmd {
 
 #define        IWL_INVALID_STATION     255
 #define IWL_MAX_TID_COUNT      8
+#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT
 
 #define STA_FLG_TX_RATE_MSK            cpu_to_le32(1 << 2)
 #define STA_FLG_PWR_SAVE_MSK           cpu_to_le32(1 << 8)
index 084aa2c4ccfb272dab28d57fbc9969644360f314..a6454726737e04b207d0c9ae710098f98cef6c63 100644 (file)
@@ -569,7 +569,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        struct iwl_scan_cmd *scan;
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        u32 rate_flags = 0;
-       u16 cmd_len;
+       u16 cmd_len = 0;
        u16 rx_chain = 0;
        enum ieee80211_band band;
        u8 n_probes = 0;
index 752493f00406a0a808c0984d0ddc96b215ce3fb1..65d1f05007be0e0b6ba421e24b273b3bb77adc97 100644 (file)
@@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
        }
 #endif
 
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
        /* saved interrupt in inta variable now we can reset trans_pcie->inta */
        trans_pcie->inta = 0;
 
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
        /* Now service all interrupt bits discovered above. */
        if (inta & CSR_INT_BIT_HW_ERR) {
                IWL_ERR(trans, "Hardware error detected.  Restarting.\n");
index 67d6e324e26f7b2e75910921aceadc034a5a10ed..324d06dfb69003ca14ac5ab024d800a750057568 100644 (file)
@@ -1262,6 +1262,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
        txq->time_stamp = jiffies;
 
        if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
+                    tid != IWL_TID_NON_QOS &&
                     txq_id != trans_pcie->agg_txq[sta_id][tid])) {
                /*
                 * FIXME: this is a uCode bug which need to be addressed,
index e05b417a3fae8b54d5e632f477dc5885c8a2697f..1d0ec57a0143d8f0a2b15cfbb2220ba065171045 100644 (file)
@@ -382,7 +382,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
 
        adapter->if_ops.cleanup_if(adapter);
 
-       dev_kfree_skb_any(adapter->sleep_cfm);
+       if (adapter->sleep_cfm)
+               dev_kfree_skb_any(adapter->sleep_cfm);
 }
 
 /*
index 84be196188ccc75bfbaf97f1e7bd8c4ab2fd654b..b728f54451e48e65bf4bef4841d0bd69f2e03492 100644 (file)
@@ -822,7 +822,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
                        continue;
 
                rtnl_lock();
-               mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+               if (priv->wdev && priv->netdev)
+                       mwifiex_del_virtual_intf(priv->wdev->wiphy,
+                                                priv->netdev);
                rtnl_unlock();
        }
 
@@ -830,9 +832,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
        if (!priv)
                goto exit_remove;
 
-       wiphy_unregister(priv->wdev->wiphy);
-       wiphy_free(priv->wdev->wiphy);
-       kfree(priv->wdev);
+       if (priv->wdev) {
+               wiphy_unregister(priv->wdev->wiphy);
+               wiphy_free(priv->wdev->wiphy);
+               kfree(priv->wdev);
+       }
 
        mwifiex_terminate_workqueue(adapter);
 
index 470ca75ec250ae522184a1da80170d247ea6733f..b0fbf5d4fea0bd6fbc9b8b340339f1db145059ee 100644 (file)
@@ -54,7 +54,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
 int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
 {
        bool cancel_flag = false;
-       int status = adapter->cmd_wait_q.status;
+       int status;
        struct cmd_ctrl_node *cmd_queued;
 
        if (!adapter->cmd_queued)
@@ -79,6 +79,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
                mwifiex_cancel_pending_ioctl(adapter);
                dev_dbg(adapter->dev, "cmd cancel\n");
        }
+
+       status = adapter->cmd_wait_q.status;
        adapter->cmd_wait_q.status = 0;
 
        return status;
@@ -240,6 +242,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 
                if (!netif_queue_stopped(priv->netdev))
                        mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+               if (netif_carrier_ok(priv->netdev))
+                       netif_carrier_off(priv->netdev);
 
                /* Clear any past association response stored for
                 * application retrieval */
@@ -271,6 +275,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 
                if (!netif_queue_stopped(priv->netdev))
                        mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+               if (netif_carrier_ok(priv->netdev))
+                       netif_carrier_off(priv->netdev);
 
                if (!ret) {
                        dev_dbg(adapter->dev, "info: network found in scan"
index 7becea3dec654de21ab5090fc55b8a5068b7703f..dd5aeaff44ba3483804df003bd5779cbf0138794 100644 (file)
@@ -2777,7 +2777,7 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
        else if (channel->band == IEEE80211_BAND_5GHZ)
                cmd->band = cpu_to_le16(0x4);
 
-       cmd->channel = channel->hw_value;
+       cmd->channel = cpu_to_le16(channel->hw_value);
 
        if (conf->channel_type == NL80211_CHAN_NO_HT ||
            conf->channel_type == NL80211_CHAN_HT20) {
@@ -4066,7 +4066,7 @@ static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
                goto done;
 
        if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-                       WLAN_CIPHER_SUITE_WEP104)
+                       key->cipher == WLAN_CIPHER_SUITE_WEP104)
                mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;
 
        cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);
index 22a1a8fc6e0262fb215c87b8d4427d04cd397142..7bef66def10c469166f6689adefbfe1d477bf034 100644 (file)
@@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
 
 static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
 {
-       int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
-       int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
-       int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
+       s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
+       s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
+       s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
        u16 eeprom;
        u8 offset0;
        u8 offset1;
@@ -552,7 +552,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
         * which gives less energy...
         */
        rssi0 = max(rssi0, rssi1);
-       return max(rssi0, rssi2);
+       return (int)max(rssi0, rssi2);
 }
 
 void rt2800_process_rxwi(struct queue_entry *entry,
index 4941a1a2321907fb93cc8a2fe08a3ce87d8ecf16..dc88baefa72e88bd2b2f60b3ea2e8f7174ff34ed 100644 (file)
@@ -422,7 +422,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
 static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
                                 enum dev_state state)
 {
-       int mask = (state == STATE_RADIO_IRQ_ON);
        u32 reg;
        unsigned long flags;
 
@@ -436,25 +435,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
        }
 
        spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-       rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
+       reg = 0;
+       if (state == STATE_RADIO_IRQ_ON) {
+               rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
+       }
        rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
        spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 
index 39e0907a3c4eac8d89a9f682dc53d8471cbec560..9245d882c06a3046dfb3d052456e6174d99d2a97 100644 (file)
@@ -1501,7 +1501,7 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
                return err;
        }
 
-       return 1;
+       return 0;
 }
 
 static int rtl_pci_start(struct ieee80211_hw *hw)
@@ -1870,7 +1870,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
        }
 
        /* Init PCI sw */
-       err = !rtl_pci_init(hw, pdev);
+       err = rtl_pci_init(hw, pdev);
        if (err) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
                         ("Failed to init PCI.\n"));
index 0a70149df3fcb8aa39c9bbf7556edc5af7cf2da4..98a574a4a465004728792a293551ae867f450d6c 100644 (file)
@@ -866,6 +866,14 @@ static int fill_ctrlset(struct zd_mac *mac,
 
        ZD_ASSERT(frag_len <= 0xffff);
 
+       /*
+        * Firmware computes the duration itself (for all frames except PSPoll)
+        * and needs the field set to 0 at input, otherwise firmware messes up
+        * duration_id and sets bits 14 and 15 on.
+        */
+       if (!ieee80211_is_pspoll(hdr->frame_control))
+               hdr->duration_id = 0;
+
        txrate = ieee80211_get_tx_rate(mac->hw, info);
 
        cs->modulation = txrate->hw_value;
index fa679057630f9152f418e9e2f9b60f549dded7e3..698b905058dd23435b3f13b40ab4e0b7c870b5c5 100644 (file)
@@ -68,7 +68,7 @@ struct netfront_cb {
 
 #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
 #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
-#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256)
 
 struct netfront_stats {
        u64                     rx_packets;
index 0321fa3b42268841d9bc9909354a71f8a385dcc5..0dab5ecf61bb26ad1c7b96684f56b52e7442928d 100644 (file)
@@ -347,8 +347,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
                        return rc;
        }
 
-       pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
-
        iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
        pci_cfg_access_lock(dev);
        pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
@@ -466,6 +464,7 @@ found:
                return -EIO;
 
        pgsz &= ~(pgsz - 1);
+       pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
 
        nres = 0;
        for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
index 97fff785e97e7027f7d54563186db969075a2558..af295bb21d62890020cc2c0084f3570bd42babdc 100644 (file)
@@ -2802,7 +2802,7 @@ pci_intx(struct pci_dev *pdev, int enable)
 
 /**
  * pci_intx_mask_supported - probe for INTx masking support
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
  *
  * Check if the device dev support INTx masking via the config space
  * command word.
@@ -2884,7 +2884,7 @@ done:
 
 /**
  * pci_check_and_mask_intx - mask INTx on pending interrupt
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
  *
  * Check if the device dev has its INTx line asserted, mask it and
  * return true in that case. False is returned if not interrupt was
@@ -2898,7 +2898,7 @@ EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
 
 /**
  * pci_check_and_mask_intx - unmask INTx of no interrupt is pending
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
  *
  * Check if the device dev has its INTx line asserted, unmask it if not
  * and return true. False is returned and the mask remains active if
index 7cc9e2f0f47cab6c55a214af1d9134e77f1bd0a8..71eac9cd724d7b12c77d68cc0eb68a3b50a9f287 100644 (file)
@@ -651,6 +651,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
        dev_dbg(&dev->dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n",
                secondary, subordinate, pass);
 
+       if (!primary && (primary != bus->number) && secondary && subordinate) {
+               dev_warn(&dev->dev, "Primary bus is hard wired to 0\n");
+               primary = bus->number;
+       }
+
        /* Check if setup is sensible at all */
        if (!pass &&
            (primary != bus->number || secondary <= bus->number)) {
index 6def3624c688c64f26f1ce981ab9a58e9e235804..ef8b18c48f2641993f56aa643ed8a35579856971 100644 (file)
@@ -77,6 +77,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
 }
 EXPORT_SYMBOL(pci_remove_bus);
 
+static void __pci_remove_behind_bridge(struct pci_dev *dev);
 /**
  * pci_remove_bus_device - remove a PCI device and any children
  * @dev: the device to remove
@@ -94,7 +95,7 @@ static void __pci_remove_bus_device(struct pci_dev *dev)
        if (dev->subordinate) {
                struct pci_bus *b = dev->subordinate;
 
-               pci_remove_behind_bridge(dev);
+               __pci_remove_behind_bridge(dev);
                pci_remove_bus(b);
                dev->subordinate = NULL;
        }
@@ -107,6 +108,24 @@ void pci_remove_bus_device(struct pci_dev *dev)
        __pci_remove_bus_device(dev);
 }
 
+static void __pci_remove_behind_bridge(struct pci_dev *dev)
+{
+       struct list_head *l, *n;
+
+       if (dev->subordinate)
+               list_for_each_safe(l, n, &dev->subordinate->devices)
+                       __pci_remove_bus_device(pci_dev_b(l));
+}
+
+static void pci_stop_behind_bridge(struct pci_dev *dev)
+{
+       struct list_head *l, *n;
+
+       if (dev->subordinate)
+               list_for_each_safe(l, n, &dev->subordinate->devices)
+                       pci_stop_bus_device(pci_dev_b(l));
+}
+
 /**
  * pci_remove_behind_bridge - remove all devices behind a PCI bridge
  * @dev: PCI bridge device
@@ -117,11 +136,8 @@ void pci_remove_bus_device(struct pci_dev *dev)
  */
 void pci_remove_behind_bridge(struct pci_dev *dev)
 {
-       struct list_head *l, *n;
-
-       if (dev->subordinate)
-               list_for_each_safe(l, n, &dev->subordinate->devices)
-                       __pci_remove_bus_device(pci_dev_b(l));
+       pci_stop_behind_bridge(dev);
+       __pci_remove_behind_bridge(dev);
 }
 
 static void pci_stop_bus_devices(struct pci_bus *bus)
index 7cf3d2fcf56a9369209395304494d4b7699d5f6d..1620088a0e7e34d6f11b6f6d347d9111fc60de9d 100644 (file)
@@ -189,7 +189,7 @@ static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
 
        if (verbose_request)
                dev_info(&pdev->xdev->dev,
-                        "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
+                        "read dev=%04x:%02x:%02x.%d - offset %x size %d\n",
                         pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
                         PCI_FUNC(devfn), where, size);
 
@@ -228,7 +228,7 @@ static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
 
        if (verbose_request)
                dev_info(&pdev->xdev->dev,
-                        "write dev=%04x:%02x:%02x.%01x - "
+                        "write dev=%04x:%02x:%02x.%d - "
                         "offset %x size %d val %x\n",
                         pci_domain_nr(bus), bus->number,
                         PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
@@ -432,7 +432,7 @@ static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
                d = pci_scan_single_device(b, devfn);
                if (d)
                        dev_info(&pdev->xdev->dev, "New device on "
-                                "%04x:%02x:%02x.%02x found.\n", domain, bus,
+                                "%04x:%02x:%02x.%d found.\n", domain, bus,
                                 PCI_SLOT(devfn), PCI_FUNC(devfn));
        }
 
@@ -1041,7 +1041,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
                pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func));
                if (!pci_dev) {
                        dev_dbg(&pdev->xdev->dev,
-                               "Cannot get PCI device %04x:%02x:%02x.%02x\n",
+                               "Cannot get PCI device %04x:%02x:%02x.%d\n",
                                domain, bus, slot, func);
                        continue;
                }
@@ -1049,7 +1049,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
                pci_dev_put(pci_dev);
 
                dev_dbg(&pdev->xdev->dev,
-                       "PCI device %04x:%02x:%02x.%02x removed.\n",
+                       "PCI device %04x:%02x:%02x.%d removed.\n",
                        domain, bus, slot, func);
        }
 
index 749c2a16012c582bca165db93f14cf4c21ec5293..1932029de48d67cf7dd10ed18f2de11e40056c29 100644 (file)
@@ -1269,10 +1269,8 @@ static int pcmcia_bus_add(struct pcmcia_socket *skt)
 
 static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
 {
-       if (!verify_cis_cache(skt)) {
-               pcmcia_put_socket(skt);
+       if (!verify_cis_cache(skt))
                return 0;
-       }
 
        dev_dbg(&skt->dev, "cis mismatch - different card\n");
 
index 59866905ea37e5f2150221506cf9bac73b2eaa6d..27f2fe3b7fb4a5e41a44a03fa75e2becce0d63d7 100644 (file)
@@ -205,7 +205,8 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev)
 
        dev_set_drvdata(&dev->dev, NULL);
 
-       for (; next = s->next, s; s = next) {
+       for (; s; s = next) {
+               next = s->next;
                soc_pcmcia_remove_one(&s->soc);
                kfree(s);
        }
index 569bdb3ef1046155b021648390087a9010591d3b..894cd5e103da6225bd660d66b696b44eab6d4a12 100644 (file)
@@ -189,7 +189,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
        pindesc->pctldev = pctldev;
 
        /* Copy basic pin info */
-       if (pindesc->name) {
+       if (name) {
                pindesc->name = name;
        } else {
                pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number);
@@ -510,10 +510,12 @@ static struct dentry *debugfs_root;
 
 static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
 {
-       static struct dentry *device_root;
+       struct dentry *device_root;
 
        device_root = debugfs_create_dir(dev_name(pctldev->dev),
                                         debugfs_root);
+       pctldev->device_root = device_root;
+
        if (IS_ERR(device_root) || !device_root) {
                pr_warn("failed to create debugfs directory for %s\n",
                        dev_name(pctldev->dev));
@@ -529,6 +531,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
        pinconf_init_device_debugfs(device_root, pctldev);
 }
 
+static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
+{
+       debugfs_remove_recursive(pctldev->device_root);
+}
+
 static void pinctrl_init_debugfs(void)
 {
        debugfs_root = debugfs_create_dir("pinctrl", NULL);
@@ -553,6 +560,10 @@ static void pinctrl_init_debugfs(void)
 {
 }
 
+static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
+{
+}
+
 #endif
 
 /**
@@ -572,40 +583,40 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
        if (pctldesc->name == NULL)
                return NULL;
 
+       pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
+       if (pctldev == NULL)
+               return NULL;
+
+       /* Initialize pin control device struct */
+       pctldev->owner = pctldesc->owner;
+       pctldev->desc = pctldesc;
+       pctldev->driver_data = driver_data;
+       INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
+       spin_lock_init(&pctldev->pin_desc_tree_lock);
+       INIT_LIST_HEAD(&pctldev->gpio_ranges);
+       mutex_init(&pctldev->gpio_ranges_lock);
+       pctldev->dev = dev;
+
        /* If we're implementing pinmuxing, check the ops for sanity */
        if (pctldesc->pmxops) {
-               ret = pinmux_check_ops(pctldesc->pmxops);
+               ret = pinmux_check_ops(pctldev);
                if (ret) {
                        pr_err("%s pinmux ops lacks necessary functions\n",
                               pctldesc->name);
-                       return NULL;
+                       goto out_err;
                }
        }
 
        /* If we're implementing pinconfig, check the ops for sanity */
        if (pctldesc->confops) {
-               ret = pinconf_check_ops(pctldesc->confops);
+               ret = pinconf_check_ops(pctldev);
                if (ret) {
                        pr_err("%s pin config ops lacks necessary functions\n",
                               pctldesc->name);
-                       return NULL;
+                       goto out_err;
                }
        }
 
-       pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
-       if (pctldev == NULL)
-               return NULL;
-
-       /* Initialize pin control device struct */
-       pctldev->owner = pctldesc->owner;
-       pctldev->desc = pctldesc;
-       pctldev->driver_data = driver_data;
-       INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
-       spin_lock_init(&pctldev->pin_desc_tree_lock);
-       INIT_LIST_HEAD(&pctldev->gpio_ranges);
-       mutex_init(&pctldev->gpio_ranges_lock);
-       pctldev->dev = dev;
-
        /* Register all the pins */
        pr_debug("try to register %d pins on %s...\n",
                 pctldesc->npins, pctldesc->name);
@@ -641,6 +652,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
        if (pctldev == NULL)
                return;
 
+       pinctrl_remove_device_debugfs(pctldev);
        pinmux_unhog_maps(pctldev);
        /* TODO: check that no pinmuxes are still active? */
        mutex_lock(&pinctrldev_list_mutex);
index 177a3310547f31ceb8a9cd1191cb55f7f253469d..cfa86da6b4b15b546cbf78de371247812c162a9c 100644 (file)
@@ -41,6 +41,9 @@ struct pinctrl_dev {
        struct device *dev;
        struct module *owner;
        void *driver_data;
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *device_root;
+#endif
 #ifdef CONFIG_PINMUX
        struct mutex pinmux_hogs_lock;
        struct list_head pinmux_hogs;
index 1259872b0a1d641e9da7f34cfd57a1f9e2ae1c91..9fb75456824c3b562fe11fa19f23c5f20d9dcc26 100644 (file)
@@ -205,8 +205,10 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
 }
 EXPORT_SYMBOL(pin_config_group_set);
 
-int pinconf_check_ops(const struct pinconf_ops *ops)
+int pinconf_check_ops(struct pinctrl_dev *pctldev)
 {
+       const struct pinconf_ops *ops = pctldev->desc->confops;
+
        /* We must be able to read out pin status */
        if (!ops->pin_config_get && !ops->pin_config_group_get)
                return -EINVAL;
@@ -236,7 +238,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
        seq_puts(s, "Format: pin (name): pinmux setting array\n");
 
        /* The pin number can be retrived from the pin controller descriptor */
-       for (i = 0; pin < pctldev->desc->npins; i++) {
+       for (i = 0; i < pctldev->desc->npins; i++) {
                struct pin_desc *desc;
 
                pin = pctldev->desc->pins[i].number;
index e7dc6165032a35e540216d870d6ef75b2acb78e6..006b77fa737e8841ff84713fe3ea24b74a82fd37 100644 (file)
@@ -13,7 +13,7 @@
 
 #ifdef CONFIG_PINCONF
 
-int pinconf_check_ops(const struct pinconf_ops *ops);
+int pinconf_check_ops(struct pinctrl_dev *pctldev);
 void pinconf_init_device_debugfs(struct dentry *devroot,
                                 struct pinctrl_dev *pctldev);
 int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
@@ -23,7 +23,7 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
 
 #else
 
-static inline int pinconf_check_ops(const struct pinconf_ops *ops)
+static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
 {
        return 0;
 }
index a76a348321bb4284d6820279fed3bb679cd23fcf..7c3193f7a04430bcc8076dfd18aafc05983e915b 100644 (file)
@@ -53,11 +53,6 @@ struct pinmux_group {
  * @dev: the device using this pinmux
  * @usecount: the number of active users of this mux setting, used to keep
  *     track of nested use cases
- * @pins: an array of discrete physical pins used in this mapping, taken
- *     from the global pin enumeration space (copied from pinmux map)
- * @num_pins: the number of pins in this mapping array, i.e. the number of
- *     elements in .pins so we can iterate over that array (copied from
- *     pinmux map)
  * @pctldev: pin control device handling this pinmux
  * @func_selector: the function selector for the pinmux device handling
  *     this pinmux
@@ -152,8 +147,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
                status = 0;
 
        if (status)
-               dev_err(pctldev->dev, "->request on device %s failed "
-                      "for pin %d\n",
+               dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
                       pctldev->desc->name, pin);
 out_free_pin:
        if (status) {
@@ -355,21 +349,20 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
        /* First sanity check the new mapping */
        for (i = 0; i < num_maps; i++) {
                if (!maps[i].name) {
-                       pr_err("failed to register map %d: "
-                              "no map name given\n", i);
+                       pr_err("failed to register map %d: no map name given\n",
+                                       i);
                        return -EINVAL;
                }
 
                if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
-                       pr_err("failed to register map %s (%d): "
-                              "no pin control device given\n",
+                       pr_err("failed to register map %s (%d): no pin control device given\n",
                               maps[i].name, i);
                        return -EINVAL;
                }
 
                if (!maps[i].function) {
-                       pr_err("failed to register map %s (%d): "
-                              "no function ID given\n", maps[i].name, i);
+                       pr_err("failed to register map %s (%d): no function ID given\n",
+                                       maps[i].name, i);
                        return -EINVAL;
                }
 
@@ -411,7 +404,7 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
 }
 
 /**
- * acquire_pins() - acquire all the pins for a certain funcion on a pinmux
+ * acquire_pins() - acquire all the pins for a certain function on a pinmux
  * @pctldev: the device to take the pins on
  * @func_selector: the function selector to acquire the pins for
  * @group_selector: the group selector containing the pins to acquire
@@ -442,8 +435,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
                ret = pin_request(pctldev, pins[i], func, NULL);
                if (ret) {
                        dev_err(pctldev->dev,
-                               "could not get pin %d for function %s "
-                               "on device %s - conflicting mux mappings?\n",
+                               "could not get pin %d for function %s on device %s - conflicting mux mappings?\n",
                                pins[i], func ? : "(undefined)",
                                pinctrl_dev_get_name(pctldev));
                        /* On error release all taken pins */
@@ -458,7 +450,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
 
 /**
  * release_pins() - release pins taken by earlier acquirement
- * @pctldev: the device to free the pinx on
+ * @pctldev: the device to free the pins on
  * @group_selector: the group selector containing the pins to free
  */
 static void release_pins(struct pinctrl_dev *pctldev,
@@ -473,8 +465,7 @@ static void release_pins(struct pinctrl_dev *pctldev,
        ret = pctlops->get_group_pins(pctldev, group_selector,
                                      &pins, &num_pins);
        if (ret) {
-               dev_err(pctldev->dev, "could not get pins to release for "
-                       "group selector %d\n",
+               dev_err(pctldev->dev, "could not get pins to release for group selector %d\n",
                        group_selector);
                return;
        }
@@ -526,8 +517,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
                ret = pinctrl_get_group_selector(pctldev, groups[0]);
                if (ret < 0) {
                        dev_err(pctldev->dev,
-                               "function %s wants group %s but the pin "
-                               "controller does not seem to have that group\n",
+                               "function %s wants group %s but the pin controller does not seem to have that group\n",
                                pmxops->get_function_name(pctldev, func_selector),
                                groups[0]);
                        return ret;
@@ -535,8 +525,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
 
                if (num_groups > 1)
                        dev_dbg(pctldev->dev,
-                               "function %s support more than one group, "
-                               "default-selecting first group %s (%d)\n",
+                               "function %s support more than one group, default-selecting first group %s (%d)\n",
                                pmxops->get_function_name(pctldev, func_selector),
                                groups[0],
                                ret);
@@ -628,10 +617,8 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
 
        if (pmx->pctldev && pmx->pctldev != pctldev) {
                dev_err(pctldev->dev,
-                       "different pin control devices given for device %s, "
-                       "function %s\n",
-                       devname,
-                       map->function);
+                       "different pin control devices given for device %s, function %s\n",
+                       devname, map->function);
                return -EINVAL;
        }
        pmx->dev = dev;
@@ -695,7 +682,6 @@ static void pinmux_free_groups(struct pinmux *pmx)
  */
 struct pinmux *pinmux_get(struct device *dev, const char *name)
 {
-
        struct pinmux_map const *map = NULL;
        struct pinctrl_dev *pctldev = NULL;
        const char *devname = NULL;
@@ -745,8 +731,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name)
                        else if (map->ctrl_dev_name)
                                devname = map->ctrl_dev_name;
 
-                       pr_warning("could not find a pinctrl device for pinmux "
-                                  "function %s, fishy, they shall all have one\n",
+                       pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n",
                                   map->function);
                        pr_warning("given pinctrl device name: %s",
                                   devname ? devname : "UNDEFINED");
@@ -904,8 +889,11 @@ void pinmux_disable(struct pinmux *pmx)
 }
 EXPORT_SYMBOL_GPL(pinmux_disable);
 
-int pinmux_check_ops(const struct pinmux_ops *ops)
+int pinmux_check_ops(struct pinctrl_dev *pctldev)
 {
+       const struct pinmux_ops *ops = pctldev->desc->pmxops;
+       unsigned selector = 0;
+
        /* Check that we implement required operations */
        if (!ops->list_functions ||
            !ops->get_function_name ||
@@ -914,6 +902,18 @@ int pinmux_check_ops(const struct pinmux_ops *ops)
            !ops->disable)
                return -EINVAL;
 
+       /* Check that all functions registered have names */
+       while (ops->list_functions(pctldev, selector) >= 0) {
+               const char *fname = ops->get_function_name(pctldev,
+                                                          selector);
+               if (!fname) {
+                       pr_err("pinmux ops has no name for function%u\n",
+                               selector);
+                       return -EINVAL;
+               }
+               selector++;
+       }
+
        return 0;
 }
 
@@ -932,8 +932,8 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
                 * without any problems, so then we can hog pinmuxes for
                 * all devices that just want a static pin mux at this point.
                 */
-               dev_err(pctldev->dev, "map %s wants to hog a non-system "
-                       "pinmux, this is not going to work\n", map->name);
+               dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n",
+                               map->name);
                return -EINVAL;
        }
 
@@ -993,9 +993,12 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev)
        for (i = 0; i < pinmux_maps_num; i++) {
                struct pinmux_map const *map = &pinmux_maps[i];
 
-               if (((map->ctrl_dev == dev) ||
-                    !strcmp(map->ctrl_dev_name, devname)) &&
-                   map->hog_on_boot) {
+               if (!map->hog_on_boot)
+                       continue;
+
+               if ((map->ctrl_dev == dev) ||
+                       (map->ctrl_dev_name &&
+                               !strcmp(map->ctrl_dev_name, devname))) {
                        /* OK time to hog! */
                        ret = pinmux_hog_map(pctldev, map);
                        if (ret)
@@ -1122,13 +1125,15 @@ static int pinmux_show(struct seq_file *s, void *what)
 
                seq_printf(s, "device: %s function: %s (%u),",
                           pinctrl_dev_get_name(pmx->pctldev),
-                          pmxops->get_function_name(pctldev, pmx->func_selector),
+                          pmxops->get_function_name(pctldev,
+                                  pmx->func_selector),
                           pmx->func_selector);
 
                seq_printf(s, " groups: [");
                list_for_each_entry(grp, &pmx->groups, node) {
                        seq_printf(s, " %s (%u)",
-                                  pctlops->get_group_name(pctldev, grp->group_selector),
+                                  pctlops->get_group_name(pctldev,
+                                          grp->group_selector),
                                   grp->group_selector);
                }
                seq_printf(s, " ]");
index 844500b3331bf8ee53ce5a3ae95f806c494e9372..97f52223fbc2968a58d6bf57aea5519cff1e6500 100644 (file)
@@ -12,7 +12,7 @@
  */
 #ifdef CONFIG_PINMUX
 
-int pinmux_check_ops(const struct pinmux_ops *ops);
+int pinmux_check_ops(struct pinctrl_dev *pctldev);
 void pinmux_init_device_debugfs(struct dentry *devroot,
                                struct pinctrl_dev *pctldev);
 void pinmux_init_debugfs(struct dentry *subsys_root);
@@ -21,7 +21,7 @@ void pinmux_unhog_maps(struct pinctrl_dev *pctldev);
 
 #else
 
-static inline int pinmux_check_ops(const struct pinmux_ops *ops)
+static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
 {
        return 0;
 }
index 42a7d603c870bb259a93a1630065de34d5c35a01..7481146a5b473c1cab6745a7d6ac1ae76e66257e 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/mutex.h>
 #include <asm/bios_ebda.h>
 
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
 static bool force;
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -83,19 +85,6 @@ static void __iomem *rtl_cmd_addr;
 static u8 rtl_cmd_type;
 static u8 rtl_cmd_width;
 
-#ifndef readq
-static inline __u64 readq(const volatile void __iomem *addr)
-{
-       const volatile u32 __iomem *p = addr;
-       u32 low, high;
-
-       low = readl(p);
-       high = readl(p + 1);
-
-       return low + ((u64)high << 32);
-}
-#endif
-
 static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
 {
        if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
index 809a3ae943c6997f65a20328f8fe2fb02690cd6c..88a98cff5a44a04e2d69771cc78ec7de3edbce82 100644 (file)
@@ -77,6 +77,8 @@
 #include <asm/processor.h>
 #include "intel_ips.h"
 
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
 #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
 
 /*
@@ -344,19 +346,6 @@ struct ips_driver {
 static bool
 ips_gpu_turbo_enabled(struct ips_driver *ips);
 
-#ifndef readq
-static inline __u64 readq(const volatile void __iomem *addr)
-{
-       const volatile u32 __iomem *p = addr;
-       u32 low, high;
-
-       low = readl(p);
-       high = readl(p + 1);
-
-       return low + ((u64)high << 32);
-}
-#endif
-
 /**
  * ips_cpu_busy - is CPU busy?
  * @ips: IPS driver struct
index 98bf5676318d4b7664870558b8f26eb35222fbe8..1ed6ea0bad6e621bcf1b9523606189e28ec708c8 100644 (file)
 
 #define BQ27500_REG_SOC                        0x2C
 #define BQ27500_REG_DCAP               0x3C /* Design capacity */
-#define BQ27500_FLAG_DSG               BIT(0) /* Discharging */
+#define BQ27500_FLAG_DSC               BIT(0)
 #define BQ27500_FLAG_SOCF              BIT(1) /* State-of-Charge threshold final */
 #define BQ27500_FLAG_SOC1              BIT(2) /* State-of-Charge threshold 1 */
-#define BQ27500_FLAG_CHG               BIT(8) /* Charging */
-#define BQ27500_FLAG_FC                        BIT(9) /* Fully charged */
+#define BQ27500_FLAG_FC                        BIT(9)
 
 #define BQ27000_RS                     20 /* Resistor sense */
 
@@ -312,7 +311,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
        struct bq27x00_reg_cache cache = {0, };
        bool is_bq27500 = di->chip == BQ27500;
 
-       cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
+       cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
        if (cache.flags >= 0) {
                if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
                        dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
@@ -401,14 +400,10 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
        if (di->chip == BQ27500) {
                if (di->cache.flags & BQ27500_FLAG_FC)
                        status = POWER_SUPPLY_STATUS_FULL;
-               else if (di->cache.flags & BQ27500_FLAG_DSG)
+               else if (di->cache.flags & BQ27500_FLAG_DSC)
                        status = POWER_SUPPLY_STATUS_DISCHARGING;
-               else if (di->cache.flags & BQ27500_FLAG_CHG)
-                       status = POWER_SUPPLY_STATUS_CHARGING;
-               else if (power_supply_am_i_supplied(&di->bat))
-                       status = POWER_SUPPLY_STATUS_NOT_CHARGING;
                else
-                       status = POWER_SUPPLY_STATUS_UNKNOWN;
+                       status = POWER_SUPPLY_STATUS_CHARGING;
        } else {
                if (di->cache.flags & BQ27000_FLAG_FC)
                        status = POWER_SUPPLY_STATUS_FULL;
index 0378d019efae4454395485571e273ce45c8f6abf..88fd9710bda212c22b59da04f970977e408ea6f2 100644 (file)
@@ -974,10 +974,11 @@ static int __devexit charger_manager_remove(struct platform_device *pdev)
        return 0;
 }
 
-const struct platform_device_id charger_manager_id[] = {
+static const struct platform_device_id charger_manager_id[] = {
        { "charger-manager", 0 },
        { },
 };
+MODULE_DEVICE_TABLE(platform, charger_manager_id);
 
 static int cm_suspend_prepare(struct device *dev)
 {
@@ -1069,4 +1070,3 @@ module_exit(charger_manager_cleanup);
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 MODULE_DESCRIPTION("Charger Manager");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("charger-manager");
index b15b575c070c5bd66e1164c93f7d58ecbc26b97a..c53dd1292f818bc595a54c863c63f362e28ad5aa 100644 (file)
@@ -464,6 +464,7 @@ static int __devexit lp8727_remove(struct i2c_client *cl)
 
 static const struct i2c_device_id lp8727_ids[] = {
        {"lp8727", 0},
+       { }
 };
 
 static struct i2c_driver lp8727_driver = {
index ca86f39a0fdc824fba463f0eb30157ce933bbe9c..e9a83f84adaf53771d94bd3b3761deb7cad2ca32 100644 (file)
@@ -2731,6 +2731,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
  * @dev: struct device for the regulator
  * @init_data: platform provided init data, passed through by driver
  * @driver_data: private regulator data
+ * @of_node: OpenFirmware node to parse for device tree bindings (may be
+ *           NULL).
  *
  * Called by regulator drivers to register a regulator.
  * Returns 0 on success.
index b06a2399587c0e08fec38c8c827da6859130840f..d0e1180ad961c115fa55ddc4e318b2fbf5e42b31 100644 (file)
@@ -150,7 +150,7 @@ static int max8649_enable_time(struct regulator_dev *rdev)
        if (ret != 0)
                return ret;
        val &= MAX8649_VOL_MASK;
-       voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */
+       voltage = max8649_list_voltage(rdev, (unsigned char)val); /* uV */
 
        /* get rate */
        ret = regmap_read(info->regmap, MAX8649_RAMP, &val);
index 80ecafef1bc38b217abe30f1aa0537ca64d9b3d4..62dcd0a432bb65832fc7bcf454b08587401ad293 100644 (file)
@@ -254,6 +254,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 
        return num;
 }
+EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
 
 struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
        struct platform_device *pdev, struct mc13xxx_regulator *regulators,
@@ -291,6 +292,7 @@ struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
 
        return data;
 }
+EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt);
 #endif
 
 MODULE_LICENSE("GPL v2");
index f1651eb6964807d9ae86c6ed88032199d5950199..679734d26a16961ef100f1731c66ba864f5057e3 100644 (file)
@@ -35,7 +35,7 @@ static void of_get_regulation_constraints(struct device_node *np,
        if (constraints->min_uV != constraints->max_uV)
                constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
        /* Only one voltage?  Then make sure it's set. */
-       if (constraints->min_uV == constraints->max_uV)
+       if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
                constraints->apply_uV = true;
 
        uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL);
index e19a4031f45e9b3ad3e1e677afa2dffd271bb4fc..3a125b835546e692e3a9c70cd25434fd54398f90 100644 (file)
@@ -774,7 +774,7 @@ config RTC_DRV_EP93XX
 
 config RTC_DRV_SA1100
        tristate "SA11x0/PXA2xx"
-       depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
+       depends on ARCH_SA1100 || ARCH_PXA
        help
          If you say Y here you will get access to the real time clock
          built into your SA11x0 or PXA2xx CPU.
index a3ad957507dc9ebce9a360c85330e067d5576f9f..ee3c122c05991e55394f7fca1e677caf4d5a3a0c 100644 (file)
@@ -307,8 +307,12 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                device_init_wakeup(&pdev->dev, 1);
 
        platform_set_drvdata(pdev, rtc);
-       rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
-       rtc->rtt += r->start;
+       rtc->rtt = ioremap(r->start, resource_size(r));
+       if (!rtc->rtt) {
+               dev_err(&pdev->dev, "failed to map registers, aborting.\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
 
        mr = rtt_readl(rtc, MR);
 
@@ -326,7 +330,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                                &at91_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc->rtcdev)) {
                ret = PTR_ERR(rtc->rtcdev);
-               goto fail;
+               goto fail_register;
        }
 
        /* register irq handler after we know what name we'll use */
@@ -351,6 +355,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
 
        return 0;
 
+fail_register:
+       iounmap(rtc->rtt);
 fail:
        platform_set_drvdata(pdev, NULL);
        kfree(rtc);
@@ -371,6 +377,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
 
        rtc_device_unregister(rtc->rtcdev);
 
+       iounmap(rtc->rtt);
        platform_set_drvdata(pdev, NULL);
        kfree(rtc);
        return 0;
index 4595d3e645a7358676b5409b8ced918f306e07c2..cb9a585312cc765c3e08a6d60720c3f669c8ba7b 100644 (file)
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
+#include <linux/string.h>
 #include <linux/pm.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/bitops.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_ARCH_PXA
+#include <mach/regs-rtc.h>
+#endif
+
 #define RTC_DEF_DIVIDER                (32768 - 1)
 #define RTC_DEF_TRIM           0
-#define RTC_FREQ               1024
-
-#define RCNR           0x00    /* RTC Count Register */
-#define RTAR           0x04    /* RTC Alarm Register */
-#define RTSR           0x08    /* RTC Status Register */
-#define RTTR           0x0c    /* RTC Timer Trim Register */
-
-#define RTSR_HZE       (1 << 3)        /* HZ interrupt enable */
-#define RTSR_ALE       (1 << 2)        /* RTC alarm interrupt enable */
-#define RTSR_HZ                (1 << 1)        /* HZ rising-edge detected */
-#define RTSR_AL                (1 << 0)        /* RTC alarm detected */
-
-#define rtc_readl(sa1100_rtc, reg)     \
-       readl_relaxed((sa1100_rtc)->base + (reg))
-#define rtc_writel(sa1100_rtc, reg, value)     \
-       writel_relaxed((value), (sa1100_rtc)->base + (reg))
-
-struct sa1100_rtc {
-       struct resource         *ress;
-       void __iomem            *base;
-       struct clk              *clk;
-       int                     irq_1Hz;
-       int                     irq_Alrm;
-       struct rtc_device       *rtc;
-       spinlock_t              lock;           /* Protects this structure */
-};
+
+static const unsigned long RTC_FREQ = 1024;
+static struct rtc_time rtc_alarm;
+static DEFINE_SPINLOCK(sa1100_rtc_lock);
+
+static inline int rtc_periodic_alarm(struct rtc_time *tm)
+{
+       return  (tm->tm_year == -1) ||
+               ((unsigned)tm->tm_mon >= 12) ||
+               ((unsigned)(tm->tm_mday - 1) >= 31) ||
+               ((unsigned)tm->tm_hour > 23) ||
+               ((unsigned)tm->tm_min > 59) ||
+               ((unsigned)tm->tm_sec > 59);
+}
+
 /*
  * Calculate the next alarm time given the requested alarm time mask
  * and the current time.
@@ -90,26 +82,46 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
        }
 }
 
+static int rtc_update_alarm(struct rtc_time *alrm)
+{
+       struct rtc_time alarm_tm, now_tm;
+       unsigned long now, time;
+       int ret;
+
+       do {
+               now = RCNR;
+               rtc_time_to_tm(now, &now_tm);
+               rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
+               ret = rtc_tm_to_time(&alarm_tm, &time);
+               if (ret != 0)
+                       break;
+
+               RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
+               RTAR = time;
+       } while (now != RCNR);
+
+       return ret;
+}
+
 static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 {
        struct platform_device *pdev = to_platform_device(dev_id);
-       struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
        unsigned int rtsr;
        unsigned long events = 0;
 
-       spin_lock(&sa1100_rtc->lock);
+       spin_lock(&sa1100_rtc_lock);
 
+       rtsr = RTSR;
        /* clear interrupt sources */
-       rtsr = rtc_readl(sa1100_rtc, RTSR);
-       rtc_writel(sa1100_rtc, RTSR, 0);
-
+       RTSR = 0;
        /* Fix for a nasty initialization problem the in SA11xx RTSR register.
         * See also the comments in sa1100_rtc_probe(). */
        if (rtsr & (RTSR_ALE | RTSR_HZE)) {
                /* This is the original code, before there was the if test
                 * above. This code does not clear interrupts that were not
                 * enabled. */
-               rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2));
+               RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
        } else {
                /* For some reason, it is possible to enter this routine
                 * without interruptions enabled, it has been tested with
@@ -118,13 +130,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
                 * This situation leads to an infinite "loop" of interrupt
                 * routine calling and as a result the processor seems to
                 * lock on its first call to open(). */
-               rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+               RTSR = RTSR_AL | RTSR_HZ;
        }
 
        /* clear alarm interrupt if it has occurred */
        if (rtsr & RTSR_AL)
                rtsr &= ~RTSR_ALE;
-       rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE));
+       RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
 
        /* update irq data & counter */
        if (rtsr & RTSR_AL)
@@ -132,100 +144,89 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
        if (rtsr & RTSR_HZ)
                events |= RTC_UF | RTC_IRQF;
 
-       rtc_update_irq(sa1100_rtc->rtc, 1, events);
+       rtc_update_irq(rtc, 1, events);
 
-       spin_unlock(&sa1100_rtc->lock);
+       if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
+               rtc_update_alarm(&rtc_alarm);
+
+       spin_unlock(&sa1100_rtc_lock);
 
        return IRQ_HANDLED;
 }
 
 static int sa1100_rtc_open(struct device *dev)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
        int ret;
+       struct platform_device *plat_dev = to_platform_device(dev);
+       struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
-       ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt,
-                               IRQF_DISABLED, "rtc 1Hz", dev);
+       ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
+               "rtc 1Hz", dev);
        if (ret) {
-               dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz);
+               dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
                goto fail_ui;
        }
-       ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt,
-                               IRQF_DISABLED, "rtc Alrm", dev);
+       ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
+               "rtc Alrm", dev);
        if (ret) {
-               dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm);
+               dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
                goto fail_ai;
        }
-       sa1100_rtc->rtc->max_user_freq = RTC_FREQ;
-       rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ);
+       rtc->max_user_freq = RTC_FREQ;
+       rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
 
        return 0;
 
  fail_ai:
-       free_irq(sa1100_rtc->irq_1Hz, dev);
+       free_irq(IRQ_RTC1Hz, dev);
  fail_ui:
        return ret;
 }
 
 static void sa1100_rtc_release(struct device *dev)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
-       spin_lock_irq(&sa1100_rtc->lock);
-       rtc_writel(sa1100_rtc, RTSR, 0);
-       spin_unlock_irq(&sa1100_rtc->lock);
+       spin_lock_irq(&sa1100_rtc_lock);
+       RTSR = 0;
+       spin_unlock_irq(&sa1100_rtc_lock);
 
-       free_irq(sa1100_rtc->irq_Alrm, dev);
-       free_irq(sa1100_rtc->irq_1Hz, dev);
+       free_irq(IRQ_RTCAlrm, dev);
+       free_irq(IRQ_RTC1Hz, dev);
 }
 
 static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-       unsigned int rtsr;
-
-       spin_lock_irq(&sa1100_rtc->lock);
-
-       rtsr = rtc_readl(sa1100_rtc, RTSR);
+       spin_lock_irq(&sa1100_rtc_lock);
        if (enabled)
-               rtsr |= RTSR_ALE;
+               RTSR |= RTSR_ALE;
        else
-               rtsr &= ~RTSR_ALE;
-       rtc_writel(sa1100_rtc, RTSR, rtsr);
-
-       spin_unlock_irq(&sa1100_rtc->lock);
+               RTSR &= ~RTSR_ALE;
+       spin_unlock_irq(&sa1100_rtc_lock);
        return 0;
 }
 
 static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
-       rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm);
+       rtc_time_to_tm(RCNR, tm);
        return 0;
 }
 
 static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
        unsigned long time;
        int ret;
 
        ret = rtc_tm_to_time(tm, &time);
        if (ret == 0)
-               rtc_writel(sa1100_rtc, RCNR, time);
+               RCNR = time;
        return ret;
 }
 
 static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-       unsigned long time;
-       unsigned int rtsr;
+       u32     rtsr;
 
-       time = rtc_readl(sa1100_rtc, RCNR);
-       rtc_time_to_tm(time, &alrm->time);
-       rtsr = rtc_readl(sa1100_rtc, RTSR);
+       memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
+       rtsr = RTSR;
        alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
        alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
        return 0;
@@ -233,39 +234,26 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-       struct rtc_time now_tm, alarm_tm;
-       unsigned long time, alarm;
-       unsigned int rtsr;
-
-       spin_lock_irq(&sa1100_rtc->lock);
-
-       time = rtc_readl(sa1100_rtc, RCNR);
-       rtc_time_to_tm(time, &now_tm);
-       rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
-       rtc_tm_to_time(&alarm_tm, &alarm);
-       rtc_writel(sa1100_rtc, RTAR, alarm);
-
-       rtsr = rtc_readl(sa1100_rtc, RTSR);
-       if (alrm->enabled)
-               rtsr |= RTSR_ALE;
-       else
-               rtsr &= ~RTSR_ALE;
-       rtc_writel(sa1100_rtc, RTSR, rtsr);
+       int ret;
 
-       spin_unlock_irq(&sa1100_rtc->lock);
+       spin_lock_irq(&sa1100_rtc_lock);
+       ret = rtc_update_alarm(&alrm->time);
+       if (ret == 0) {
+               if (alrm->enabled)
+                       RTSR |= RTSR_ALE;
+               else
+                       RTSR &= ~RTSR_ALE;
+       }
+       spin_unlock_irq(&sa1100_rtc_lock);
 
-       return 0;
+       return ret;
 }
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
+       seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
+       seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
 
-       seq_printf(seq, "trim/divider\t\t: 0x%08x\n",
-                       rtc_readl(sa1100_rtc, RTTR));
-       seq_printf(seq, "RTSR\t\t\t: 0x%08x\n",
-                       rtc_readl(sa1100_rtc, RTSR));
        return 0;
 }
 
@@ -282,51 +270,7 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
 
 static int sa1100_rtc_probe(struct platform_device *pdev)
 {
-       struct sa1100_rtc *sa1100_rtc;
-       unsigned int rttr;
-       int ret;
-
-       sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
-       if (!sa1100_rtc)
-               return -ENOMEM;
-
-       spin_lock_init(&sa1100_rtc->lock);
-       platform_set_drvdata(pdev, sa1100_rtc);
-
-       ret = -ENXIO;
-       sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!sa1100_rtc->ress) {
-               dev_err(&pdev->dev, "No I/O memory resource defined\n");
-               goto err_ress;
-       }
-
-       sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0);
-       if (sa1100_rtc->irq_1Hz < 0) {
-               dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n");
-               goto err_ress;
-       }
-       sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1);
-       if (sa1100_rtc->irq_Alrm < 0) {
-               dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
-               goto err_ress;
-       }
-
-       ret = -ENOMEM;
-       sa1100_rtc->base = ioremap(sa1100_rtc->ress->start,
-                               resource_size(sa1100_rtc->ress));
-       if (!sa1100_rtc->base) {
-               dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n");
-               goto err_map;
-       }
-
-       sa1100_rtc->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(sa1100_rtc->clk)) {
-               dev_err(&pdev->dev, "failed to find rtc clock source\n");
-               ret = PTR_ERR(sa1100_rtc->clk);
-               goto err_clk;
-       }
-       clk_prepare(sa1100_rtc->clk);
-       clk_enable(sa1100_rtc->clk);
+       struct rtc_device *rtc;
 
        /*
         * According to the manual we should be able to let RTTR be zero
@@ -335,24 +279,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
         * If the clock divider is uninitialized then reset it to the
         * default value to get the 1Hz clock.
         */
-       if (rtc_readl(sa1100_rtc, RTTR) == 0) {
-               rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-               rtc_writel(sa1100_rtc, RTTR, rttr);
-               dev_warn(&pdev->dev, "warning: initializing default clock"
-                        " divider/trim value\n");
+       if (RTTR == 0) {
+               RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+               dev_warn(&pdev->dev, "warning: "
+                       "initializing default clock divider/trim value\n");
                /* The current RTC value probably doesn't make sense either */
-               rtc_writel(sa1100_rtc, RCNR, 0);
+               RCNR = 0;
        }
 
        device_init_wakeup(&pdev->dev, 1);
 
-       sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
-                                               &sa1100_rtc_ops, THIS_MODULE);
-       if (IS_ERR(sa1100_rtc->rtc)) {
-               dev_err(&pdev->dev, "Failed to register RTC device -> %d\n",
-                       ret);
-               goto err_rtc_reg;
-       }
+       rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
+               THIS_MODULE);
+
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
+
+       platform_set_drvdata(pdev, rtc);
+
        /* Fix for a nasty initialization problem the in SA11xx RTSR register.
         * See also the comments in sa1100_rtc_interrupt().
         *
@@ -375,46 +319,33 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
         *
         * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
         * the corresponding bits in RTSR. */
-       rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+       RTSR = RTSR_AL | RTSR_HZ;
 
        return 0;
-
-err_rtc_reg:
-err_clk:
-       iounmap(sa1100_rtc->base);
-err_ress:
-err_map:
-       kfree(sa1100_rtc);
-       return ret;
 }
 
 static int sa1100_rtc_remove(struct platform_device *pdev)
 {
-       struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+       if (rtc)
+               rtc_device_unregister(rtc);
 
-       rtc_device_unregister(sa1100_rtc->rtc);
-       clk_disable(sa1100_rtc->clk);
-       clk_unprepare(sa1100_rtc->clk);
-       iounmap(sa1100_rtc->base);
        return 0;
 }
 
 #ifdef CONFIG_PM
 static int sa1100_rtc_suspend(struct device *dev)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
        if (device_may_wakeup(dev))
-               enable_irq_wake(sa1100_rtc->irq_Alrm);
+               enable_irq_wake(IRQ_RTCAlrm);
        return 0;
 }
 
 static int sa1100_rtc_resume(struct device *dev)
 {
-       struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
        if (device_may_wakeup(dev))
-               disable_irq_wake(sa1100_rtc->irq_Alrm);
+               disable_irq_wake(IRQ_RTCAlrm);
        return 0;
 }
 
index eef27a197c00f9d38bb529660e1cb6d3e80f47a3..110137e7ec81caae83eee0d914f61b73e38c746a 100644 (file)
@@ -3261,6 +3261,12 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
                        device->path_data.tbvpm |= eventlpm;
                        dasd_schedule_device_bh(device);
                }
+               if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+                       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                                     "Pathgroup re-established\n");
+                       if (device->discipline->kick_validate)
+                               device->discipline->kick_validate(device);
+               }
        }
        dasd_put_device(device);
 }
index 553b3c5abb0abf37faa0507f28512e1d3d7ac363..b3beed5434e43d8064cbf48659a4ff9426ea3c36 100644 (file)
@@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
        unsigned long flags;
        struct alias_server *server, *newserver;
        struct alias_lcu *lcu, *newlcu;
-       int is_lcu_known;
        struct dasd_uid uid;
 
        private = (struct dasd_eckd_private *) device->private;
 
        device->discipline->get_uid(device, &uid);
        spin_lock_irqsave(&aliastree.lock, flags);
-       is_lcu_known = 1;
        server = _find_server(&uid);
        if (!server) {
                spin_unlock_irqrestore(&aliastree.lock, flags);
@@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
                if (!server) {
                        list_add(&newserver->server, &aliastree.serverlist);
                        server = newserver;
-                       is_lcu_known = 0;
                } else {
                        /* someone was faster */
                        _free_server(newserver);
@@ -226,12 +223,10 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
                if (!lcu) {
                        list_add(&newlcu->lcu, &server->lculist);
                        lcu = newlcu;
-                       is_lcu_known = 0;
                } else {
                        /* someone was faster */
                        _free_lcu(newlcu);
                }
-               is_lcu_known = 0;
        }
        spin_lock(&lcu->lock);
        list_add(&device->alias_list, &lcu->inactive_devices);
@@ -239,64 +234,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
        spin_unlock(&lcu->lock);
        spin_unlock_irqrestore(&aliastree.lock, flags);
 
-       return is_lcu_known;
-}
-
-/*
- * The first device to be registered on an LCU will have to do
- * some additional setup steps to configure that LCU on the
- * storage server. All further devices should wait with their
- * initialization until the first device is done.
- * To synchronize this work, the first device will call
- * dasd_alias_lcu_setup_complete when it is done, and all
- * other devices will wait for it with dasd_alias_wait_for_lcu_setup.
- */
-void dasd_alias_lcu_setup_complete(struct dasd_device *device)
-{
-       unsigned long flags;
-       struct alias_server *server;
-       struct alias_lcu *lcu;
-       struct dasd_uid uid;
-
-       device->discipline->get_uid(device, &uid);
-       lcu = NULL;
-       spin_lock_irqsave(&aliastree.lock, flags);
-       server = _find_server(&uid);
-       if (server)
-               lcu = _find_lcu(server, &uid);
-       spin_unlock_irqrestore(&aliastree.lock, flags);
-       if (!lcu) {
-               DBF_EVENT_DEVID(DBF_ERR, device->cdev,
-                               "could not find lcu for %04x %02x",
-                               uid.ssid, uid.real_unit_addr);
-               WARN_ON(1);
-               return;
-       }
-       complete_all(&lcu->lcu_setup);
-}
-
-void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
-{
-       unsigned long flags;
-       struct alias_server *server;
-       struct alias_lcu *lcu;
-       struct dasd_uid uid;
-
-       device->discipline->get_uid(device, &uid);
-       lcu = NULL;
-       spin_lock_irqsave(&aliastree.lock, flags);
-       server = _find_server(&uid);
-       if (server)
-               lcu = _find_lcu(server, &uid);
-       spin_unlock_irqrestore(&aliastree.lock, flags);
-       if (!lcu) {
-               DBF_EVENT_DEVID(DBF_ERR, device->cdev,
-                               "could not find lcu for %04x %02x",
-                               uid.ssid, uid.real_unit_addr);
-               WARN_ON(1);
-               return;
-       }
-       wait_for_completion(&lcu->lcu_setup);
+       return 0;
 }
 
 /*
index bbcd5e9206ee27dff5c85fc78ef09353135e3656..70880be260151b62dce8ff5724a47bf8a28be7ac 100644 (file)
@@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
        struct dasd_eckd_private *private;
        int enable_pav;
 
+       private = (struct dasd_eckd_private *) device->private;
+       if (private->uid.type == UA_BASE_PAV_ALIAS ||
+           private->uid.type == UA_HYPER_PAV_ALIAS)
+               return;
        if (dasd_nopav || MACHINE_IS_VM)
                enable_pav = 0;
        else
@@ -1542,11 +1546,28 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
 
        /* may be requested feature is not available on server,
         * therefore just report error and go ahead */
-       private = (struct dasd_eckd_private *) device->private;
        DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
                        "returned rc=%d", private->uid.ssid, rc);
 }
 
+/*
+ * worker to do a validate server in case of a lost pathgroup
+ */
+static void dasd_eckd_do_validate_server(struct work_struct *work)
+{
+       struct dasd_device *device = container_of(work, struct dasd_device,
+                                                 kick_validate);
+       dasd_eckd_validate_server(device);
+       dasd_put_device(device);
+}
+
+static void dasd_eckd_kick_validate_server(struct dasd_device *device)
+{
+       dasd_get_device(device);
+       /* queue call to do_validate_server to the kernel event daemon. */
+       schedule_work(&device->kick_validate);
+}
+
 static u32 get_fcx_max_data(struct dasd_device *device)
 {
 #if defined(CONFIG_64BIT)
@@ -1588,10 +1609,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        struct dasd_eckd_private *private;
        struct dasd_block *block;
        struct dasd_uid temp_uid;
-       int is_known, rc, i;
+       int rc, i;
        int readonly;
        unsigned long value;
 
+       /* setup work queue for validate server*/
+       INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server);
+
        if (!ccw_device_is_pathgroup(device->cdev)) {
                dev_warn(&device->cdev->dev,
                         "A channel path group could not be established\n");
@@ -1651,22 +1675,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                block->base = device;
        }
 
-       /* register lcu with alias handling, enable PAV if this is a new lcu */
-       is_known = dasd_alias_make_device_known_to_lcu(device);
-       if (is_known < 0) {
-               rc = is_known;
+       /* register lcu with alias handling, enable PAV */
+       rc = dasd_alias_make_device_known_to_lcu(device);
+       if (rc)
                goto out_err2;
-       }
-       /*
-        * dasd_eckd_validate_server is done on the first device that
-        * is found for an LCU. All later other devices have to wait
-        * for it, so they will read the correct feature codes.
-        */
-       if (!is_known) {
-               dasd_eckd_validate_server(device);
-               dasd_alias_lcu_setup_complete(device);
-       } else
-               dasd_alias_wait_for_lcu_setup(device);
+
+       dasd_eckd_validate_server(device);
 
        /* device may report different configuration data after LCU setup */
        rc = dasd_eckd_read_conf(device);
@@ -4098,7 +4112,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
        struct dasd_eckd_characteristics temp_rdc_data;
-       int is_known, rc;
+       int rc;
        struct dasd_uid temp_uid;
        unsigned long flags;
 
@@ -4121,14 +4135,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
                goto out_err;
 
        /* register lcu with alias handling, enable PAV if this is a new lcu */
-       is_known = dasd_alias_make_device_known_to_lcu(device);
-       if (is_known < 0)
-               return is_known;
-       if (!is_known) {
-               dasd_eckd_validate_server(device);
-               dasd_alias_lcu_setup_complete(device);
-       } else
-               dasd_alias_wait_for_lcu_setup(device);
+       rc = dasd_alias_make_device_known_to_lcu(device);
+       if (rc)
+               return rc;
+       dasd_eckd_validate_server(device);
 
        /* RE-Read Configuration Data */
        rc = dasd_eckd_read_conf(device);
@@ -4270,6 +4280,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .restore = dasd_eckd_restore_device,
        .reload = dasd_eckd_reload_device,
        .get_uid = dasd_eckd_get_uid,
+       .kick_validate = dasd_eckd_kick_validate_server,
 };
 
 static int __init
index afe8c33422edae5f6e90ae8afa597f54f0346959..33a6743ddc558c11e9b07e09e230efb40e80da28 100644 (file)
@@ -355,6 +355,7 @@ struct dasd_discipline {
        int (*reload) (struct dasd_device *);
 
        int (*get_uid) (struct dasd_device *, struct dasd_uid *);
+       void (*kick_validate) (struct dasd_device *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -455,6 +456,7 @@ struct dasd_device {
        struct work_struct kick_work;
        struct work_struct restore_device;
        struct work_struct reload_device;
+       struct work_struct kick_validate;
        struct timer_list timer;
 
        debug_info_t *debug_area;
index 934458ad55e51782c7b595b48c5f3088393b8495..e71a50d4b2217b22fb262338f31aa1fe98931349 100644 (file)
@@ -87,6 +87,7 @@ struct raw3215_info {
        struct tty_struct *tty;       /* pointer to tty structure if present */
        struct raw3215_req *queued_read; /* pointer to queued read requests */
        struct raw3215_req *queued_write;/* pointer to queued write requests */
+       struct tasklet_struct tlet;   /* tasklet to invoke tty_wakeup */
        wait_queue_head_t empty_wait; /* wait queue for flushing */
        struct timer_list timer;      /* timer for delayed output */
        int line_pos;                 /* position on the line (for tabs) */
@@ -333,20 +334,24 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
        }
 }
 
+/*
+ * Call tty_wakeup from tasklet context
+ */
+static void raw3215_wakeup(unsigned long data)
+{
+       struct raw3215_info *raw = (struct raw3215_info *) data;
+       tty_wakeup(raw->tty);
+}
+
 /*
  * Try to start the next IO and wake up processes waiting on the tty.
  */
 static void raw3215_next_io(struct raw3215_info *raw)
 {
-       struct tty_struct *tty;
-
        raw3215_mk_write_req(raw);
        raw3215_try_io(raw);
-       tty = raw->tty;
-       if (tty != NULL &&
-           RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
-               tty_wakeup(tty);
-       }
+       if (raw->tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
+               tasklet_schedule(&raw->tlet);
 }
 
 /*
@@ -682,6 +687,7 @@ static int raw3215_probe (struct ccw_device *cdev)
                return -ENOMEM;
        }
        init_waitqueue_head(&raw->empty_wait);
+       tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
 
        dev_set_drvdata(&cdev->dev, raw);
        cdev->handler = raw3215_irq;
@@ -901,6 +907,7 @@ static int __init con3215_init(void)
 
        raw->flags |= RAW3215_FIXED;
        init_waitqueue_head(&raw->empty_wait);
+       tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
 
        /* Request the console irq */
        if (raw3215_startup(raw) != 0) {
@@ -966,6 +973,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp)
        tty->closing = 1;
        /* Shutdown the terminal */
        raw3215_shutdown(raw);
+       tasklet_kill(&raw->tlet);
        tty->closing = 0;
        raw->tty = NULL;
 }
index 06ea3bcfdd2a3064f462592bbed67ca4b24e9c7e..16570aa84aac0e1e420a541d7224ecfd0e567bbc 100644 (file)
@@ -830,16 +830,11 @@ config SCSI_ISCI
        tristate "Intel(R) C600 Series Chipset SAS Controller"
        depends on PCI && SCSI
        depends on X86
-       # (temporary): known alpha quality driver
-       depends on EXPERIMENTAL
        select SCSI_SAS_LIBSAS
-       select SCSI_SAS_HOST_SMP
        ---help---
          This driver supports the 6Gb/s SAS capabilities of the storage
          control unit found in the Intel(R) C600 series chipset.
 
-         The experimental tag will be removed after the driver exits alpha
-
 config SCSI_GENERIC_NCR5380
        tristate "Generic NCR5380/53c400 SCSI PIO support"
        depends on ISA && SCSI
index 78963be2c4fb308f09df6f38b3cf5097b3bb5f53..cb07c628b2f1856a3a26dadba052e2587edd3ae7 100644 (file)
@@ -673,12 +673,7 @@ struct bfa_itnim_iostats_s {
        u32     tm_iocdowns;            /*  TM cleaned-up due to IOC down   */
        u32     tm_cleanups;            /*  TM cleanup requests */
        u32     tm_cleanup_comps;       /*  TM cleanup completions      */
-       u32     lm_lun_across_sg;       /*  LM lun is across sg data buf */
-       u32     lm_lun_not_sup;         /*  LM lun not supported */
-       u32     lm_rpl_data_changed;    /*  LM report-lun data changed */
-       u32     lm_wire_residue_changed; /* LM report-lun rsp residue changed */
-       u32     lm_small_buf_addresidue; /* LM buf smaller than reported cnt */
-       u32     lm_lun_not_rdy;         /* LM lun not ready */
+       u32     rsvd[6];
 };
 
 /* Modify char* port_stt[] in bfal_port.c if a new state was added */
index 50b6a1c86195ac6d6c394295fcdd8150dbd43852..8d0b88f67a382e3582c40382d7dfe3892a19f3c8 100644 (file)
@@ -56,161 +56,6 @@ struct scsi_cdb_s {
 
 #define SCSI_MAX_ALLOC_LEN      0xFF    /* maximum allocarion length */
 
-#define SCSI_SENSE_CUR_ERR     0x70
-#define SCSI_SENSE_DEF_ERR     0x71
-
-/*
- * SCSI additional sense codes
- */
-#define SCSI_ASC_LUN_NOT_READY         0x04
-#define SCSI_ASC_LUN_NOT_SUPPORTED     0x25
-#define SCSI_ASC_TOCC                  0x3F
-
-/*
- * SCSI additional sense code qualifiers
- */
-#define SCSI_ASCQ_MAN_INTR_REQ         0x03    /* manual intervention req */
-#define SCSI_ASCQ_RL_DATA_CHANGED      0x0E    /* report luns data changed */
-
-/*
- * Methods of reporting informational exceptions
- */
-#define SCSI_MP_IEC_UNIT_ATTN          0x2     /* generate unit attention */
-
-struct scsi_report_luns_data_s {
-       u32             lun_list_length;        /* length of LUN list length */
-       u32             reserved;
-       struct scsi_lun lun[1];                 /* first LUN in lun list */
-};
-
-struct scsi_inquiry_vendor_s {
-       u8      vendor_id[8];
-};
-
-struct scsi_inquiry_prodid_s {
-       u8      product_id[16];
-};
-
-struct scsi_inquiry_prodrev_s {
-       u8      product_rev[4];
-};
-
-struct scsi_inquiry_data_s {
-#ifdef __BIG_ENDIAN
-       u8              peripheral_qual:3;      /* peripheral qualifier */
-       u8              device_type:5;          /* peripheral device type */
-       u8              rmb:1;                  /* removable medium bit */
-       u8              device_type_mod:7;      /* device type modifier */
-       u8              version;
-       u8              aenc:1;         /* async evt notification capability */
-       u8              trm_iop:1;      /* terminate I/O process */
-       u8              norm_aca:1;     /* normal ACA supported */
-       u8              hi_support:1;   /* SCSI-3: supports REPORT LUNS */
-       u8              rsp_data_format:4;
-       u8              additional_len;
-       u8              sccs:1;
-       u8              reserved1:7;
-       u8              reserved2:1;
-       u8              enc_serv:1;     /* enclosure service component */
-       u8              reserved3:1;
-       u8              multi_port:1;   /* multi-port device */
-       u8              m_chngr:1;      /* device in medium transport element */
-       u8              ack_req_q:1;    /* SIP specific bit */
-       u8              addr32:1;       /* SIP specific bit */
-       u8              addr16:1;       /* SIP specific bit */
-       u8              rel_adr:1;      /* relative address */
-       u8              w_bus32:1;
-       u8              w_bus16:1;
-       u8              synchronous:1;
-       u8              linked_commands:1;
-       u8              trans_dis:1;
-       u8              cmd_queue:1;    /* command queueing supported */
-       u8              soft_reset:1;   /* soft reset alternative (VS) */
-#else
-       u8              device_type:5;  /* peripheral device type */
-       u8              peripheral_qual:3; /* peripheral qualifier */
-       u8              device_type_mod:7; /* device type modifier */
-       u8              rmb:1;          /* removable medium bit */
-       u8              version;
-       u8              rsp_data_format:4;
-       u8              hi_support:1;   /* SCSI-3: supports REPORT LUNS */
-       u8              norm_aca:1;     /* normal ACA supported */
-       u8              terminate_iop:1;/* terminate I/O process */
-       u8              aenc:1;         /* async evt notification capability */
-       u8              additional_len;
-       u8              reserved1:7;
-       u8              sccs:1;
-       u8              addr16:1;       /* SIP specific bit */
-       u8              addr32:1;       /* SIP specific bit */
-       u8              ack_req_q:1;    /* SIP specific bit */
-       u8              m_chngr:1;      /* device in medium transport element */
-       u8              multi_port:1;   /* multi-port device */
-       u8              reserved3:1;    /* TBD - Vendor Specific */
-       u8              enc_serv:1;     /* enclosure service component */
-       u8              reserved2:1;
-       u8              soft_seset:1;   /* soft reset alternative (VS) */
-       u8              cmd_queue:1;    /* command queueing supported */
-       u8              trans_dis:1;
-       u8              linked_commands:1;
-       u8              synchronous:1;
-       u8              w_bus16:1;
-       u8              w_bus32:1;
-       u8              rel_adr:1;      /* relative address */
-#endif
-       struct scsi_inquiry_vendor_s    vendor_id;
-       struct scsi_inquiry_prodid_s    product_id;
-       struct scsi_inquiry_prodrev_s   product_rev;
-       u8              vendor_specific[20];
-       u8              reserved4[40];
-};
-
-/*
- *     SCSI sense data format
- */
-struct scsi_sense_s {
-#ifdef __BIG_ENDIAN
-       u8              valid:1;
-       u8              rsp_code:7;
-#else
-       u8              rsp_code:7;
-       u8              valid:1;
-#endif
-       u8              seg_num;
-#ifdef __BIG_ENDIAN
-       u8              file_mark:1;
-       u8              eom:1;          /* end of media */
-       u8              ili:1;          /* incorrect length indicator */
-       u8              reserved:1;
-       u8              sense_key:4;
-#else
-       u8              sense_key:4;
-       u8              reserved:1;
-       u8              ili:1;          /* incorrect length indicator */
-       u8              eom:1;          /* end of media */
-       u8              file_mark:1;
-#endif
-       u8              information[4]; /* device-type or cmd specific info */
-       u8              add_sense_length; /* additional sense length */
-       u8              command_info[4];/* command specific information */
-       u8              asc;            /* additional sense code */
-       u8              ascq;           /* additional sense code qualifier */
-       u8              fru_code;       /* field replaceable unit code */
-#ifdef __BIG_ENDIAN
-       u8              sksv:1;         /* sense key specific valid */
-       u8              c_d:1;          /* command/data bit */
-       u8              res1:2;
-       u8              bpv:1;          /* bit pointer valid */
-       u8              bpointer:3;     /* bit pointer */
-#else
-       u8              bpointer:3;     /* bit pointer */
-       u8              bpv:1;          /* bit pointer valid */
-       u8              res1:2;
-       u8              c_d:1;          /* command/data bit */
-       u8              sksv:1;         /* sense key specific valid */
-#endif
-       u8              fpointer[2];    /* field pointer */
-};
-
 /*
  * Fibre Channel Header Structure (FCHS) definition
  */
index e07bd4745d8ba5b968ded24e81785096c1535b84..f0f80e282e39cc023a72dacef7ee23b09c06a79e 100644 (file)
@@ -24,8 +24,6 @@ BFA_TRC_FILE(HAL, FCPIM);
  *  BFA ITNIM Related definitions
  */
 static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim);
-static bfa_boolean_t bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim);
 static void bfa_ioim_lm_init(struct bfa_s *bfa);
 
 #define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \
@@ -60,14 +58,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa);
        }                                                               \
 } while (0)
 
-#define bfa_ioim_rp_wwn(__ioim)                                                \
-       (((struct bfa_fcs_rport_s *)                                    \
-        (__ioim)->itnim->rport->rport_drv)->pwwn)
-
-#define bfa_ioim_lp_wwn(__ioim)                                                \
-       ((BFA_LPS_FROM_TAG(BFA_LPS_MOD((__ioim)->bfa),                  \
-       (__ioim)->itnim->rport->rport_info.lp_tag))->pwwn)              \
-
 #define bfa_itnim_sler_cb(__itnim) do {                                        \
        if ((__itnim)->bfa->fcs)                                        \
                bfa_cb_itnim_sler((__itnim)->ditn);      \
@@ -77,13 +67,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa);
        }                                                               \
 } while (0)
 
-enum bfa_ioim_lm_status {
-       BFA_IOIM_LM_PRESENT = 1,
-       BFA_IOIM_LM_LUN_NOT_SUP = 2,
-       BFA_IOIM_LM_RPL_DATA_CHANGED = 3,
-       BFA_IOIM_LM_LUN_NOT_RDY = 4,
-};
-
 enum bfa_ioim_lm_ua_status {
        BFA_IOIM_LM_UA_RESET = 0,
        BFA_IOIM_LM_UA_SET = 1,
@@ -145,9 +128,6 @@ enum bfa_ioim_event {
        BFA_IOIM_SM_TMDONE      = 16,   /*  IO cleanup from tskim */
        BFA_IOIM_SM_HWFAIL      = 17,   /*  IOC h/w failure event */
        BFA_IOIM_SM_IOTOV       = 18,   /*  ITN offline TOV */
-       BFA_IOIM_SM_LM_LUN_NOT_SUP = 19,/*  lunmask lun not supported */
-       BFA_IOIM_SM_LM_RPL_DC = 20,     /*  lunmask report-lun data changed */
-       BFA_IOIM_SM_LM_LUN_NOT_RDY = 21,/*  lunmask lun not ready */
 };
 
 
@@ -245,9 +225,6 @@ static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
 static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
 static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
 static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
-static void __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete);
 
 /*
  * forward declaration of BFA IO state machine
@@ -445,12 +422,6 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
        bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
        bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
        bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
-       bfa_fcpim_add_iostats(lstats, rstats, lm_lun_across_sg);
-       bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_sup);
-       bfa_fcpim_add_iostats(lstats, rstats, lm_rpl_data_changed);
-       bfa_fcpim_add_iostats(lstats, rstats, lm_wire_residue_changed);
-       bfa_fcpim_add_iostats(lstats, rstats, lm_small_buf_addresidue);
-       bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_rdy);
 }
 
 bfa_status_t
@@ -1580,27 +1551,6 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
                        __bfa_cb_ioim_abort, ioim);
                break;
 
-       case BFA_IOIM_SM_LM_LUN_NOT_SUP:
-               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-               bfa_ioim_move_to_comp_q(ioim);
-               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-                       __bfa_cb_ioim_lm_lun_not_sup, ioim);
-               break;
-
-       case BFA_IOIM_SM_LM_RPL_DC:
-               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-               bfa_ioim_move_to_comp_q(ioim);
-               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-                               __bfa_cb_ioim_lm_rpl_dc, ioim);
-               break;
-
-       case BFA_IOIM_SM_LM_LUN_NOT_RDY:
-               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-               bfa_ioim_move_to_comp_q(ioim);
-               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-                       __bfa_cb_ioim_lm_lun_not_rdy, ioim);
-               break;
-
        default:
                bfa_sm_fault(ioim->bfa, event);
        }
@@ -2160,243 +2110,6 @@ bfa_ioim_lm_init(struct bfa_s *bfa)
        }
 }
 
-/*
- * Validate LUN for LUN masking
- */
-static enum bfa_ioim_lm_status
-bfa_ioim_lm_check(struct bfa_ioim_s *ioim, struct bfa_lps_s *lps,
-               struct bfa_rport_s *rp, struct scsi_lun lun)
-{
-       u8 i;
-       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
-       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
-       struct scsi_cdb_s *cdb = (struct scsi_cdb_s *)cmnd->cmnd;
-
-       if ((cdb->scsi_cdb[0] == REPORT_LUNS) &&
-           (scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
-               ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
-               return BFA_IOIM_LM_PRESENT;
-       }
-
-       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
-
-               if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
-                       continue;
-
-               if ((scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) ==
-                   scsilun_to_int((struct scsi_lun *)&lun))
-                   && (rp->rport_tag == lun_list[i].rp_tag)
-                   && ((u8)ioim->itnim->rport->rport_info.lp_tag ==
-                                               lun_list[i].lp_tag)) {
-                       bfa_trc(ioim->bfa, lun_list[i].rp_tag);
-                       bfa_trc(ioim->bfa, lun_list[i].lp_tag);
-                       bfa_trc(ioim->bfa, scsilun_to_int(
-                               (struct scsi_lun *)&lun_list[i].lun));
-
-                       if ((lun_list[i].ua == BFA_IOIM_LM_UA_SET) &&
-                           ((cdb->scsi_cdb[0] != INQUIRY) ||
-                           (cdb->scsi_cdb[0] != REPORT_LUNS))) {
-                               lun_list[i].ua = BFA_IOIM_LM_UA_RESET;
-                               return BFA_IOIM_LM_RPL_DATA_CHANGED;
-                       }
-
-                       if (cdb->scsi_cdb[0] == REPORT_LUNS)
-                               ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
-
-                       return BFA_IOIM_LM_PRESENT;
-               }
-       }
-
-       if ((cdb->scsi_cdb[0] == INQUIRY) &&
-           (scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
-               ioim->proc_rsp_data = bfa_ioim_lm_proc_inq_data;
-               return BFA_IOIM_LM_PRESENT;
-       }
-
-       if (cdb->scsi_cdb[0] == TEST_UNIT_READY)
-               return BFA_IOIM_LM_LUN_NOT_RDY;
-
-       return BFA_IOIM_LM_LUN_NOT_SUP;
-}
-
-static bfa_boolean_t
-bfa_ioim_lm_proc_rsp_data_dummy(struct bfa_ioim_s *ioim)
-{
-       return BFA_TRUE;
-}
-
-static void
-bfa_ioim_lm_fetch_lun(struct bfa_ioim_s *ioim, u8 *rl_data, int offset,
-               int buf_lun_cnt)
-{
-       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
-       struct scsi_lun *lun_data = (struct scsi_lun *)(rl_data + offset);
-       struct scsi_lun lun;
-       int i, j;
-
-       bfa_trc(ioim->bfa, buf_lun_cnt);
-       for (j = 0; j < buf_lun_cnt; j++) {
-               lun = *((struct scsi_lun *)(lun_data + j));
-               for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
-                       if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
-                               continue;
-                       if ((lun_list[i].rp_wwn == bfa_ioim_rp_wwn(ioim)) &&
-                           (lun_list[i].lp_wwn == bfa_ioim_lp_wwn(ioim)) &&
-                           (scsilun_to_int((struct scsi_lun *)&lun_list[i].lun)
-                               == scsilun_to_int((struct scsi_lun *)&lun))) {
-                               lun_list[i].state = BFA_IOIM_LUN_MASK_FETCHED;
-                               break;
-                       }
-               } /* next lun in mask DB */
-       } /* next lun in buf */
-}
-
-static int
-bfa_ioim_lm_update_lun_sg(struct bfa_ioim_s *ioim, u32 *pgdlen,
-               struct scsi_report_luns_data_s *rl)
-{
-       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
-       struct scatterlist *sg = scsi_sglist(cmnd);
-       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
-       struct scsi_lun *prev_rl_data = NULL, *base_rl_data;
-       int i, j, sgeid, lun_fetched_cnt = 0, prev_sg_len = 0, base_count;
-       int lun_across_sg_bytes, bytes_from_next_buf;
-       u64     last_lun, temp_last_lun;
-
-       /* fetch luns from the first sg element */
-       bfa_ioim_lm_fetch_lun(ioim, (u8 *)(rl->lun), 0,
-                       (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1);
-
-       /* fetch luns from multiple sg elements */
-       scsi_for_each_sg(cmnd, sg, scsi_sg_count(cmnd), sgeid) {
-               if (sgeid == 0) {
-                       prev_sg_len = sg_dma_len(sg);
-                       prev_rl_data = (struct scsi_lun *)
-                                       phys_to_virt(sg_dma_address(sg));
-                       continue;
-               }
-
-               /* if the buf is having more data */
-               lun_across_sg_bytes = prev_sg_len % sizeof(struct scsi_lun);
-               if (lun_across_sg_bytes) {
-                       bfa_trc(ioim->bfa, lun_across_sg_bytes);
-                       bfa_stats(ioim->itnim, lm_lun_across_sg);
-                       bytes_from_next_buf = sizeof(struct scsi_lun) -
-                                             lun_across_sg_bytes;
-
-                       /* from next buf take higher bytes */
-                       temp_last_lun = *((u64 *)
-                                         phys_to_virt(sg_dma_address(sg)));
-                       last_lun |= temp_last_lun >>
-                                   (lun_across_sg_bytes * BITS_PER_BYTE);
-
-                       /* from prev buf take higher bytes */
-                       temp_last_lun = *((u64 *)(prev_rl_data +
-                                         (prev_sg_len - lun_across_sg_bytes)));
-                       temp_last_lun >>= bytes_from_next_buf * BITS_PER_BYTE;
-                       last_lun = last_lun | (temp_last_lun <<
-                                  (bytes_from_next_buf * BITS_PER_BYTE));
-
-                       bfa_ioim_lm_fetch_lun(ioim, (u8 *)&last_lun, 0, 1);
-               } else
-                       bytes_from_next_buf = 0;
-
-               *pgdlen += sg_dma_len(sg);
-               prev_sg_len = sg_dma_len(sg);
-               prev_rl_data = (struct scsi_lun *)
-                               phys_to_virt(sg_dma_address(sg));
-               bfa_ioim_lm_fetch_lun(ioim, (u8 *)prev_rl_data,
-                               bytes_from_next_buf,
-                               sg_dma_len(sg) / sizeof(struct scsi_lun));
-       }
-
-       /* update the report luns data - based on fetched luns */
-       sg = scsi_sglist(cmnd);
-       base_rl_data = (struct scsi_lun *)rl->lun;
-       base_count = (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1;
-       for (i = 0, j = 0; i < MAX_LUN_MASK_CFG; i++) {
-               if (lun_list[i].state == BFA_IOIM_LUN_MASK_FETCHED) {
-                       base_rl_data[j] = lun_list[i].lun;
-                       lun_list[i].state = BFA_IOIM_LUN_MASK_ACTIVE;
-                       j++;
-                       lun_fetched_cnt++;
-               }
-
-               if (j > base_count) {
-                       j = 0;
-                       sg = sg_next(sg);
-                       base_rl_data = (struct scsi_lun *)
-                                       phys_to_virt(sg_dma_address(sg));
-                       base_count = sg_dma_len(sg) / sizeof(struct scsi_lun);
-               }
-       }
-
-       bfa_trc(ioim->bfa, lun_fetched_cnt);
-       return lun_fetched_cnt;
-}
-
-static bfa_boolean_t
-bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim)
-{
-       struct scsi_inquiry_data_s *inq;
-       struct scatterlist *sg = scsi_sglist((struct scsi_cmnd *)ioim->dio);
-
-       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
-       inq = (struct scsi_inquiry_data_s *)phys_to_virt(sg_dma_address(sg));
-
-       bfa_trc(ioim->bfa, inq->device_type);
-       inq->peripheral_qual = SCSI_INQ_PQ_NOT_CON;
-       return 0;
-}
-
-static bfa_boolean_t
-bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim)
-{
-       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
-       struct scatterlist *sg = scsi_sglist(cmnd);
-       struct bfi_ioim_rsp_s *m;
-       struct scsi_report_luns_data_s *rl = NULL;
-       int lun_count = 0, lun_fetched_cnt = 0;
-       u32 residue, pgdlen = 0;
-
-       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
-       if (bfa_get_lun_mask_status(ioim->bfa) != BFA_LUNMASK_ENABLED)
-               return BFA_TRUE;
-
-       m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
-       if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION)
-               return BFA_TRUE;
-
-       pgdlen = sg_dma_len(sg);
-       bfa_trc(ioim->bfa, pgdlen);
-       rl = (struct scsi_report_luns_data_s *)phys_to_virt(sg_dma_address(sg));
-       lun_count = cpu_to_be32(rl->lun_list_length) / sizeof(struct scsi_lun);
-       lun_fetched_cnt = bfa_ioim_lm_update_lun_sg(ioim, &pgdlen, rl);
-
-       if (lun_count == lun_fetched_cnt)
-               return BFA_TRUE;
-
-       bfa_trc(ioim->bfa, lun_count);
-       bfa_trc(ioim->bfa, lun_fetched_cnt);
-       bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
-
-       if (be32_to_cpu(rl->lun_list_length) <= pgdlen)
-               rl->lun_list_length = be32_to_cpu(lun_fetched_cnt) *
-                                     sizeof(struct scsi_lun);
-       else
-               bfa_stats(ioim->itnim, lm_small_buf_addresidue);
-
-       bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
-       bfa_trc(ioim->bfa, be32_to_cpu(m->residue));
-
-       residue = be32_to_cpu(m->residue);
-       residue += (lun_count - lun_fetched_cnt) * sizeof(struct scsi_lun);
-       bfa_stats(ioim->itnim, lm_wire_residue_changed);
-       m->residue = be32_to_cpu(residue);
-       bfa_trc(ioim->bfa, ioim->nsges);
-       return BFA_FALSE;
-}
-
 static void
 __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
 {
@@ -2454,83 +2167,6 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
                          m->scsi_status, sns_len, snsinfo, residue);
 }
 
-static void
-__bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete)
-{
-       struct bfa_ioim_s *ioim = cbarg;
-       int sns_len = 0xD;
-       u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
-       struct scsi_sense_s *snsinfo;
-
-       if (!complete) {
-               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-               return;
-       }
-
-       snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
-                                       ioim->fcpim->fcp, ioim->iotag);
-       snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
-       snsinfo->add_sense_length = 0xa;
-       snsinfo->asc = SCSI_ASC_LUN_NOT_SUPPORTED;
-       snsinfo->sense_key = ILLEGAL_REQUEST;
-       bfa_trc(ioim->bfa, residue);
-       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
-                       SCSI_STATUS_CHECK_CONDITION, sns_len,
-                       (u8 *)snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete)
-{
-       struct bfa_ioim_s *ioim = cbarg;
-       int sns_len = 0xD;
-       u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
-       struct scsi_sense_s *snsinfo;
-
-       if (!complete) {
-               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-               return;
-       }
-
-       snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
-                                                      ioim->iotag);
-       snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
-       snsinfo->sense_key = SCSI_MP_IEC_UNIT_ATTN;
-       snsinfo->asc = SCSI_ASC_TOCC;
-       snsinfo->add_sense_length = 0x6;
-       snsinfo->ascq = SCSI_ASCQ_RL_DATA_CHANGED;
-       bfa_trc(ioim->bfa, residue);
-       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
-                       SCSI_STATUS_CHECK_CONDITION, sns_len,
-                       (u8 *)snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete)
-{
-       struct bfa_ioim_s *ioim = cbarg;
-       int sns_len = 0xD;
-       u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
-       struct scsi_sense_s *snsinfo;
-
-       if (!complete) {
-               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-               return;
-       }
-
-       snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
-                                       ioim->fcpim->fcp, ioim->iotag);
-       snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
-       snsinfo->add_sense_length = 0xa;
-       snsinfo->sense_key = NOT_READY;
-       snsinfo->asc = SCSI_ASC_LUN_NOT_READY;
-       snsinfo->ascq = SCSI_ASCQ_MAN_INTR_REQ;
-       bfa_trc(ioim->bfa, residue);
-       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
-                       SCSI_STATUS_CHECK_CONDITION, sns_len,
-                       (u8 *)snsinfo, residue);
-}
-
 void
 bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn,
                        u16 rp_tag, u8 lp_tag)
@@ -2647,7 +2283,8 @@ bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
        if (port) {
                *pwwn = port->port_cfg.pwwn;
                rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
-               rp = rp_fcs->bfa_rport;
+               if (rp_fcs)
+                       rp = rp_fcs->bfa_rport;
        }
 
        lunm_list = bfa_get_lun_mask_list(bfa);
@@ -2715,7 +2352,8 @@ bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
                if (port) {
                        *pwwn = port->port_cfg.pwwn;
                        rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
-                       rp = rp_fcs->bfa_rport;
+                       if (rp_fcs)
+                               rp = rp_fcs->bfa_rport;
                }
        }
 
@@ -2757,7 +2395,6 @@ __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
                return;
        }
 
-       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
                          0, 0, NULL, 0);
 }
@@ -2773,7 +2410,6 @@ __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
                return;
        }
 
-       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
                          0, 0, NULL, 0);
 }
@@ -2788,7 +2424,6 @@ __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
                return;
        }
 
-       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
 }
 
@@ -3132,7 +2767,6 @@ bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
                ioim->bfa     = fcpim->bfa;
                ioim->fcpim   = fcpim;
                ioim->iosp    = iosp;
-               ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
                INIT_LIST_HEAD(&ioim->sgpg_q);
                bfa_reqq_winit(&ioim->iosp->reqq_wait,
                                   bfa_ioim_qresume, ioim);
@@ -3170,7 +2804,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                        evt = BFA_IOIM_SM_DONE;
                else
                        evt = BFA_IOIM_SM_COMP;
-               ioim->proc_rsp_data(ioim);
                break;
 
        case BFI_IOIM_STS_TIMEDOUT:
@@ -3206,7 +2839,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                if (rsp->abort_tag != ioim->abort_tag) {
                        bfa_trc(ioim->bfa, rsp->abort_tag);
                        bfa_trc(ioim->bfa, ioim->abort_tag);
-                       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
                        return;
                }
 
@@ -3225,7 +2857,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                WARN_ON(1);
        }
 
-       ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
        bfa_sm_send_event(ioim, evt);
 }
 
@@ -3244,15 +2875,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 
        bfa_ioim_cb_profile_comp(fcpim, ioim);
 
-       if (bfa_get_lun_mask_status(bfa) != BFA_LUNMASK_ENABLED)  {
-               bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
-               return;
-       }
-
-       if (ioim->proc_rsp_data(ioim) == BFA_TRUE)
-               bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
-       else
-               bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP);
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
 }
 
 /*
@@ -3364,35 +2987,6 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
 void
 bfa_ioim_start(struct bfa_ioim_s *ioim)
 {
-       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
-       struct bfa_lps_s        *lps;
-       enum bfa_ioim_lm_status status;
-       struct scsi_lun scsilun;
-
-       if (bfa_get_lun_mask_status(ioim->bfa) == BFA_LUNMASK_ENABLED) {
-               lps = BFA_IOIM_TO_LPS(ioim);
-               int_to_scsilun(cmnd->device->lun, &scsilun);
-               status = bfa_ioim_lm_check(ioim, lps,
-                               ioim->itnim->rport, scsilun);
-               if (status == BFA_IOIM_LM_LUN_NOT_RDY) {
-                       bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_RDY);
-                       bfa_stats(ioim->itnim, lm_lun_not_rdy);
-                       return;
-               }
-
-               if (status == BFA_IOIM_LM_LUN_NOT_SUP) {
-                       bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_SUP);
-                       bfa_stats(ioim->itnim, lm_lun_not_sup);
-                       return;
-               }
-
-               if (status == BFA_IOIM_LM_RPL_DATA_CHANGED) {
-                       bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_RPL_DC);
-                       bfa_stats(ioim->itnim, lm_rpl_data_changed);
-                       return;
-               }
-       }
-
        bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
 
        /*
index 1080bcb81cb73a2caf409d800da3b78deed8234f..36f26da80f76c1c496ec20bc1e42ae93e878df11 100644 (file)
@@ -110,7 +110,6 @@ struct bfad_ioim_s;
 struct bfad_tskim_s;
 
 typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
-typedef bfa_boolean_t (*bfa_ioim_lm_proc_rsp_data_t) (struct bfa_ioim_s *ioim);
 
 struct bfa_fcpim_s {
        struct bfa_s            *bfa;
@@ -124,7 +123,6 @@ struct bfa_fcpim_s {
        u32                     path_tov;
        u16                     q_depth;
        u8                      reqq;           /*  Request queue to be used */
-       u8                      lun_masking_pending;
        struct list_head        itnim_q;        /*  queue of active itnim */
        struct list_head        ioim_resfree_q; /*  IOs waiting for f/w */
        struct list_head        ioim_comp_q;    /*  IO global comp Q    */
@@ -181,7 +179,6 @@ struct bfa_ioim_s {
        u8                      reqq;           /*  Request queue for I/O */
        u8                      mode;           /*  IO is passthrough or not */
        u64                     start_time;     /*  IO's Profile start val */
-       bfa_ioim_lm_proc_rsp_data_t proc_rsp_data; /* RSP data adjust */
 };
 
 struct bfa_ioim_sp_s {
@@ -261,10 +258,6 @@ struct bfa_itnim_s {
        (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET;              \
 } while (0)
 
-#define BFA_IOIM_TO_LPS(__ioim)                \
-       BFA_LPS_FROM_TAG(BFA_LPS_MOD(__ioim->bfa),      \
-               __ioim->itnim->rport->rport_info.lp_tag)
-
 static inline bfa_boolean_t
 bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
 {
index 95adb86d3769d477bdbf0b652aa704621eca665b..b52cbb6bcd5a3b6b4c7623753df79630892686ea 100644 (file)
@@ -582,11 +582,6 @@ void bfa_cb_rport_qos_scn_prio(void *rport,
 #define BFA_LP_TAG_INVALID     0xff
 void   bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
 void   bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
-bfa_boolean_t  bfa_rport_lunmask_active(struct bfa_rport_s *rp);
-wwn_t  bfa_rport_get_pwwn(struct bfa_s *bfa, struct bfa_rport_s *rp);
-struct bfa_rport_s *bfa_rport_get_by_wwn(struct bfa_s *bfa, u16 vf_id,
-                                        wwn_t *lpwwn, wwn_t rpwwn);
-void *bfa_cb_get_rp_by_wwn(void *arg, u16 vf_id, wwn_t *lpwwn, wwn_t rpwwn);
 
 /*
  * bfa fcxp API functions
index 66fb72531b34caab0323797761d68ac2ab0e6fbc..404fd10ddb21cd6b89821694807e402d30e3bf21 100644 (file)
@@ -674,6 +674,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        bfa_fcs_vport_start(&vport->fcs_vport);
+       list_add_tail(&vport->list_entry, &bfad->vport_list);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
        return BFA_STATUS_OK;
@@ -1404,6 +1405,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
        bfad->ref_count = 0;
        bfad->pport.bfad = bfad;
        INIT_LIST_HEAD(&bfad->pbc_vport_list);
+       INIT_LIST_HEAD(&bfad->vport_list);
 
        /* Setup the debugfs node for this bfad */
        if (bfa_debugfs_enable)
index 9d95844ab463ededc29b22e417d413e912b7cc48..1938fe0473e99b9aa24a5ee6e50a4e6fe9e9ac4d 100644 (file)
@@ -491,7 +491,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
 
 free_scsi_host:
        bfad_scsi_host_free(bfad, im_port);
-
+       list_del(&vport->list_entry);
        kfree(vport);
 
        return 0;
index 06fc00caeb41f725750a1ddafd44b5731e7eaa4a..530de2b1200a20c58b0e88a49c299ed97c2d1126 100644 (file)
@@ -2394,6 +2394,21 @@ out:
        return 0;
 }
 
+/* Function to reset the LUN SCAN mode */
+static void
+bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg)
+{
+       struct bfad_im_port_s *pport_im = bfad->pport.im_port;
+       struct bfad_vport_s *vport = NULL;
+
+       /* Set the scsi device LUN SCAN flags for base port */
+       bfad_reset_sdev_bflags(pport_im, lunmask_cfg);
+
+       /* Set the scsi device LUN SCAN flags for the vports */
+       list_for_each_entry(vport, &bfad->vport_list, list_entry)
+               bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg);
+}
+
 int
 bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
 {
@@ -2401,11 +2416,17 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE)
+       if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) {
                iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE);
-       else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE)
+               /* Set the LUN Scanning mode to be Sequential scan */
+               if (iocmd->status == BFA_STATUS_OK)
+                       bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE);
+       } else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) {
                iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE);
-       else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
+               /* Set the LUN Scanning mode to default REPORT_LUNS scan */
+               if (iocmd->status == BFA_STATUS_OK)
+                       bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE);
+       } else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
                iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        return 0;
index 5e19a5f820ec6d515773ec942ff4ba1d9184608e..dc5b9d99c4505f1356f7e0bed16d05bd992285ef 100644 (file)
@@ -43,6 +43,7 @@
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_bsg_fc.h>
+#include <scsi/scsi_devinfo.h>
 
 #include "bfa_modules.h"
 #include "bfa_fcs.h"
@@ -227,6 +228,7 @@ struct bfad_s {
        struct list_head        active_aen_q;
        struct bfa_aen_entry_s  aen_list[BFA_AEN_MAX_ENTRY];
        spinlock_t              bfad_aen_spinlock;
+       struct list_head        vport_list;
 };
 
 /* BFAD state machine events */
index e5db649e8eb757dbe79241645c024734d76dd21a..3153923f5b6027f1c16d806e14092e1df5356218 100644 (file)
@@ -917,6 +917,37 @@ bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
        return NULL;
 }
 
+/*
+ * Function is invoked from the SCSI Host Template slave_alloc() entry point.
+ * Has the logic to query the LUN Mask database to check if this LUN needs to
+ * be made visible to the SCSI mid-layer or not.
+ *
+ * Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack.
+ * Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack.
+ */
+static int
+bfad_im_check_if_make_lun_visible(struct scsi_device *sdev,
+                                 struct fc_rport *rport)
+{
+       struct bfad_itnim_data_s *itnim_data =
+                               (struct bfad_itnim_data_s *) rport->dd_data;
+       struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
+       struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport;
+       struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa);
+       int i = 0, ret = -ENXIO;
+
+       for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+               if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE &&
+                   scsilun_to_int(&lun_list[i].lun) == sdev->lun &&
+                   lun_list[i].rp_tag == bfa_rport->rport_tag &&
+                   lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) {
+                       ret = BFA_STATUS_OK;
+                       break;
+               }
+       }
+       return ret;
+}
+
 /*
  * Scsi_Host template entry slave_alloc
  */
@@ -924,10 +955,33 @@ static int
 bfad_im_slave_alloc(struct scsi_device *sdev)
 {
        struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+       struct bfad_itnim_data_s *itnim_data =
+                               (struct bfad_itnim_data_s *) rport->dd_data;
+       struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
 
        if (!rport || fc_remote_port_chkready(rport))
                return -ENXIO;
 
+       if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) {
+               /*
+                * We should not mask LUN 0 - since this will translate
+                * to no LUN / TARGET for SCSI ml resulting no scan.
+                */
+               if (sdev->lun == 0) {
+                       sdev->sdev_bflags |= BLIST_NOREPORTLUN |
+                                            BLIST_SPARSELUN;
+                       goto done;
+               }
+
+               /*
+                * Query LUN Mask configuration - to expose this LUN
+                * to the SCSI mid-layer or to mask it.
+                */
+               if (bfad_im_check_if_make_lun_visible(sdev, rport) !=
+                                                       BFA_STATUS_OK)
+                       return -ENXIO;
+       }
+done:
        sdev->hostdata = rport->dd_data;
 
        return 0;
@@ -1037,6 +1091,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
            && (fc_rport->scsi_target_id < MAX_FCP_TARGET))
                itnim->scsi_tgt_id = fc_rport->scsi_target_id;
 
+       itnim->channel = fc_rport->channel;
+
        return;
 }
 
index 004b6cf848d943288934452237c1cfa2ef8b8cfd..0814367ef101a1c075c0cfd4f5a52bc34dea920d 100644 (file)
@@ -91,6 +91,7 @@ struct bfad_itnim_s {
        struct fc_rport *fc_rport;
        struct bfa_itnim_s *bfa_itnim;
        u16        scsi_tgt_id;
+       u16        channel;
        u16        queue_work;
        unsigned long   last_ramp_up_time;
        unsigned long   last_queue_full_time;
@@ -166,4 +167,30 @@ irqreturn_t bfad_intx(int irq, void *dev_id);
 int bfad_im_bsg_request(struct fc_bsg_job *job);
 int bfad_im_bsg_timeout(struct fc_bsg_job *job);
 
+/*
+ * Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the
+ * SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan
+ *
+ * Internally iterate's over all the ITNIM's part of the im_port & set's the
+ * sdev_bflags for the scsi_device associated with LUN #0.
+ */
+#define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do {          \
+       struct scsi_device *__sdev = NULL;                              \
+       struct bfad_itnim_s *__itnim = NULL;                            \
+       u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN;           \
+       list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list), \
+                           list_entry) {                               \
+               __sdev = scsi_device_lookup((__im_port)->shost,         \
+                                           __itnim->channel,           \
+                                           __itnim->scsi_tgt_id, 0);   \
+               if (__sdev) {                                           \
+                       if ((__lunmask_cfg) == BFA_TRUE)                \
+                               __sdev->sdev_bflags |= scan_flags;      \
+                       else                                            \
+                               __sdev->sdev_bflags &= ~scan_flags;     \
+                       scsi_device_put(__sdev);                        \
+               }                                                       \
+       }                                                               \
+} while (0)
+
 #endif
index c5360ffb4bed35ae9bd06fa1a0195f2517b82778..d3ff9cd40234f5d5ea478020ecbf0a04bac1503e 100644 (file)
@@ -1868,8 +1868,9 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
 
        tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
        if (!tdata->skb) {
-               pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n",
-                       cdev->skb_tx_rsvd, headroom, opcode);
+               struct cxgbi_sock *csk = cconn->cep->csk;
+               struct net_device *ndev = cdev->ports[csk->port_id];
+               ndev->stats.tx_dropped++;
                return -ENOMEM;
        }
 
index 4ef021291a4d06d2ecd4340f5ba1c35658a5c9d1..04c5cea47a2258a2156f692a6441253db31a8506 100644 (file)
@@ -466,6 +466,11 @@ static int alua_check_sense(struct scsi_device *sdev,
                         * Power On, Reset, or Bus Device Reset, just retry.
                         */
                        return ADD_TO_MLQUEUE;
+               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01)
+                       /*
+                        * Mode Parameters Changed
+                        */
+                       return ADD_TO_MLQUEUE;
                if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
                        /*
                         * ALUA state changed
index 841ebf4a6788fc3895d5ddd31b8a67f7ce49ab55..53a31c753cb1e682ead92268901bc966845a1996 100644 (file)
@@ -953,6 +953,8 @@ static int __init rdac_init(void)
        if (!kmpath_rdacd) {
                scsi_unregister_device_handler(&rdac_dh);
                printk(KERN_ERR "kmpath_rdacd creation failed.\n");
+
+               r = -EINVAL;
        }
 done:
        return r;
index 8d67467dd9cec100f52b51803fbe943192421a58..e9599600aa230b8b6315c405730352f99e6a7d9a 100644 (file)
@@ -58,7 +58,11 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for "     \
                 "Direct Data Placement (DDP).");
 
-DEFINE_MUTEX(fcoe_config_mutex);
+unsigned int fcoe_debug_logging;
+module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+
+static DEFINE_MUTEX(fcoe_config_mutex);
 
 static struct workqueue_struct *fcoe_wq;
 
@@ -67,8 +71,8 @@ static DECLARE_COMPLETION(fcoe_flush_completion);
 
 /* fcoe host list */
 /* must only by accessed under the RTNL mutex */
-LIST_HEAD(fcoe_hostlist);
-DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
+static LIST_HEAD(fcoe_hostlist);
+static DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
 
 /* Function Prototypes */
 static int fcoe_reset(struct Scsi_Host *);
@@ -157,7 +161,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
        .lport_set_port_id = fcoe_set_port_id,
 };
 
-struct fc_function_template fcoe_nport_fc_functions = {
+static struct fc_function_template fcoe_nport_fc_functions = {
        .show_host_node_name = 1,
        .show_host_port_name = 1,
        .show_host_supported_classes = 1,
@@ -197,7 +201,7 @@ struct fc_function_template fcoe_nport_fc_functions = {
        .bsg_request = fc_lport_bsg_request,
 };
 
-struct fc_function_template fcoe_vport_fc_functions = {
+static struct fc_function_template fcoe_vport_fc_functions = {
        .show_host_node_name = 1,
        .show_host_port_name = 1,
        .show_host_supported_classes = 1,
@@ -433,7 +437,7 @@ static inline void fcoe_interface_put(struct fcoe_interface *fcoe)
  *
  * Caller must be holding the RTNL mutex
  */
-void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
+static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 {
        struct net_device *netdev = fcoe->netdev;
        struct fcoe_ctlr *fip = &fcoe->ctlr;
@@ -748,7 +752,7 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
  *
  * Returns: True for read types I/O, otherwise returns false.
  */
-bool fcoe_oem_match(struct fc_frame *fp)
+static bool fcoe_oem_match(struct fc_frame *fp)
 {
        struct fc_frame_header *fh = fc_frame_header_get(fp);
        struct fcp_cmnd *fcp;
@@ -756,11 +760,12 @@ bool fcoe_oem_match(struct fc_frame *fp)
        if (fc_fcp_is_read(fr_fsp(fp)) &&
            (fr_fsp(fp)->data_len > fcoe_ddp_min))
                return true;
-       else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) {
+       else if ((fr_fsp(fp) == NULL) &&
+                (fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD) &&
+                (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) {
                fcp = fc_frame_payload_get(fp, sizeof(*fcp));
-               if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN &&
-                   fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) &&
-                   (fcp->fc_flags & FCP_CFL_WRDATA))
+               if ((fcp->fc_flags & FCP_CFL_WRDATA) &&
+                   (ntohl(fcp->fc_dl) > fcoe_ddp_min))
                        return true;
        }
        return false;
@@ -1106,7 +1111,7 @@ static int __init fcoe_if_init(void)
  *
  * Returns: 0 on success
  */
-int __exit fcoe_if_exit(void)
+static int __exit fcoe_if_exit(void)
 {
        fc_release_transport(fcoe_nport_scsi_transport);
        fc_release_transport(fcoe_vport_scsi_transport);
@@ -1295,7 +1300,7 @@ static inline unsigned int fcoe_select_cpu(void)
  *
  * Returns: 0 for success
  */
-int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
+static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
             struct packet_type *ptype, struct net_device *olddev)
 {
        struct fc_lport *lport;
@@ -1451,7 +1456,7 @@ static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
  *
  * Return: 0 for success
  */
-int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
+static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 {
        int wlen;
        u32 crc;
@@ -1671,8 +1676,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
                        skb->dev ? skb->dev->name : "<NULL>");
 
        port = lport_priv(lport);
-       if (skb_is_nonlinear(skb))
-               skb_linearize(skb);     /* not ideal */
+       skb_linearize(skb); /* check for skb_is_nonlinear is within skb_linearize */
 
        /*
         * Frame length checks and setting up the header pointers
@@ -1728,7 +1732,7 @@ drop:
  *
  * Return: 0 for success
  */
-int fcoe_percpu_receive_thread(void *arg)
+static int fcoe_percpu_receive_thread(void *arg)
 {
        struct fcoe_percpu_s *p = arg;
        struct sk_buff *skb;
@@ -2146,7 +2150,7 @@ out_nortnl:
  * Returns: 0 if the ethtool query was successful
  *          -1 if the ethtool query failed
  */
-int fcoe_link_speed_update(struct fc_lport *lport)
+static int fcoe_link_speed_update(struct fc_lport *lport)
 {
        struct net_device *netdev = fcoe_netdev(lport);
        struct ethtool_cmd ecmd;
@@ -2180,7 +2184,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
  * Returns: 0 if link is UP and OK, -1 if not
  *
  */
-int fcoe_link_ok(struct fc_lport *lport)
+static int fcoe_link_ok(struct fc_lport *lport)
 {
        struct net_device *netdev = fcoe_netdev(lport);
 
@@ -2200,7 +2204,7 @@ int fcoe_link_ok(struct fc_lport *lport)
  * there no packets that will be handled by the lport, but also that any
  * threads already handling packet have returned.
  */
-void fcoe_percpu_clean(struct fc_lport *lport)
+static void fcoe_percpu_clean(struct fc_lport *lport)
 {
        struct fcoe_percpu_s *pp;
        struct fcoe_rcv_info *fr;
@@ -2251,7 +2255,7 @@ void fcoe_percpu_clean(struct fc_lport *lport)
  *
  * Returns: Always 0 (return value required by FC transport template)
  */
-int fcoe_reset(struct Scsi_Host *shost)
+static int fcoe_reset(struct Scsi_Host *shost)
 {
        struct fc_lport *lport = shost_priv(shost);
        struct fcoe_port *port = lport_priv(lport);
index 6c6884bcf84004e7f792ccccc71bf9728cc24095..bcc89e63949573173e20fac339765d72633b96de 100644 (file)
@@ -40,9 +40,7 @@
 #define FCOE_MIN_XID           0x0000  /* the min xid supported by fcoe_sw */
 #define FCOE_MAX_XID           0x0FFF  /* the max xid supported by fcoe_sw */
 
-unsigned int fcoe_debug_logging;
-module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+extern unsigned int fcoe_debug_logging;
 
 #define FCOE_LOGGING       0x01 /* General logging, not categorized */
 #define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */
index 5140f5d0fd6be610f5038368fdec6627be4e9cea..b96962c394492604cd2fc2a73ce80731db28882d 100644 (file)
@@ -4271,7 +4271,9 @@ static void stop_controller_lockup_detector(struct ctlr_info *h)
        remove_ctlr_from_lockup_detector_list(h);
        /* If the list of ctlr's to monitor is empty, stop the thread */
        if (list_empty(&hpsa_ctlr_list)) {
+               spin_unlock_irqrestore(&lockup_detector_lock, flags);
                kthread_stop(hpsa_lockup_detector);
+               spin_lock_irqsave(&lockup_detector_lock, flags);
                hpsa_lockup_detector = NULL;
        }
        spin_unlock_irqrestore(&lockup_detector_lock, flags);
diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile
deleted file mode 100644 (file)
index 5f54461..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Makefile for create_fw
-#
-CC=gcc
-CFLAGS=-c -Wall -O2 -g
-LDFLAGS=
-SOURCES=create_fw.c
-OBJECTS=$(SOURCES:.cpp=.o)
-EXECUTABLE=create_fw
-
-all: $(SOURCES) $(EXECUTABLE)
-
-$(EXECUTABLE): $(OBJECTS)
-       $(CC) $(LDFLAGS) $(OBJECTS) -o $@
-
-.c.o:
-       $(CC) $(CFLAGS) $< -O $@
-
-clean:
-       rm -f *.o $(EXECUTABLE)
diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README
deleted file mode 100644 (file)
index 8056d2b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-This defines the temporary binary blow we are to pass to the SCU
-driver to emulate the binary firmware that we will eventually be
-able to access via NVRAM on the SCU controller.
-
-The current size of the binary blob is expected to be 149 bytes or larger
-
-Header Types:
-0x1: Phy Masks
-0x2: Phy Gens
-0x3: SAS Addrs
-0xff: End of Data
-
-ID string - u8[12]: "#SCU MAGIC#\0"
-Version - u8: 1
-SubVersion - u8: 0
-
-Header Type - u8: 0x1
-Size - u8: 8
-Phy Mask - u32[8]
-
-Header Type - u8: 0x2
-Size - u8: 8
-Phy Gen - u32[8]
-
-Header Type - u8: 0x3
-Size - u8: 8
-Sas Addr - u64[8]
-
-Header Type - u8: 0xf
-
-
-==============================================================================
-
-Place isci_firmware.bin in /lib/firmware
-Be sure to recreate the initramfs image to include the firmware.
-
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
deleted file mode 100644 (file)
index c7a2887..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <asm/types.h>
-#include <strings.h>
-#include <stdint.h>
-
-#include "create_fw.h"
-#include "../probe_roms.h"
-
-int write_blob(struct isci_orom *isci_orom)
-{
-       FILE *fd;
-       int err;
-       size_t count;
-
-       fd = fopen(blob_name, "w+");
-       if (!fd) {
-               perror("Open file for write failed");
-               fclose(fd);
-               return -EIO;
-       }
-
-       count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd);
-       if (count != 1) {
-               perror("Write data failed");
-               fclose(fd);
-               return -EIO;
-       }
-
-       fclose(fd);
-
-       return 0;
-}
-
-void set_binary_values(struct isci_orom *isci_orom)
-{
-       int ctrl_idx, phy_idx, port_idx;
-
-       /* setting OROM signature */
-       strncpy(isci_orom->hdr.signature, sig, strlen(sig));
-       isci_orom->hdr.version = version;
-       isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
-       isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
-       isci_orom->hdr.num_elements = num_elements;
-
-       for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
-               isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
-               isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up =
-                       max_num_concurrent_dev_spin_up;
-               isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
-                       enable_ssc;
-
-               for (port_idx = 0; port_idx < 4; port_idx++)
-                       isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
-                               phy_mask[ctrl_idx][port_idx];
-
-               for (phy_idx = 0; phy_idx < 4; phy_idx++) {
-                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
-                               (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
-                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
-                               (__u32)(sas_addr[ctrl_idx][phy_idx]);
-
-                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
-                               afe_tx_amp_control0;
-                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
-                               afe_tx_amp_control1;
-                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
-                               afe_tx_amp_control2;
-                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
-                               afe_tx_amp_control3;
-               }
-       }
-}
-
-int main(void)
-{
-       int err;
-       struct isci_orom *isci_orom;
-
-       isci_orom = malloc(sizeof(struct isci_orom));
-       memset(isci_orom, 0, sizeof(struct isci_orom));
-
-       set_binary_values(isci_orom);
-
-       err = write_blob(isci_orom);
-       if (err < 0) {
-               free(isci_orom);
-               return err;
-       }
-
-       free(isci_orom);
-       return 0;
-}
diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h
deleted file mode 100644 (file)
index 5f29882..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _CREATE_FW_H_
-#define _CREATE_FW_H_
-#include "../probe_roms.h"
-
-
-/* we are configuring for 2 SCUs */
-static const int num_elements = 2;
-
-/*
- * For all defined arrays:
- * elements 0-3 are for SCU0, ports 0-3
- * elements 4-7 are for SCU1, ports 0-3
- *
- * valid configurations for one SCU are:
- *  P0  P1  P2  P3
- * ----------------
- * 0xF,0x0,0x0,0x0 # 1 x4 port
- * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
- *                 # ports
- * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
- *                 # port
- * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
- * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
- *
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value assigned to UNINIT_PARAM (255).
- */
-
-/* discovery mode type (port auto config mode by default ) */
-
-/*
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value "0000000000000000". SAS address of zero's is
- * considered invalid and will not be used.
- */
-#ifdef MPC
-static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
-static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
-                                    {1, 2, 4, 8} };
-static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL,
-                                                    0x5FCFFFFFF0000002ULL,
-                                                    0x5FCFFFFFF0000003ULL,
-                                                    0x5FCFFFFFF0000004ULL },
-                                                  { 0x5FCFFFFFF0000005ULL,
-                                                    0x5FCFFFFFF0000006ULL,
-                                                    0x5FCFFFFFF0000007ULL,
-                                                    0x5FCFFFFFF0000008ULL } };
-#else  /* APC (default) */
-static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
-static const __u8 phy_mask[2][4];
-static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
-                                                    0x5FCFFFFF00000001ULL,
-                                                    0x5FCFFFFF00000001ULL,
-                                                    0x5FCFFFFF00000001ULL },
-                                                  { 0x5FCFFFFF00000002ULL,
-                                                    0x5FCFFFFF00000002ULL,
-                                                    0x5FCFFFFF00000002ULL,
-                                                    0x5FCFFFFF00000002ULL } };
-#endif
-
-/* Maximum number of concurrent device spin up */
-static const int max_num_concurrent_dev_spin_up = 1;
-
-/* enable of ssc operation */
-static const int enable_ssc;
-
-/* AFE_TX_AMP_CONTROL */
-static const unsigned int afe_tx_amp_control0 = 0x000bdd08;
-static const unsigned int afe_tx_amp_control1 = 0x000ffc00;
-static const unsigned int afe_tx_amp_control2 = 0x000b7c09;
-static const unsigned int afe_tx_amp_control3 = 0x000afc6e;
-
-static const char blob_name[] = "isci_firmware.bin";
-static const char sig[] = "ISCUOEMB";
-static const unsigned char version = 0x10;
-
-#endif
index e7fe9c4c85b84d7098850eb16288caaae8b20578..1a65d6514237dd59ac24c8deb89f1afce27a4e3d 100644 (file)
@@ -899,7 +899,8 @@ static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost)
                         */
                        if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) ||
                            (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) ||
-                           (iphy->is_in_link_training == true && is_phy_starting(iphy))) {
+                           (iphy->is_in_link_training == true && is_phy_starting(iphy)) ||
+                           (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) {
                                is_controller_start_complete = false;
                                break;
                        }
@@ -1666,6 +1667,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
        /* Default to no SSC operation. */
        ihost->oem_parameters.controller.do_enable_ssc = false;
 
+       /* Default to short cables on all phys. */
+       ihost->oem_parameters.controller.cable_selection_mask = 0;
+
        /* Initialize all of the port parameter information to narrow ports. */
        for (index = 0; index < SCI_MAX_PORTS; index++) {
                ihost->oem_parameters.ports[index].phy_mask = 0;
@@ -1673,8 +1677,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
 
        /* Initialize all of the phy parameter information. */
        for (index = 0; index < SCI_MAX_PHYS; index++) {
-               /* Default to 6G (i.e. Gen 3) for now. */
-               ihost->user_parameters.phys[index].max_speed_generation = 3;
+               /* Default to 3G (i.e. Gen 2). */
+               ihost->user_parameters.phys[index].max_speed_generation =
+                       SCIC_SDS_PARM_GEN2_SPEED;
 
                /* the frequencies cannot be 0 */
                ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f;
@@ -1694,7 +1699,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
        ihost->user_parameters.ssp_inactivity_timeout = 5;
        ihost->user_parameters.stp_max_occupancy_timeout = 5;
        ihost->user_parameters.ssp_max_occupancy_timeout = 20;
-       ihost->user_parameters.no_outbound_task_timeout = 20;
+       ihost->user_parameters.no_outbound_task_timeout = 2;
 }
 
 static void controller_timeout(unsigned long data)
@@ -1759,7 +1764,7 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost,
        return sci_controller_reset(ihost);
 }
 
-int sci_oem_parameters_validate(struct sci_oem_params *oem)
+int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version)
 {
        int i;
 
@@ -1791,18 +1796,61 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem)
            oem->controller.max_concurr_spin_up < 1)
                return -EINVAL;
 
+       if (oem->controller.do_enable_ssc) {
+               if (version < ISCI_ROM_VER_1_1 && oem->controller.do_enable_ssc != 1)
+                       return -EINVAL;
+
+               if (version >= ISCI_ROM_VER_1_1) {
+                       u8 test = oem->controller.ssc_sata_tx_spread_level;
+
+                       switch (test) {
+                       case 0:
+                       case 2:
+                       case 3:
+                       case 6:
+                       case 7:
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+
+                       test = oem->controller.ssc_sas_tx_spread_level;
+                       if (oem->controller.ssc_sas_tx_type == 0) {
+                               switch (test) {
+                               case 0:
+                               case 2:
+                               case 3:
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                       } else if (oem->controller.ssc_sas_tx_type == 1) {
+                               switch (test) {
+                               case 0:
+                               case 3:
+                               case 6:
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                       }
+               }
+       }
+
        return 0;
 }
 
 static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
 {
        u32 state = ihost->sm.current_state_id;
+       struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
 
        if (state == SCIC_RESET ||
            state == SCIC_INITIALIZING ||
            state == SCIC_INITIALIZED) {
 
-               if (sci_oem_parameters_validate(&ihost->oem_parameters))
+               if (sci_oem_parameters_validate(&ihost->oem_parameters,
+                                               pci_info->orom->hdr.version))
                        return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 
                return SCI_SUCCESS;
@@ -1857,6 +1905,31 @@ static void power_control_timeout(unsigned long data)
                ihost->power_control.phys_waiting--;
                ihost->power_control.phys_granted_power++;
                sci_phy_consume_power_handler(iphy);
+
+               if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+                       u8 j;
+
+                       for (j = 0; j < SCI_MAX_PHYS; j++) {
+                               struct isci_phy *requester = ihost->power_control.requesters[j];
+
+                               /*
+                                * Search the power_control queue to see if there are other phys
+                                * attached to the same remote device. If found, take all of
+                                * them out of await_sas_power state.
+                                */
+                               if (requester != NULL && requester != iphy) {
+                                       u8 other = memcmp(requester->frame_rcvd.iaf.sas_addr,
+                                                         iphy->frame_rcvd.iaf.sas_addr,
+                                                         sizeof(requester->frame_rcvd.iaf.sas_addr));
+
+                                       if (other == 0) {
+                                               ihost->power_control.requesters[j] = NULL;
+                                               ihost->power_control.phys_waiting--;
+                                               sci_phy_consume_power_handler(requester);
+                                       }
+                               }
+                       }
+               }
        }
 
        /*
@@ -1891,9 +1964,34 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
                ihost->power_control.timer_started = true;
 
        } else {
-               /* Add the phy in the waiting list */
-               ihost->power_control.requesters[iphy->phy_index] = iphy;
-               ihost->power_control.phys_waiting++;
+               /*
+                * There are phys, attached to the same sas address as this phy, are
+                * already in READY state, this phy don't need wait.
+                */
+               u8 i;
+               struct isci_phy *current_phy;
+
+               for (i = 0; i < SCI_MAX_PHYS; i++) {
+                       u8 other;
+                       current_phy = &ihost->phys[i];
+
+                       other = memcmp(current_phy->frame_rcvd.iaf.sas_addr,
+                                      iphy->frame_rcvd.iaf.sas_addr,
+                                      sizeof(current_phy->frame_rcvd.iaf.sas_addr));
+
+                       if (current_phy->sm.current_state_id == SCI_PHY_READY &&
+                           current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
+                           other == 0) {
+                               sci_phy_consume_power_handler(iphy);
+                               break;
+                       }
+               }
+
+               if (i == SCI_MAX_PHYS) {
+                       /* Add the phy in the waiting list */
+                       ihost->power_control.requesters[iphy->phy_index] = iphy;
+                       ihost->power_control.phys_waiting++;
+               }
        }
 }
 
@@ -1908,162 +2006,250 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,
        ihost->power_control.requesters[iphy->phy_index] = NULL;
 }
 
+static int is_long_cable(int phy, unsigned char selection_byte)
+{
+       return !!(selection_byte & (1 << phy));
+}
+
+static int is_medium_cable(int phy, unsigned char selection_byte)
+{
+       return !!(selection_byte & (1 << (phy + 4)));
+}
+
+static enum cable_selections decode_selection_byte(
+       int phy,
+       unsigned char selection_byte)
+{
+       return ((selection_byte & (1 << phy)) ? 1 : 0)
+               + (selection_byte & (1 << (phy + 4)) ? 2 : 0);
+}
+
+static unsigned char *to_cable_select(struct isci_host *ihost)
+{
+       if (is_cable_select_overridden())
+               return ((unsigned char *)&cable_selection_override)
+                       + ihost->id;
+       else
+               return &ihost->oem_parameters.controller.cable_selection_mask;
+}
+
+enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy)
+{
+       return decode_selection_byte(phy, *to_cable_select(ihost));
+}
+
+char *lookup_cable_names(enum cable_selections selection)
+{
+       static char *cable_names[] = {
+               [short_cable]     = "short",
+               [long_cable]      = "long",
+               [medium_cable]    = "medium",
+               [undefined_cable] = "<undefined, assumed long>" /* bit 0==1 */
+       };
+       return (selection <= undefined_cable) ? cable_names[selection]
+                                             : cable_names[undefined_cable];
+}
+
 #define AFE_REGISTER_WRITE_DELAY 10
 
-/* Initialize the AFE for this phy index. We need to read the AFE setup from
- * the OEM parameters
- */
 static void sci_controller_afe_initialization(struct isci_host *ihost)
 {
+       struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
        const struct sci_oem_params *oem = &ihost->oem_parameters;
        struct pci_dev *pdev = ihost->pdev;
        u32 afe_status;
        u32 phy_id;
+       unsigned char cable_selection_mask = *to_cable_select(ihost);
 
        /* Clear DFX Status registers */
-       writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0);
+       writel(0x0081000f, &afe->afe_dfx_master_control0);
        udelay(AFE_REGISTER_WRITE_DELAY);
 
-       if (is_b0(pdev)) {
+       if (is_b0(pdev) || is_c0(pdev) || is_c1(pdev)) {
                /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement
-                * Timer, PM Stagger Timer */
-               writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2);
+                * Timer, PM Stagger Timer
+                */
+               writel(0x0007FFFF, &afe->afe_pmsn_master_control2);
                udelay(AFE_REGISTER_WRITE_DELAY);
        }
 
        /* Configure bias currents to normal */
        if (is_a2(pdev))
-               writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control);
+               writel(0x00005A00, &afe->afe_bias_control);
        else if (is_b0(pdev) || is_c0(pdev))
-               writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control);
+               writel(0x00005F00, &afe->afe_bias_control);
+       else if (is_c1(pdev))
+               writel(0x00005500, &afe->afe_bias_control);
 
        udelay(AFE_REGISTER_WRITE_DELAY);
 
        /* Enable PLL */
-       if (is_b0(pdev) || is_c0(pdev))
-               writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0);
-       else
-               writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0);
+       if (is_a2(pdev))
+               writel(0x80040908, &afe->afe_pll_control0);
+       else if (is_b0(pdev) || is_c0(pdev))
+               writel(0x80040A08, &afe->afe_pll_control0);
+       else if (is_c1(pdev)) {
+               writel(0x80000B08, &afe->afe_pll_control0);
+               udelay(AFE_REGISTER_WRITE_DELAY);
+               writel(0x00000B08, &afe->afe_pll_control0);
+               udelay(AFE_REGISTER_WRITE_DELAY);
+               writel(0x80000B08, &afe->afe_pll_control0);
+       }
 
        udelay(AFE_REGISTER_WRITE_DELAY);
 
        /* Wait for the PLL to lock */
        do {
-               afe_status = readl(&ihost->scu_registers->afe.afe_common_block_status);
+               afe_status = readl(&afe->afe_common_block_status);
                udelay(AFE_REGISTER_WRITE_DELAY);
        } while ((afe_status & 0x00001000) == 0);
 
        if (is_a2(pdev)) {
-               /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
-               writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0);
+               /* Shorten SAS SNW lock time (RxLock timer value from 76
+                * us to 50 us)
+                */
+               writel(0x7bcc96ad, &afe->afe_pmsn_master_control0);
                udelay(AFE_REGISTER_WRITE_DELAY);
        }
 
        for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
+               struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_id];
                const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
+               int cable_length_long =
+                       is_long_cable(phy_id, cable_selection_mask);
+               int cable_length_medium =
+                       is_medium_cable(phy_id, cable_selection_mask);
 
-               if (is_b0(pdev)) {
-                        /* Configure transmitter SSC parameters */
-                       writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
+               if (is_a2(pdev)) {
+                       /* All defaults, except the Receive Word
+                        * Alignament/Comma Detect Enable....(0xe800)
+                        */
+                       writel(0x00004512, &xcvr->afe_xcvr_control0);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
+
+                       writel(0x0050100F, &xcvr->afe_xcvr_control1);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
+               } else if (is_b0(pdev)) {
+                       /* Configure transmitter SSC parameters */
+                       writel(0x00030000, &xcvr->afe_tx_ssc_control);
                        udelay(AFE_REGISTER_WRITE_DELAY);
                } else if (is_c0(pdev)) {
-                        /* Configure transmitter SSC parameters */
-                       writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
+                       /* Configure transmitter SSC parameters */
+                       writel(0x00010202, &xcvr->afe_tx_ssc_control);
                        udelay(AFE_REGISTER_WRITE_DELAY);
 
-                       /*
-                        * All defaults, except the Receive Word Alignament/Comma Detect
-                        * Enable....(0xe800) */
-                       writel(0x00004500, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
+                       /* All defaults, except the Receive Word
+                        * Alignament/Comma Detect Enable....(0xe800)
+                        */
+                       writel(0x00014500, &xcvr->afe_xcvr_control0);
                        udelay(AFE_REGISTER_WRITE_DELAY);
-               } else {
-                       /*
-                        * All defaults, except the Receive Word Alignament/Comma Detect
-                        * Enable....(0xe800) */
-                       writel(0x00004512, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
+               } else if (is_c1(pdev)) {
+                       /* Configure transmitter SSC parameters */
+                       writel(0x00010202, &xcvr->afe_tx_ssc_control);
                        udelay(AFE_REGISTER_WRITE_DELAY);
 
-                       writel(0x0050100F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1);
+                       /* All defaults, except the Receive Word
+                        * Alignament/Comma Detect Enable....(0xe800)
+                        */
+                       writel(0x0001C500, &xcvr->afe_xcvr_control0);
                        udelay(AFE_REGISTER_WRITE_DELAY);
                }
 
-               /*
-                * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
-                * & increase TX int & ext bias 20%....(0xe85c) */
+               /* Power up TX and RX out from power down (PWRDNTX and
+                * PWRDNRX) & increase TX int & ext bias 20%....(0xe85c)
+                */
                if (is_a2(pdev))
-                       writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+                       writel(0x000003F0, &xcvr->afe_channel_control);
                else if (is_b0(pdev)) {
-                        /* Power down TX and RX (PWRDNTX and PWRDNRX) */
-                       writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+                       writel(0x000003D7, &xcvr->afe_channel_control);
                        udelay(AFE_REGISTER_WRITE_DELAY);
 
-                       /*
-                        * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
-                        * & increase TX int & ext bias 20%....(0xe85c) */
-                       writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
-               } else {
-                       writel(0x000001E7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+                       writel(0x000003D4, &xcvr->afe_channel_control);
+               } else if (is_c0(pdev)) {
+                       writel(0x000001E7, &xcvr->afe_channel_control);
                        udelay(AFE_REGISTER_WRITE_DELAY);
 
-                       /*
-                        * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
-                        * & increase TX int & ext bias 20%....(0xe85c) */
-                       writel(0x000001E4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+                       writel(0x000001E4, &xcvr->afe_channel_control);
+               } else if (is_c1(pdev)) {
+                       writel(cable_length_long ? 0x000002F7 : 0x000001F7,
+                              &xcvr->afe_channel_control);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
+
+                       writel(cable_length_long ? 0x000002F4 : 0x000001F4,
+                              &xcvr->afe_channel_control);
                }
                udelay(AFE_REGISTER_WRITE_DELAY);
 
                if (is_a2(pdev)) {
                        /* Enable TX equalization (0xe824) */
-                       writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
+                       writel(0x00040000, &xcvr->afe_tx_control);
                        udelay(AFE_REGISTER_WRITE_DELAY);
                }
 
-               /*
-                * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
-                * RDD=0x0(RX Detect Enabled) ....(0xe800) */
-               writel(0x00004100, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
+               if (is_a2(pdev) || is_b0(pdev))
+                       /* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0,
+                        * TPD=0x0(TX Power On), RDD=0x0(RX Detect
+                        * Enabled) ....(0xe800)
+                        */
+                       writel(0x00004100, &xcvr->afe_xcvr_control0);
+               else if (is_c0(pdev))
+                       writel(0x00014100, &xcvr->afe_xcvr_control0);
+               else if (is_c1(pdev))
+                       writel(0x0001C100, &xcvr->afe_xcvr_control0);
                udelay(AFE_REGISTER_WRITE_DELAY);
 
                /* Leave DFE/FFE on */
                if (is_a2(pdev))
-                       writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
+                       writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
                else if (is_b0(pdev)) {
-                       writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
+                       writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
                        udelay(AFE_REGISTER_WRITE_DELAY);
                        /* Enable TX equalization (0xe824) */
-                       writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
-               } else {
-                       writel(0x0140DF0F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1);
+                       writel(0x00040000, &xcvr->afe_tx_control);
+               } else if (is_c0(pdev)) {
+                       writel(0x01400C0F, &xcvr->afe_rx_ssc_control1);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
+
+                       writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
+
+                       /* Enable TX equalization (0xe824) */
+                       writel(0x00040000, &xcvr->afe_tx_control);
+               } else if (is_c1(pdev)) {
+                       writel(cable_length_long ? 0x01500C0C :
+                              cable_length_medium ? 0x01400C0D : 0x02400C0D,
+                              &xcvr->afe_xcvr_control1);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
+
+                       writel(0x000003E0, &xcvr->afe_dfx_rx_control1);
                        udelay(AFE_REGISTER_WRITE_DELAY);
 
-                       writel(0x3F6F103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
+                       writel(cable_length_long ? 0x33091C1F :
+                              cable_length_medium ? 0x3315181F : 0x2B17161F,
+                              &xcvr->afe_rx_ssc_control0);
                        udelay(AFE_REGISTER_WRITE_DELAY);
 
                        /* Enable TX equalization (0xe824) */
-                       writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
+                       writel(0x00040000, &xcvr->afe_tx_control);
                }
 
                udelay(AFE_REGISTER_WRITE_DELAY);
 
-               writel(oem_phy->afe_tx_amp_control0,
-                       &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0);
+               writel(oem_phy->afe_tx_amp_control0, &xcvr->afe_tx_amp_control0);
                udelay(AFE_REGISTER_WRITE_DELAY);
 
-               writel(oem_phy->afe_tx_amp_control1,
-                       &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1);
+               writel(oem_phy->afe_tx_amp_control1, &xcvr->afe_tx_amp_control1);
                udelay(AFE_REGISTER_WRITE_DELAY);
 
-               writel(oem_phy->afe_tx_amp_control2,
-                       &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2);
+               writel(oem_phy->afe_tx_amp_control2, &xcvr->afe_tx_amp_control2);
                udelay(AFE_REGISTER_WRITE_DELAY);
 
-               writel(oem_phy->afe_tx_amp_control3,
-                       &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3);
+               writel(oem_phy->afe_tx_amp_control3, &xcvr->afe_tx_amp_control3);
                udelay(AFE_REGISTER_WRITE_DELAY);
        }
 
        /* Transfer control to the PEs */
-       writel(0x00010f00, &ihost->scu_registers->afe.afe_dfx_master_control0);
+       writel(0x00010f00, &afe->afe_dfx_master_control0);
        udelay(AFE_REGISTER_WRITE_DELAY);
 }
 
index 646051afd3cbd07e2ab6761a18edef7355cf39f6..5477f0fa8233198e691945a08c14eba074be2f21 100644 (file)
@@ -435,11 +435,36 @@ static inline bool is_b0(struct pci_dev *pdev)
 
 static inline bool is_c0(struct pci_dev *pdev)
 {
-       if (pdev->revision >= 5)
+       if (pdev->revision == 5)
                return true;
        return false;
 }
 
+static inline bool is_c1(struct pci_dev *pdev)
+{
+       if (pdev->revision >= 6)
+               return true;
+       return false;
+}
+
+enum cable_selections {
+       short_cable     = 0,
+       long_cable      = 1,
+       medium_cable    = 2,
+       undefined_cable = 3
+};
+
+#define CABLE_OVERRIDE_DISABLED (0x10000)
+
+static inline int is_cable_select_overridden(void)
+{
+       return cable_selection_override < CABLE_OVERRIDE_DISABLED;
+}
+
+enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy);
+void validate_cable_selections(struct isci_host *ihost);
+char *lookup_cable_names(enum cable_selections);
+
 /* set hw control for 'activity', even though active enclosures seem to drive
  * the activity led on their own.  Skip setting FSENG control on 'status' due
  * to unexpected operation and 'error' due to not being a supported automatic
index a97edabcb85a29e96e1741171fcce2ea4c7cb4c0..17c4c2c89c2e5d9fe56f7e3b08010fc5ded3d71b 100644 (file)
@@ -65,7 +65,7 @@
 #include "probe_roms.h"
 
 #define MAJ 1
-#define MIN 0
+#define MIN 1
 #define BUILD 0
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
        __stringify(BUILD)
@@ -94,7 +94,7 @@ MODULE_DEVICE_TABLE(pci, isci_id_table);
 
 /* linux isci specific settings */
 
-unsigned char no_outbound_task_to = 20;
+unsigned char no_outbound_task_to = 2;
 module_param(no_outbound_task_to, byte, 0);
 MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)");
 
@@ -114,7 +114,7 @@ u16 stp_inactive_to = 5;
 module_param(stp_inactive_to, ushort, 0);
 MODULE_PARM_DESC(stp_inactive_to, "STP inactivity timeout (100us incr)");
 
-unsigned char phy_gen = 3;
+unsigned char phy_gen = SCIC_SDS_PARM_GEN2_SPEED;
 module_param(phy_gen, byte, 0);
 MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
 
@@ -122,6 +122,14 @@ unsigned char max_concurr_spinup;
 module_param(max_concurr_spinup, byte, 0);
 MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
 
+uint cable_selection_override = CABLE_OVERRIDE_DISABLED;
+module_param(cable_selection_override, uint, 0);
+
+MODULE_PARM_DESC(cable_selection_override,
+                "This field indicates length of the SAS/SATA cable between "
+                "host and device. If any bits > 15 are set (default) "
+                "indicates \"use platform defaults\"");
+
 static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
@@ -412,6 +420,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
                return NULL;
        isci_host->shost = shost;
 
+       dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: "
+                "{%s, %s, %s, %s}\n",
+                (is_cable_select_overridden() ? "* " : ""), isci_host->id,
+                lookup_cable_names(decode_cable_selection(isci_host, 3)),
+                lookup_cable_names(decode_cable_selection(isci_host, 2)),
+                lookup_cable_names(decode_cable_selection(isci_host, 1)),
+                lookup_cable_names(decode_cable_selection(isci_host, 0)));
+
        err = isci_host_init(isci_host);
        if (err)
                goto err_shost;
@@ -466,7 +482,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
                orom = isci_request_oprom(pdev);
 
        for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
-               if (sci_oem_parameters_validate(&orom->ctrl[i])) {
+               if (sci_oem_parameters_validate(&orom->ctrl[i],
+                                               orom->hdr.version)) {
                        dev_warn(&pdev->dev,
                                 "[%d]: invalid oem parameters detected, falling back to firmware\n", i);
                        devm_kfree(&pdev->dev, orom);
index 8efeb6b083213bb20d15ca3a9ca0a954515ec23f..234ab46fce3346948300d9ae95364e33103792ee 100644 (file)
@@ -480,6 +480,7 @@ extern u16 ssp_inactive_to;
 extern u16 stp_inactive_to;
 extern unsigned char phy_gen;
 extern unsigned char max_concurr_spinup;
+extern uint cable_selection_override;
 
 irqreturn_t isci_msix_isr(int vec, void *data);
 irqreturn_t isci_intx_isr(int vec, void *data);
index 35f50c2183e18a4c6460b07db081bb7d82ff6beb..fe18acfd6eb3ad9b62a775665a1dbedecb32e011 100644 (file)
@@ -91,22 +91,23 @@ sci_phy_transport_layer_initialization(struct isci_phy *iphy,
 
 static enum sci_status
 sci_phy_link_layer_initialization(struct isci_phy *iphy,
-                                 struct scu_link_layer_registers __iomem *reg)
+                                 struct scu_link_layer_registers __iomem *llr)
 {
        struct isci_host *ihost = iphy->owning_port->owning_controller;
+       struct sci_phy_user_params *phy_user;
+       struct sci_phy_oem_params *phy_oem;
        int phy_idx = iphy->phy_index;
-       struct sci_phy_user_params *phy_user = &ihost->user_parameters.phys[phy_idx];
-       struct sci_phy_oem_params *phy_oem =
-               &ihost->oem_parameters.phys[phy_idx];
-       u32 phy_configuration;
        struct sci_phy_cap phy_cap;
+       u32 phy_configuration;
        u32 parity_check = 0;
        u32 parity_count = 0;
        u32 llctl, link_rate;
        u32 clksm_value = 0;
        u32 sp_timeouts = 0;
 
-       iphy->link_layer_registers = reg;
+       phy_user = &ihost->user_parameters.phys[phy_idx];
+       phy_oem = &ihost->oem_parameters.phys[phy_idx];
+       iphy->link_layer_registers = llr;
 
        /* Set our IDENTIFY frame data */
        #define SCI_END_DEVICE 0x01
@@ -116,32 +117,26 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
               SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |
               SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |
               SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE),
-              &iphy->link_layer_registers->transmit_identification);
+              &llr->transmit_identification);
 
        /* Write the device SAS Address */
-       writel(0xFEDCBA98,
-              &iphy->link_layer_registers->sas_device_name_high);
-       writel(phy_idx, &iphy->link_layer_registers->sas_device_name_low);
+       writel(0xFEDCBA98, &llr->sas_device_name_high);
+       writel(phy_idx, &llr->sas_device_name_low);
 
        /* Write the source SAS Address */
-       writel(phy_oem->sas_address.high,
-               &iphy->link_layer_registers->source_sas_address_high);
-       writel(phy_oem->sas_address.low,
-               &iphy->link_layer_registers->source_sas_address_low);
+       writel(phy_oem->sas_address.high, &llr->source_sas_address_high);
+       writel(phy_oem->sas_address.low, &llr->source_sas_address_low);
 
        /* Clear and Set the PHY Identifier */
-       writel(0, &iphy->link_layer_registers->identify_frame_phy_id);
-       writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx),
-               &iphy->link_layer_registers->identify_frame_phy_id);
+       writel(0, &llr->identify_frame_phy_id);
+       writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), &llr->identify_frame_phy_id);
 
        /* Change the initial state of the phy configuration register */
-       phy_configuration =
-               readl(&iphy->link_layer_registers->phy_configuration);
+       phy_configuration = readl(&llr->phy_configuration);
 
        /* Hold OOB state machine in reset */
        phy_configuration |=  SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
-       writel(phy_configuration,
-               &iphy->link_layer_registers->phy_configuration);
+       writel(phy_configuration, &llr->phy_configuration);
 
        /* Configure the SNW capabilities */
        phy_cap.all = 0;
@@ -149,15 +144,64 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
        phy_cap.gen3_no_ssc = 1;
        phy_cap.gen2_no_ssc = 1;
        phy_cap.gen1_no_ssc = 1;
-       if (ihost->oem_parameters.controller.do_enable_ssc == true) {
+       if (ihost->oem_parameters.controller.do_enable_ssc) {
+               struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
+               struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_idx];
+               struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
+               bool en_sas = false;
+               bool en_sata = false;
+               u32 sas_type = 0;
+               u32 sata_spread = 0x2;
+               u32 sas_spread = 0x2;
+
                phy_cap.gen3_ssc = 1;
                phy_cap.gen2_ssc = 1;
                phy_cap.gen1_ssc = 1;
+
+               if (pci_info->orom->hdr.version < ISCI_ROM_VER_1_1)
+                       en_sas = en_sata = true;
+               else {
+                       sata_spread = ihost->oem_parameters.controller.ssc_sata_tx_spread_level;
+                       sas_spread = ihost->oem_parameters.controller.ssc_sas_tx_spread_level;
+
+                       if (sata_spread)
+                               en_sata = true;
+
+                       if (sas_spread) {
+                               en_sas = true;
+                               sas_type = ihost->oem_parameters.controller.ssc_sas_tx_type;
+                       }
+
+               }
+
+               if (en_sas) {
+                       u32 reg;
+
+                       reg = readl(&xcvr->afe_xcvr_control0);
+                       reg |= (0x00100000 | (sas_type << 19));
+                       writel(reg, &xcvr->afe_xcvr_control0);
+
+                       reg = readl(&xcvr->afe_tx_ssc_control);
+                       reg |= sas_spread << 8;
+                       writel(reg, &xcvr->afe_tx_ssc_control);
+               }
+
+               if (en_sata) {
+                       u32 reg;
+
+                       reg = readl(&xcvr->afe_tx_ssc_control);
+                       reg |= sata_spread;
+                       writel(reg, &xcvr->afe_tx_ssc_control);
+
+                       reg = readl(&llr->stp_control);
+                       reg |= 1 << 12;
+                       writel(reg, &llr->stp_control);
+               }
        }
 
-       /*
-        * The SAS specification indicates that the phy_capabilities that
-        * are transmitted shall have an even parity.  Calculate the parity. */
+       /* The SAS specification indicates that the phy_capabilities that
+        * are transmitted shall have an even parity.  Calculate the parity.
+        */
        parity_check = phy_cap.all;
        while (parity_check != 0) {
                if (parity_check & 0x1)
@@ -165,20 +209,20 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
                parity_check >>= 1;
        }
 
-       /*
-        * If parity indicates there are an odd number of bits set, then
-        * set the parity bit to 1 in the phy capabilities. */
+       /* If parity indicates there are an odd number of bits set, then
+        * set the parity bit to 1 in the phy capabilities.
+        */
        if ((parity_count % 2) != 0)
                phy_cap.parity = 1;
 
-       writel(phy_cap.all, &iphy->link_layer_registers->phy_capabilities);
+       writel(phy_cap.all, &llr->phy_capabilities);
 
        /* Set the enable spinup period but disable the ability to send
         * notify enable spinup
         */
        writel(SCU_ENSPINUP_GEN_VAL(COUNT,
                        phy_user->notify_enable_spin_up_insertion_frequency),
-               &iphy->link_layer_registers->notify_enable_spinup_control);
+               &llr->notify_enable_spinup_control);
 
        /* Write the ALIGN Insertion Ferequency for connected phy and
         * inpendent of connected state
@@ -189,11 +233,13 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
        clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,
                        phy_user->align_insertion_frequency);
 
-       writel(clksm_value, &iphy->link_layer_registers->clock_skew_management);
+       writel(clksm_value, &llr->clock_skew_management);
 
-       /* @todo Provide a way to write this register correctly */
-       writel(0x02108421,
-               &iphy->link_layer_registers->afe_lookup_table_control);
+       if (is_c0(ihost->pdev) || is_c1(ihost->pdev)) {
+               writel(0x04210400, &llr->afe_lookup_table_control);
+               writel(0x020A7C05, &llr->sas_primitive_timeout);
+       } else
+               writel(0x02108421, &llr->afe_lookup_table_control);
 
        llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,
                (u8)ihost->user_parameters.no_outbound_task_timeout);
@@ -210,9 +256,9 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
                break;
        }
        llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
-       writel(llctl, &iphy->link_layer_registers->link_layer_control);
+       writel(llctl, &llr->link_layer_control);
 
-       sp_timeouts = readl(&iphy->link_layer_registers->sas_phy_timeouts);
+       sp_timeouts = readl(&llr->sas_phy_timeouts);
 
        /* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */
        sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
@@ -222,20 +268,23 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
         */
        sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
 
-       writel(sp_timeouts, &iphy->link_layer_registers->sas_phy_timeouts);
+       writel(sp_timeouts, &llr->sas_phy_timeouts);
 
        if (is_a2(ihost->pdev)) {
-               /* Program the max ARB time for the PHY to 700us so we inter-operate with
-                * the PMC expander which shuts down PHYs if the expander PHY generates too
-                * many breaks.  This time value will guarantee that the initiator PHY will
-                * generate the break.
+               /* Program the max ARB time for the PHY to 700us so we
+                * inter-operate with the PMC expander which shuts down
+                * PHYs if the expander PHY generates too many breaks.
+                * This time value will guarantee that the initiator PHY
+                * will generate the break.
                 */
                writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME,
-                       &iphy->link_layer_registers->maximum_arbitration_wait_timer_timeout);
+                      &llr->maximum_arbitration_wait_timer_timeout);
        }
 
-       /* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */
-       writel(0, &iphy->link_layer_registers->link_layer_hang_detection_timeout);
+       /* Disable link layer hang detection, rely on the OS timeout for
+        * I/O timeouts.
+        */
+       writel(0, &llr->link_layer_hang_detection_timeout);
 
        /* We can exit the initial state to the stopped state */
        sci_change_state(&iphy->sm, SCI_PHY_STOPPED);
@@ -1049,24 +1098,25 @@ static void scu_link_layer_stop_protocol_engine(
        writel(enable_spinup_value, &iphy->link_layer_registers->notify_enable_spinup_control);
 }
 
-/**
- *
- *
- * This method will start the OOB/SN state machine for this struct isci_phy object.
- */
-static void scu_link_layer_start_oob(
-       struct isci_phy *iphy)
+static void scu_link_layer_start_oob(struct isci_phy *iphy)
 {
-       u32 scu_sas_pcfg_value;
-
-       scu_sas_pcfg_value =
-               readl(&iphy->link_layer_registers->phy_configuration);
-       scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
-       scu_sas_pcfg_value &=
-               ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
-               SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
-       writel(scu_sas_pcfg_value,
-              &iphy->link_layer_registers->phy_configuration);
+       struct scu_link_layer_registers __iomem *ll = iphy->link_layer_registers;
+       u32 val;
+
+       /** Reset OOB sequence - start */
+       val = readl(&ll->phy_configuration);
+       val &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
+                SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
+       writel(val, &ll->phy_configuration);
+       readl(&ll->phy_configuration); /* flush */
+       /** Reset OOB sequence - end */
+
+       /** Start OOB sequence - start */
+       val = readl(&ll->phy_configuration);
+       val |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+       writel(val, &ll->phy_configuration);
+       readl(&ll->phy_configuration); /* flush */
+       /** Start OOB sequence - end */
 }
 
 /**
index ac7f27749f975761a1beefc7f1b1741a5c02e0bc..7c6ac58a5c4c45c37af504f8e10bfa84cb7df3ee 100644 (file)
@@ -114,7 +114,7 @@ static u32 sci_port_get_phys(struct isci_port *iport)
  * value is returned if the specified port is not valid.  When this value is
  * returned, no data is copied to the properties output parameter.
  */
-static enum sci_status sci_port_get_properties(struct isci_port *iport,
+enum sci_status sci_port_get_properties(struct isci_port *iport,
                                                struct sci_port_properties *prop)
 {
        if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT)
@@ -647,19 +647,26 @@ void sci_port_setup_transports(struct isci_port *iport, u32 device_id)
        }
 }
 
-static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy,
-                                 bool do_notify_user)
+static void sci_port_resume_phy(struct isci_port *iport, struct isci_phy *iphy)
+{
+       sci_phy_resume(iphy);
+       iport->enabled_phy_mask |= 1 << iphy->phy_index;
+}
+
+static void sci_port_activate_phy(struct isci_port *iport,
+                                 struct isci_phy *iphy,
+                                 u8 flags)
 {
        struct isci_host *ihost = iport->owning_controller;
 
-       if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA)
+       if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME))
                sci_phy_resume(iphy);
 
        iport->active_phy_mask |= 1 << iphy->phy_index;
 
        sci_controller_clear_invalid_phy(ihost, iphy);
 
-       if (do_notify_user == true)
+       if (flags & PF_NOTIFY)
                isci_port_link_up(ihost, iport, iphy);
 }
 
@@ -669,14 +676,19 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
        struct isci_host *ihost = iport->owning_controller;
 
        iport->active_phy_mask &= ~(1 << iphy->phy_index);
+       iport->enabled_phy_mask &= ~(1 << iphy->phy_index);
        if (!iport->active_phy_mask)
                iport->last_active_phy = iphy->phy_index;
 
        iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
 
-       /* Re-assign the phy back to the LP as if it were a narrow port */
-       writel(iphy->phy_index,
-               &iport->port_pe_configuration_register[iphy->phy_index]);
+       /* Re-assign the phy back to the LP as if it were a narrow port for APC
+        * mode. For MPC mode, the phy will remain in the port.
+        */
+       if (iport->owning_controller->oem_parameters.controller.mode_type ==
+               SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
+               writel(iphy->phy_index,
+                       &iport->port_pe_configuration_register[iphy->phy_index]);
 
        if (do_notify_user == true)
                isci_port_link_down(ihost, iphy, iport);
@@ -701,18 +713,16 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
  * sci_port_general_link_up_handler - phy can be assigned to port?
  * @sci_port: sci_port object for which has a phy that has gone link up.
  * @sci_phy: This is the struct isci_phy object that has gone link up.
- * @do_notify_user: This parameter specifies whether to inform the user (via
- *    sci_port_link_up()) as to the fact that a new phy as become ready.
+ * @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy
  *
- * Determine if this phy can be assigned to this
- * port . If the phy is not a valid PHY for
- * this port then the function will notify the user. A PHY can only be
- * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
- * the same port. none
+ * Determine if this phy can be assigned to this port . If the phy is
+ * not a valid PHY for this port then the function will notify the user.
+ * A PHY can only be part of a port if it's attached SAS ADDRESS is the
+ * same as all other PHYs in the same port.
  */
 static void sci_port_general_link_up_handler(struct isci_port *iport,
-                                                 struct isci_phy *iphy,
-                                                 bool do_notify_user)
+                                            struct isci_phy *iphy,
+                                            u8 flags)
 {
        struct sci_sas_address port_sas_address;
        struct sci_sas_address phy_sas_address;
@@ -730,7 +740,7 @@ static void sci_port_general_link_up_handler(struct isci_port *iport,
            iport->active_phy_mask == 0) {
                struct sci_base_state_machine *sm = &iport->sm;
 
-               sci_port_activate_phy(iport, iphy, do_notify_user);
+               sci_port_activate_phy(iport, iphy, flags);
                if (sm->current_state_id == SCI_PORT_RESETTING)
                        port_state_machine_change(iport, SCI_PORT_READY);
        } else
@@ -781,11 +791,16 @@ bool sci_port_link_detected(
        struct isci_phy *iphy)
 {
        if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
-           (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) &&
-           sci_port_is_wide(iport)) {
-               sci_port_invalid_link_up(iport, iphy);
-
-               return false;
+           (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) {
+               if (sci_port_is_wide(iport)) {
+                       sci_port_invalid_link_up(iport, iphy);
+                       return false;
+               } else {
+                       struct isci_host *ihost = iport->owning_controller;
+                       struct isci_port *dst_port = &(ihost->ports[iphy->phy_index]);
+                       writel(iphy->phy_index,
+                              &dst_port->port_pe_configuration_register[iphy->phy_index]);
+               }
        }
 
        return true;
@@ -975,6 +990,13 @@ static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine
        }
 }
 
+static void scic_sds_port_ready_substate_waiting_exit(
+                                       struct sci_base_state_machine *sm)
+{
+       struct isci_port *iport = container_of(sm, typeof(*iport), sm);
+       sci_port_resume_port_task_scheduler(iport);
+}
+
 static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm)
 {
        u32 index;
@@ -988,13 +1010,13 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach
                        writel(iport->physical_port_index,
                                &iport->port_pe_configuration_register[
                                        iport->phy_table[index]->phy_index]);
+                       if (((iport->active_phy_mask^iport->enabled_phy_mask) & (1 << index)) != 0)
+                               sci_port_resume_phy(iport, iport->phy_table[index]);
                }
        }
 
        sci_port_update_viit_entry(iport);
 
-       sci_port_resume_port_task_scheduler(iport);
-
        /*
         * Post the dummy task for the port so the hardware can schedule
         * io correctly
@@ -1061,20 +1083,9 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach
        if (iport->active_phy_mask == 0) {
                isci_port_not_ready(ihost, iport);
 
-               port_state_machine_change(iport,
-                                         SCI_PORT_SUB_WAITING);
-       } else if (iport->started_request_count == 0)
-               port_state_machine_change(iport,
-                                         SCI_PORT_SUB_OPERATIONAL);
-}
-
-static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm)
-{
-       struct isci_port *iport = container_of(sm, typeof(*iport), sm);
-
-       sci_port_suspend_port_task_scheduler(iport);
-       if (iport->ready_exit)
-               sci_port_invalidate_dummy_remote_node(iport);
+               port_state_machine_change(iport, SCI_PORT_SUB_WAITING);
+       } else
+               port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL);
 }
 
 enum sci_status sci_port_start(struct isci_port *iport)
@@ -1252,7 +1263,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
                if (status != SCI_SUCCESS)
                        return status;
 
-               sci_port_general_link_up_handler(iport, iphy, true);
+               sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
                iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
                port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING);
 
@@ -1262,7 +1273,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
 
                if (status != SCI_SUCCESS)
                        return status;
-               sci_port_general_link_up_handler(iport, iphy, true);
+               sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY);
 
                /* Re-enter the configuring state since this may be the last phy in
                 * the port.
@@ -1338,13 +1349,13 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
                /* Since this is the first phy going link up for the port we
                 * can just enable it and continue
                 */
-               sci_port_activate_phy(iport, iphy, true);
+               sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME);
 
                port_state_machine_change(iport,
                                          SCI_PORT_SUB_OPERATIONAL);
                return SCI_SUCCESS;
        case SCI_PORT_SUB_OPERATIONAL:
-               sci_port_general_link_up_handler(iport, iphy, true);
+               sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
                return SCI_SUCCESS;
        case SCI_PORT_RESETTING:
                /* TODO We should  make  sure  that  the phy  that  has gone
@@ -1361,7 +1372,7 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
                /* In the resetting state we don't notify the user regarding
                 * link up and link down notifications.
                 */
-               sci_port_general_link_up_handler(iport, iphy, false);
+               sci_port_general_link_up_handler(iport, iphy, PF_RESUME);
                return SCI_SUCCESS;
        default:
                dev_warn(sciport_to_dev(iport),
@@ -1584,14 +1595,14 @@ static const struct sci_base_state sci_port_state_table[] = {
        },
        [SCI_PORT_SUB_WAITING] = {
                .enter_state = sci_port_ready_substate_waiting_enter,
+               .exit_state  = scic_sds_port_ready_substate_waiting_exit,
        },
        [SCI_PORT_SUB_OPERATIONAL] = {
                .enter_state = sci_port_ready_substate_operational_enter,
                .exit_state  = sci_port_ready_substate_operational_exit
        },
        [SCI_PORT_SUB_CONFIGURING] = {
-               .enter_state = sci_port_ready_substate_configuring_enter,
-               .exit_state  = sci_port_ready_substate_configuring_exit
+               .enter_state = sci_port_ready_substate_configuring_enter
        },
        [SCI_PORT_RESETTING] = {
                .exit_state  = sci_port_resetting_state_exit
@@ -1609,6 +1620,7 @@ void sci_port_construct(struct isci_port *iport, u8 index,
        iport->logical_port_index  = SCIC_SDS_DUMMY_PORT;
        iport->physical_port_index = index;
        iport->active_phy_mask     = 0;
+       iport->enabled_phy_mask    = 0;
        iport->last_active_phy     = 0;
        iport->ready_exit          = false;
 
index cb5ffbc386038136812da1e596ca5059ff391615..08116090eb7015dbe7c4b3862748a20601e6d765 100644 (file)
@@ -63,6 +63,9 @@
 
 #define SCIC_SDS_DUMMY_PORT   0xFF
 
+#define PF_NOTIFY (1 << 0)
+#define PF_RESUME (1 << 1)
+
 struct isci_phy;
 struct isci_host;
 
@@ -83,6 +86,8 @@ enum isci_status {
  * @logical_port_index: software port index
  * @physical_port_index: hardware port index
  * @active_phy_mask: identifies phy members
+ * @enabled_phy_mask: phy mask for the port
+ *                    that are already part of the port
  * @reserved_tag:
  * @reserved_rni: reserver for port task scheduler workaround
  * @started_request_count: reference count for outstanding commands
@@ -104,6 +109,7 @@ struct isci_port {
        u8 logical_port_index;
        u8 physical_port_index;
        u8 active_phy_mask;
+       u8 enabled_phy_mask;
        u8 last_active_phy;
        u16 reserved_rni;
        u16 reserved_tag;
@@ -250,6 +256,10 @@ bool sci_port_link_detected(
        struct isci_port *iport,
        struct isci_phy *iphy);
 
+enum sci_status sci_port_get_properties(
+       struct isci_port *iport,
+       struct sci_port_properties *prop);
+
 enum sci_status sci_port_link_up(struct isci_port *iport,
                                      struct isci_phy *iphy);
 enum sci_status sci_port_link_down(struct isci_port *iport,
index 38a99d2811411d102220a96bdf918579fb47546b..6d1e9544cbe5c03b7f84059b7651c1b9d560ffb2 100644 (file)
@@ -57,7 +57,7 @@
 
 #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT    (10)
 #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT    (10)
-#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION  (100)
+#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION  (250)
 
 enum SCIC_SDS_APC_ACTIVITY {
        SCIC_SDS_APC_SKIP_PHY,
@@ -466,6 +466,23 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
        return sci_port_configuration_agent_validate_ports(ihost, port_agent);
 }
 
+/*
+ * This routine will restart the automatic port configuration timeout
+ * timer for the next time period. This could be caused by either a link
+ * down event or a link up event where we can not yet tell to which a phy
+ * belongs.
+ */
+static void sci_apc_agent_start_timer(
+       struct sci_port_configuration_agent *port_agent,
+       u32 timeout)
+{
+       if (port_agent->timer_pending)
+               sci_del_timer(&port_agent->timer);
+
+       port_agent->timer_pending = true;
+       sci_mod_timer(&port_agent->timer, timeout);
+}
+
 static void sci_apc_agent_configure_ports(struct isci_host *ihost,
                                               struct sci_port_configuration_agent *port_agent,
                                               struct isci_phy *iphy,
@@ -565,17 +582,8 @@ static void sci_apc_agent_configure_ports(struct isci_host *ihost,
                break;
 
        case SCIC_SDS_APC_START_TIMER:
-               /*
-                * This can occur for either a link down event, or a link
-                * up event where we cannot yet tell the port to which a
-                * phy belongs.
-                */
-               if (port_agent->timer_pending)
-                       sci_del_timer(&port_agent->timer);
-
-               port_agent->timer_pending = true;
-               sci_mod_timer(&port_agent->timer,
-                             SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
+               sci_apc_agent_start_timer(port_agent,
+                                         SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
                break;
 
        case SCIC_SDS_APC_SKIP_PHY:
@@ -607,7 +615,8 @@ static void sci_apc_agent_link_up(struct isci_host *ihost,
        if (!iport) {
                /* the phy is not the part of this port */
                port_agent->phy_ready_mask |= 1 << phy_index;
-               sci_apc_agent_configure_ports(ihost, port_agent, iphy, true);
+               sci_apc_agent_start_timer(port_agent,
+                                         SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
        } else {
                /* the phy is already the part of the port */
                u32 port_state = iport->sm.current_state_id;
index b5f4341de2434ead30763b4228e49ff5ee2edc67..9b8117b9d7569e7a8bda7623ec2aa3a07fcfffb6 100644 (file)
@@ -147,7 +147,7 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw
 
        memcpy(orom, fw->data, fw->size);
 
-       if (is_c0(pdev))
+       if (is_c0(pdev) || is_c1(pdev))
                goto out;
 
        /*
index 2c75248ca326ea38e3a9256da8e966fddd516d41..bb0e9d4d97c9a8f0437e51aee3440c8ff0060004 100644 (file)
@@ -152,7 +152,7 @@ struct sci_user_parameters {
 #define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
 
 struct sci_oem_params;
-int sci_oem_parameters_validate(struct sci_oem_params *oem);
+int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version);
 
 struct isci_orom;
 struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
@@ -191,6 +191,11 @@ struct isci_oem_hdr {
                        0x1a, 0x04, 0xc6)
 #define ISCI_EFI_VAR_NAME      "RstScuO"
 
+#define ISCI_ROM_VER_1_0       0x10
+#define ISCI_ROM_VER_1_1       0x11
+#define ISCI_ROM_VER_1_3       0x13
+#define ISCI_ROM_VER_LATEST    ISCI_ROM_VER_1_3
+
 /* Allowed PORT configuration modes APC Automatic PORT configuration mode is
  * defined by the OEM configuration parameters providing no PHY_MASK parameters
  * for any PORT. i.e. There are no phys assigned to any of the ports at start.
@@ -220,8 +225,86 @@ struct sci_oem_params {
        struct {
                uint8_t mode_type;
                uint8_t max_concurr_spin_up;
-               uint8_t do_enable_ssc;
-               uint8_t reserved;
+               /*
+                * This bitfield indicates the OEM's desired default Tx
+                * Spread Spectrum Clocking (SSC) settings for SATA and SAS.
+                * NOTE: Default SSC Modulation Frequency is 31.5KHz.
+                */
+               union {
+                       struct {
+                       /*
+                        * NOTE: Max spread for SATA is +0 / -5000 PPM.
+                        * Down-spreading SSC (only method allowed for SATA):
+                        *  SATA SSC Tx Disabled                    = 0x0
+                        *  SATA SSC Tx at +0 / -1419 PPM Spread    = 0x2
+                        *  SATA SSC Tx at +0 / -2129 PPM Spread    = 0x3
+                        *  SATA SSC Tx at +0 / -4257 PPM Spread    = 0x6
+                        *  SATA SSC Tx at +0 / -4967 PPM Spread    = 0x7
+                        */
+                               uint8_t ssc_sata_tx_spread_level:4;
+                       /*
+                        * SAS SSC Tx Disabled                     = 0x0
+                        *
+                        * NOTE: Max spread for SAS down-spreading +0 /
+                        *       -2300 PPM
+                        * Down-spreading SSC:
+                        *  SAS SSC Tx at +0 / -1419 PPM Spread     = 0x2
+                        *  SAS SSC Tx at +0 / -2129 PPM Spread     = 0x3
+                        *
+                        * NOTE: Max spread for SAS center-spreading +2300 /
+                        *       -2300 PPM
+                        * Center-spreading SSC:
+                        *  SAS SSC Tx at +1064 / -1064 PPM Spread  = 0x3
+                        *  SAS SSC Tx at +2129 / -2129 PPM Spread  = 0x6
+                        */
+                               uint8_t ssc_sas_tx_spread_level:3;
+                       /*
+                        * NOTE: Refer to the SSC section of the SAS 2.x
+                        * Specification for proper setting of this field.
+                        * For standard SAS Initiator SAS PHY operation it
+                        * should be 0 for Down-spreading.
+                        * SAS SSC Tx spread type:
+                        *  Down-spreading SSC      = 0
+                        *  Center-spreading SSC    = 1
+                        */
+                               uint8_t ssc_sas_tx_type:1;
+                       };
+                       uint8_t do_enable_ssc;
+               };
+               /*
+                * This field indicates length of the SAS/SATA cable between
+                * host and device.
+                * This field is used make relationship between analog
+                * parameters of the phy in the silicon and length of the cable.
+                * Supported cable attenuation levels:
+                * "short"- up to 3m, "medium"-3m to 6m, and "long"- more than
+                * 6m.
+                *
+                * This is bit mask field:
+                *
+                * BIT:      (MSB) 7     6     5     4
+                * ASSIGNMENT:   <phy3><phy2><phy1><phy0>  - Medium cable
+                *                                           length assignment
+                * BIT:            3     2     1     0  (LSB)
+                * ASSIGNMENT:   <phy3><phy2><phy1><phy0>  - Long cable length
+                *                                           assignment
+                *
+                * BITS 7-4 are set when the cable length is assigned to medium
+                * BITS 3-0 are set when the cable length is assigned to long
+                *
+                * The BIT positions are clear when the cable length is
+                * assigned to short.
+                *
+                * Setting the bits for both long and medium cable length is
+                * undefined.
+                *
+                * A value of 0x84 would assign
+                *    phy3 - medium
+                *    phy2 - long
+                *    phy1 - short
+                *    phy0 - short
+                */
+               uint8_t cable_selection_mask;
        } controller;
 
        struct {
index b207cd3b15a0514da4579e9e869556d6b95dc961..dd74b6ceeb823df92bd69e69a0964069f1b5011a 100644 (file)
@@ -53,6 +53,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <scsi/sas.h>
+#include <linux/bitops.h>
 #include "isci.h"
 #include "port.h"
 #include "remote_device.h"
@@ -1101,6 +1102,7 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
                                                       struct isci_remote_device *idev)
 {
        enum sci_status status;
+       struct sci_port_properties properties;
        struct domain_device *dev = idev->domain_dev;
 
        sci_remote_device_construct(iport, idev);
@@ -1110,6 +1112,11 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
         * entries will be needed to store the remote node.
         */
        idev->is_direct_attached = true;
+
+       sci_port_get_properties(iport, &properties);
+       /* Get accurate port width from port's phy mask for a DA device. */
+       idev->device_port_width = hweight32(properties.phy_mask);
+
        status = sci_controller_allocate_remote_node_context(iport->owning_controller,
                                                                  idev,
                                                                  &idev->rnc.remote_node_index);
@@ -1125,9 +1132,6 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
 
        idev->connection_rate = sci_port_get_max_allowed_speed(iport);
 
-       /* / @todo Should I assign the port width by reading all of the phys on the port? */
-       idev->device_port_width = 1;
-
        return SCI_SUCCESS;
 }
 
index 66ad3dc89498a3ab305de95bc179ecaf42afa2f3..f5a3f7d2bdab29059af48d4b333d39b91c57d3d0 100644 (file)
@@ -496,7 +496,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
                }
        }
 
-       isci_print_tmf(tmf);
+       isci_print_tmf(ihost, tmf);
 
        if (tmf->status == SCI_SUCCESS)
                ret =  TMF_RESP_FUNC_COMPLETE;
index bc78c0a41d5cac86df69d6a23af08e6dac949552..1b27b3797c6c9cce8c1160c11d43240ccc4a52fe 100644 (file)
@@ -106,7 +106,6 @@ struct isci_tmf {
        } resp;
        unsigned char lun[8];
        u16 io_tag;
-       struct isci_remote_device *device;
        enum isci_tmf_function_codes tmf_code;
        int status;
 
@@ -120,10 +119,10 @@ struct isci_tmf {
 
 };
 
-static inline void isci_print_tmf(struct isci_tmf *tmf)
+static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
 {
        if (SAS_PROTOCOL_SATA == tmf->proto)
-               dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
+               dev_dbg(&ihost->pdev->dev,
                        "%s: status = %x\n"
                        "tmf->resp.d2h_fis.status = %x\n"
                        "tmf->resp.d2h_fis.error = %x\n",
@@ -132,7 +131,7 @@ static inline void isci_print_tmf(struct isci_tmf *tmf)
                        tmf->resp.d2h_fis.status,
                        tmf->resp.d2h_fis.error);
        else
-               dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
+               dev_dbg(&ihost->pdev->dev,
                        "%s: status = %x\n"
                        "tmf->resp.resp_iu.data_present = %x\n"
                        "tmf->resp.resp_iu.status = %x\n"
index 7269e928824a07f93efb1e570eb136f6cbedfbeb..1d1b0c9da29ba684100515b337431ccfb8be2b08 100644 (file)
@@ -61,7 +61,7 @@ static void fc_disc_restart(struct fc_disc *);
  * Locking Note: This function expects that the lport mutex is locked before
  * calling it.
  */
-void fc_disc_stop_rports(struct fc_disc *disc)
+static void fc_disc_stop_rports(struct fc_disc *disc)
 {
        struct fc_lport *lport;
        struct fc_rport_priv *rdata;
@@ -682,7 +682,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
  * fc_disc_stop() - Stop discovery for a given lport
  * @lport: The local port that discovery should stop on
  */
-void fc_disc_stop(struct fc_lport *lport)
+static void fc_disc_stop(struct fc_lport *lport)
 {
        struct fc_disc *disc = &lport->disc;
 
@@ -698,7 +698,7 @@ void fc_disc_stop(struct fc_lport *lport)
  * This function will block until discovery has been
  * completely stopped and all rports have been deleted.
  */
-void fc_disc_stop_final(struct fc_lport *lport)
+static void fc_disc_stop_final(struct fc_lport *lport)
 {
        fc_disc_stop(lport);
        lport->tt.rport_flush_queue();
index fb9161dc4ca67411f07413018562286fcaeff017..e17a28d324d04ccdf903043ae4549e04c94ccb85 100644 (file)
@@ -28,6 +28,7 @@
 #include <scsi/fc/fc_els.h>
 #include <scsi/libfc.h>
 #include <scsi/fc_encode.h>
+#include "fc_libfc.h"
 
 /**
  * fc_elsct_send() - Send an ELS or CT frame
index 9de9db27e87401b1f5cf244a15e9320011faa276..4d70d96fa5dc5730016a00a3c1753370ca5e980e 100644 (file)
@@ -91,7 +91,7 @@ struct fc_exch_pool {
  * It manages the allocation of exchange IDs.
  */
 struct fc_exch_mgr {
-       struct fc_exch_pool *pool;
+       struct fc_exch_pool __percpu *pool;
        mempool_t       *ep_pool;
        enum fc_class   class;
        struct kref     kref;
index 221875ec3d7c64de19c4f6404961be441fb16f34..f607314810accf03b38bee7b1f36fde6d4c2da9f 100644 (file)
@@ -155,6 +155,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
                fsp->xfer_ddp = FC_XID_UNKNOWN;
                atomic_set(&fsp->ref_cnt, 1);
                init_timer(&fsp->timer);
+               fsp->timer.data = (unsigned long)fsp;
                INIT_LIST_HEAD(&fsp->list);
                spin_lock_init(&fsp->scsi_pkt_lock);
        }
@@ -1850,9 +1851,6 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
        }
        put_cpu();
 
-       init_timer(&fsp->timer);
-       fsp->timer.data = (unsigned long)fsp;
-
        /*
         * send it to the lower layer
         * if we get -1 return then put the request in the pending
index e77094a587ed62aa17e1c1479d6a1ba04ad2af06..83750ebb527f5e2841f26a06d70a063658d8603f 100644 (file)
@@ -677,7 +677,8 @@ EXPORT_SYMBOL(fc_set_mfs);
  * @lport: The local port receiving the event
  * @event: The discovery event
  */
-void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
+static void fc_lport_disc_callback(struct fc_lport *lport,
+                                  enum fc_disc_event event)
 {
        switch (event) {
        case DISC_EV_SUCCESS:
@@ -1568,7 +1569,7 @@ EXPORT_SYMBOL(fc_lport_flogi_resp);
  * Locking Note: The lport lock is expected to be held before calling
  * this routine.
  */
-void fc_lport_enter_flogi(struct fc_lport *lport)
+static void fc_lport_enter_flogi(struct fc_lport *lport)
 {
        struct fc_frame *fp;
 
index b9e434844a69bb93fe12e153896973a1c8df2968..83aa1efec875999d5c980ab27dcb93cfc71e734c 100644 (file)
@@ -391,7 +391,7 @@ static void fc_rport_work(struct work_struct *work)
  * If it appears we are already logged in, ADISC is used to verify
  * the setup.
  */
-int fc_rport_login(struct fc_rport_priv *rdata)
+static int fc_rport_login(struct fc_rport_priv *rdata)
 {
        mutex_lock(&rdata->rp_mutex);
 
@@ -451,7 +451,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
  * function will hold the rport lock, call an _enter_*
  * function and then unlock the rport.
  */
-int fc_rport_logoff(struct fc_rport_priv *rdata)
+static int fc_rport_logoff(struct fc_rport_priv *rdata)
 {
        mutex_lock(&rdata->rp_mutex);
 
@@ -653,8 +653,8 @@ static int fc_rport_login_complete(struct fc_rport_priv *rdata,
  * @fp:            The FLOGI response frame
  * @rp_arg: The remote port that received the FLOGI response
  */
-void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
-                        void *rp_arg)
+static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
+                               void *rp_arg)
 {
        struct fc_rport_priv *rdata = rp_arg;
        struct fc_lport *lport = rdata->local_port;
@@ -1520,7 +1520,7 @@ reject:
  *
  * Locking Note: Called with the lport lock held.
  */
-void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
+static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
 {
        struct fc_seq_els_data els_data;
 
index 4ceeace804533c42b287aa9c54a3f952176dab9f..70eb1f79b1ba2f9fd08568e190bfb9126ece962c 100644 (file)
@@ -565,8 +565,7 @@ static int __devinit esp_mac_probe(struct platform_device *dev)
        esp_chips[dev->id] = esp;
        mb();
        if (esp_chips[!dev->id] == NULL) {
-               err = request_irq(host->irq, mac_scsi_esp_intr, 0,
-                                 "Mac ESP", NULL);
+               err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
                if (err < 0) {
                        esp_chips[dev->id] = NULL;
                        goto fail_free_priv;
index ea2bde206f7f951ee66abe3baa2b2abd94b3980e..2bccfbe5661e652bc24736cc572004698a7aecca 100644 (file)
@@ -339,9 +339,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
 
        printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
 
-       /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
-       disable_irq(IRQ_MAC_SCSI);
-
        /* get in phase */
        NCR5380_write( TARGET_COMMAND_REG,
                      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
@@ -357,9 +354,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
        for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
                barrier();
 
-       /* switch on SCSI IRQ again */
-       enable_irq(IRQ_MAC_SCSI);
-
        printk(KERN_INFO " done\n" );
 }
 #endif
index 5c1776406c963f996e16aac4781fe4540112d250..15eefa1d61fd8dfbd25d696bb519a28570005454 100644 (file)
@@ -306,19 +306,22 @@ mega_query_adapter(adapter_t *adapter)
        adapter->host->sg_tablesize = adapter->sglen;
 
 
-       /* use HP firmware and bios version encoding */
+       /* use HP firmware and bios version encoding
+          Note: fw_version[0|1] and bios_version[0|1] were originally shifted
+          right 8 bits making them zero. This 0 value was hardcoded to fix
+          sparse warnings. */
        if (adapter->product_info.subsysvid == HP_SUBSYS_VID) {
                sprintf (adapter->fw_version, "%c%d%d.%d%d",
                         adapter->product_info.fw_version[2],
-                        adapter->product_info.fw_version[1] >> 8,
+                        0,
                         adapter->product_info.fw_version[1] & 0x0f,
-                        adapter->product_info.fw_version[0] >> 8,
+                        0,
                         adapter->product_info.fw_version[0] & 0x0f);
                sprintf (adapter->bios_version, "%c%d%d.%d%d",
                         adapter->product_info.bios_version[2],
-                        adapter->product_info.bios_version[1] >> 8,
+                        0,
                         adapter->product_info.bios_version[1] & 0x0f,
-                        adapter->product_info.bios_version[0] >> 8,
+                        0,
                         adapter->product_info.bios_version[0] & 0x0f);
        } else {
                memcpy(adapter->fw_version,
index dd94c7d574fb8b8027f574657cbdc43b46fa906f..e5f416f8042d45620cab8ced05fc56738cc8764a 100644 (file)
@@ -33,9 +33,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "00.00.06.12-rc1"
-#define MEGASAS_RELDATE                                "Oct. 5, 2011"
-#define MEGASAS_EXT_VERSION                    "Wed. Oct. 5 17:00:00 PDT 2011"
+#define MEGASAS_VERSION                                "00.00.06.14-rc1"
+#define MEGASAS_RELDATE                                "Jan. 6, 2012"
+#define MEGASAS_EXT_VERSION                    "Fri. Jan. 6 17:00:00 PDT 2012"
 
 /*
  * Device IDs
@@ -773,7 +773,6 @@ struct megasas_ctrl_info {
 
 #define MFI_OB_INTR_STATUS_MASK                        0x00000002
 #define MFI_POLL_TIMEOUT_SECS                  60
-#define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ/10)
 
 #define MFI_REPLY_1078_MESSAGE_INTERRUPT       0x80000000
 #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT       0x00000001
@@ -1353,7 +1352,6 @@ struct megasas_instance {
        u32 mfiStatus;
        u32 last_seq_num;
 
-       struct timer_list io_completion_timer;
        struct list_head internal_reset_pending_q;
 
        /* Ptr to hba specific information */
index 29a994f9c4f1e6a9c0973ecd3cebe413f4937c7b..8b300be442849336d296768c69a44e126e24a40d 100644 (file)
@@ -18,7 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  *  FILE: megaraid_sas_base.c
- *  Version : v00.00.06.12-rc1
+ *  Version : v00.00.06.14-rc1
  *
  *  Authors: LSI Corporation
  *           Sreenivas Bagalkote
 #include "megaraid_sas_fusion.h"
 #include "megaraid_sas.h"
 
-/*
- * poll_mode_io:1- schedule complete completion from q cmd
- */
-static unsigned int poll_mode_io;
-module_param_named(poll_mode_io, poll_mode_io, int, 0);
-MODULE_PARM_DESC(poll_mode_io,
-       "Complete cmds from IO path, (default=0)");
-
 /*
  * Number of sectors per IO command
  * Will be set in megasas_init_mfi if user does not provide
@@ -1439,11 +1431,6 @@ megasas_build_and_issue_cmd(struct megasas_instance *instance,
 
        instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
                                cmd->frame_count-1, instance->reg_set);
-       /*
-        * Check if we have pend cmds to be completed
-        */
-       if (poll_mode_io && atomic_read(&instance->fw_outstanding))
-               tasklet_schedule(&instance->isr_tasklet);
 
        return 0;
 out_return_cmd:
@@ -3370,47 +3357,6 @@ fail_fw_init:
        return -EINVAL;
 }
 
-/**
- * megasas_start_timer - Initializes a timer object
- * @instance:          Adapter soft state
- * @timer:             timer object to be initialized
- * @fn:                        timer function
- * @interval:          time interval between timer function call
- */
-static inline void
-megasas_start_timer(struct megasas_instance *instance,
-                       struct timer_list *timer,
-                       void *fn, unsigned long interval)
-{
-       init_timer(timer);
-       timer->expires = jiffies + interval;
-       timer->data = (unsigned long)instance;
-       timer->function = fn;
-       add_timer(timer);
-}
-
-/**
- * megasas_io_completion_timer - Timer fn
- * @instance_addr:     Address of adapter soft state
- *
- * Schedules tasklet for cmd completion
- * if poll_mode_io is set
- */
-static void
-megasas_io_completion_timer(unsigned long instance_addr)
-{
-       struct megasas_instance *instance =
-                       (struct megasas_instance *)instance_addr;
-
-       if (atomic_read(&instance->fw_outstanding))
-               tasklet_schedule(&instance->isr_tasklet);
-
-       /* Restart timer */
-       if (poll_mode_io)
-               mod_timer(&instance->io_completion_timer,
-                       jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
-}
-
 static u32
 megasas_init_adapter_mfi(struct megasas_instance *instance)
 {
@@ -3638,11 +3584,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
        tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
                (unsigned long)instance);
 
-       /* Initialize the cmd completion timer */
-       if (poll_mode_io)
-               megasas_start_timer(instance, &instance->io_completion_timer,
-                               megasas_io_completion_timer,
-                               MEGASAS_COMPLETION_TIMER_INTERVAL);
        return 0;
 
 fail_init_adapter:
@@ -4369,9 +4310,6 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
        host = instance->host;
        instance->unload = 1;
 
-       if (poll_mode_io)
-               del_timer_sync(&instance->io_completion_timer);
-
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
 
@@ -4511,12 +4449,6 @@ megasas_resume(struct pci_dev *pdev)
        }
 
        instance->instancet->enable_intr(instance->reg_set);
-
-       /* Initialize the cmd completion timer */
-       if (poll_mode_io)
-               megasas_start_timer(instance, &instance->io_completion_timer,
-                               megasas_io_completion_timer,
-                               MEGASAS_COMPLETION_TIMER_INTERVAL);
        instance->unload = 0;
 
        /*
@@ -4570,9 +4502,6 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
        host = instance->host;
        fusion = instance->ctrl_context;
 
-       if (poll_mode_io)
-               del_timer_sync(&instance->io_completion_timer);
-
        scsi_remove_host(instance->host);
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
@@ -4773,6 +4702,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
        cmd->frame->hdr.context = cmd->index;
        cmd->frame->hdr.pad_0 = 0;
+       cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
+                                  MFI_FRAME_SENSE64);
 
        /*
         * The management interface between applications and the fw uses
@@ -5219,60 +5150,6 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun
 static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
                megasas_sysfs_set_dbg_lvl);
 
-static ssize_t
-megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
-{
-       return sprintf(buf, "%u\n", poll_mode_io);
-}
-
-static ssize_t
-megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
-                               const char *buf, size_t count)
-{
-       int retval = count;
-       int tmp = poll_mode_io;
-       int i;
-       struct megasas_instance *instance;
-
-       if (sscanf(buf, "%u", &poll_mode_io) < 1) {
-               printk(KERN_ERR "megasas: could not set poll_mode_io\n");
-               retval = -EINVAL;
-       }
-
-       /*
-        * Check if poll_mode_io is already set or is same as previous value
-        */
-       if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
-               goto out;
-
-       if (poll_mode_io) {
-               /*
-                * Start timers for all adapters
-                */
-               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-                       instance = megasas_mgmt_info.instance[i];
-                       if (instance) {
-                               megasas_start_timer(instance,
-                                       &instance->io_completion_timer,
-                                       megasas_io_completion_timer,
-                                       MEGASAS_COMPLETION_TIMER_INTERVAL);
-                       }
-               }
-       } else {
-               /*
-                * Delete timers for all adapters
-                */
-               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-                       instance = megasas_mgmt_info.instance[i];
-                       if (instance)
-                               del_timer_sync(&instance->io_completion_timer);
-               }
-       }
-
-out:
-       return retval;
-}
-
 static void
 megasas_aen_polling(struct work_struct *work)
 {
@@ -5502,11 +5379,6 @@ megasas_aen_polling(struct work_struct *work)
        kfree(ev);
 }
 
-
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
-               megasas_sysfs_show_poll_mode_io,
-               megasas_sysfs_set_poll_mode_io);
-
 /**
  * megasas_init - Driver load entry point
  */
@@ -5565,11 +5437,6 @@ static int __init megasas_init(void)
                                  &driver_attr_dbg_lvl);
        if (rval)
                goto err_dcf_dbg_lvl;
-       rval = driver_create_file(&megasas_pci_driver.driver,
-                                 &driver_attr_poll_mode_io);
-       if (rval)
-               goto err_dcf_poll_mode_io;
-
        rval = driver_create_file(&megasas_pci_driver.driver,
                                &driver_attr_support_device_change);
        if (rval)
@@ -5578,10 +5445,6 @@ static int __init megasas_init(void)
        return rval;
 
 err_dcf_support_device_change:
-       driver_remove_file(&megasas_pci_driver.driver,
-                 &driver_attr_poll_mode_io);
-
-err_dcf_poll_mode_io:
        driver_remove_file(&megasas_pci_driver.driver,
                           &driver_attr_dbg_lvl);
 err_dcf_dbg_lvl:
@@ -5606,8 +5469,6 @@ err_pcidrv:
  */
 static void __exit megasas_exit(void)
 {
-       driver_remove_file(&megasas_pci_driver.driver,
-                          &driver_attr_poll_mode_io);
        driver_remove_file(&megasas_pci_driver.driver,
                           &driver_attr_dbg_lvl);
        driver_remove_file(&megasas_pci_driver.driver,
index 5255dd688aca49b807f430ffa26dd80a41fcf42e..294abb0defa66e4b34bb8eacf9d91d534bfe144f 100644 (file)
@@ -282,7 +282,9 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
        else {
                *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
                if ((raid->level >= 5) &&
-                   (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER))
+                   ((instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) ||
+                    (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER &&
+                     raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
                        pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
                else if (raid->level == 1) {
                        /* Get alternate Pd. */
index 22a3ff02e48a419d0e9353d72e53f8d13a3e41f0..bfe68545203ff9123a58f1f9ae896b3b59293811 100644 (file)
 #define QL4_SESS_RECOVERY_TMO          120     /* iSCSI session */
                                                /* recovery timeout */
 
+#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8))
+#define LSW(x) ((uint16_t)(x))
 #define LSDW(x) ((u32)((u64)(x)))
 #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
 
@@ -671,6 +673,7 @@ struct scsi_qla_host {
        uint16_t pri_ddb_idx;
        uint16_t sec_ddb_idx;
        int is_reset;
+       uint16_t temperature;
 };
 
 struct ql4_task_data {
index 1bdfa8120ac888c65c304c28dc3f3aba806ea403..90614f38b55d54541bba90d114d37e1ae4c553d7 100644 (file)
@@ -697,6 +697,9 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
                        writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
                               &ha->reg->ctrl_status);
                        readl(&ha->reg->ctrl_status);
+                       writel(set_rmask(CSR_SCSI_COMPLETION_INTR),
+                              &ha->reg->ctrl_status);
+                       readl(&ha->reg->ctrl_status);
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
                        if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) {
                                DEBUG2(printk("scsi%ld: %s: Get firmware "
index c2593782fbbef8c203148b1661c92a3e1dbe35f6..e1e66a45e4d06f59ab7e35a4b46999d3bba90106 100644 (file)
@@ -219,6 +219,13 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
                ha->mailbox_timeout_count++;
                mbx_sts[0] = (-1);
                set_bit(DPC_RESET_HA, &ha->dpc_flags);
+               if (is_qla8022(ha)) {
+                       ql4_printk(KERN_INFO, ha,
+                                  "disabling pause transmit on port 0 & 1.\n");
+                       qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+                                       CRB_NIU_XG_PAUSE_CTL_P0 |
+                                       CRB_NIU_XG_PAUSE_CTL_P1);
+               }
                goto mbox_exit;
        }
 
index 8d6bc1b2ff17266a45d66dfb923f5c7757cf1493..65253dfbe962b24db546ee83ee8d0ea77a12da83 100644 (file)
@@ -10,6 +10,8 @@
 #include "ql4_def.h"
 #include "ql4_glbl.h"
 
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
 #define MASK(n)                DMA_BIT_MASK(n)
 #define MN_WIN(addr)   (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
 #define OCM_WIN(addr)  (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
@@ -655,27 +657,6 @@ static int qla4_8xxx_pci_is_same_window(struct scsi_qla_host *ha,
        return 0;
 }
 
-#ifndef readq
-static inline __u64 readq(const volatile void __iomem *addr)
-{
-       const volatile u32 __iomem *p = addr;
-       u32 low, high;
-
-       low = readl(p);
-       high = readl(p + 1);
-
-       return low + ((u64)high << 32);
-}
-#endif
-
-#ifndef writeq
-static inline void writeq(__u64 val, volatile void __iomem *addr)
-{
-       writel(val, addr);
-       writel(val >> 32, addr+4);
-}
-#endif
-
 static int qla4_8xxx_pci_mem_read_direct(struct scsi_qla_host *ha,
                u64 off, void *data, int size)
 {
@@ -1875,6 +1856,11 @@ exit:
 int qla4_8xxx_load_risc(struct scsi_qla_host *ha)
 {
        int retval;
+
+       /* clear the interrupt */
+       writel(0, &ha->qla4_8xxx_reg->host_int);
+       readl(&ha->qla4_8xxx_reg->host_int);
+
        retval = qla4_8xxx_device_state_handler(ha);
 
        if (retval == QLA_SUCCESS && !test_bit(AF_INIT_DONE, &ha->flags))
index 35376a1c3f1bc109fb8bea9deb54cec9b7acf0c8..dc45ac92369150eea7821fac2bacc24c8fe11311 100644 (file)
 #define PHAN_PEG_RCV_INITIALIZED       0xff01
 
 /*CRB_RELATED*/
-#define QLA82XX_CRB_BASE       QLA82XX_CAM_RAM(0x200)
-#define QLA82XX_REG(X)         (QLA82XX_CRB_BASE+(X))
-
+#define QLA82XX_CRB_BASE               (QLA82XX_CAM_RAM(0x200))
+#define QLA82XX_REG(X)                 (QLA82XX_CRB_BASE+(X))
 #define CRB_CMDPEG_STATE               QLA82XX_REG(0x50)
 #define CRB_RCVPEG_STATE               QLA82XX_REG(0x13c)
 #define CRB_DMA_SHIFT                  QLA82XX_REG(0xcc)
+#define CRB_TEMP_STATE                 QLA82XX_REG(0x1b4)
+
+#define qla82xx_get_temp_val(x)                ((x) >> 16)
+#define qla82xx_get_temp_state(x)      ((x) & 0xffff)
+#define qla82xx_encode_temp(val, state)        (((val) << 16) | (state))
+
+/*
+ * Temperature control.
+ */
+enum {
+       QLA82XX_TEMP_NORMAL = 0x1,      /* Normal operating range */
+       QLA82XX_TEMP_WARN,      /* Sound alert, temperature getting high */
+       QLA82XX_TEMP_PANIC      /* Fatal error, hardware has shut down. */
+};
+
+#define CRB_NIU_XG_PAUSE_CTL_P0                0x1
+#define CRB_NIU_XG_PAUSE_CTL_P1                0x8
 
 #define QLA82XX_HW_H0_CH_HUB_ADR       0x05
 #define QLA82XX_HW_H1_CH_HUB_ADR       0x0E
index ec393a00c03816f52515fc7e294187a2527e2bf0..ce6d3b7f0c616a3adc14677c27996e99711d4f75 100644 (file)
@@ -35,43 +35,44 @@ static struct kmem_cache *srb_cachep;
 int ql4xdisablesysfsboot = 1;
 module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ql4xdisablesysfsboot,
-               "Set to disable exporting boot targets to sysfs\n"
-               " 0 - Export boot targets\n"
-               " 1 - Do not export boot targets (Default)");
+                " Set to disable exporting boot targets to sysfs.\n"
+                "\t\t  0 - Export boot targets\n"
+                "\t\t  1 - Do not export boot targets (Default)");
 
 int ql4xdontresethba = 0;
 module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ql4xdontresethba,
-               "Don't reset the HBA for driver recovery \n"
-               " 0 - It will reset HBA (Default)\n"
-               " 1 - It will NOT reset HBA");
+                " Don't reset the HBA for driver recovery.\n"
+                "\t\t  0 - It will reset HBA (Default)\n"
+                "\t\t  1 - It will NOT reset HBA");
 
-int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */
+int ql4xextended_error_logging;
 module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ql4xextended_error_logging,
-                "Option to enable extended error logging, "
-                "Default is 0 - no logging, 1 - debug logging");
+                " Option to enable extended error logging.\n"
+                "\t\t  0 - no logging (Default)\n"
+                "\t\t  2 - debug logging");
 
 int ql4xenablemsix = 1;
 module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql4xenablemsix,
-               "Set to enable MSI or MSI-X interrupt mechanism.\n"
-               " 0 = enable INTx interrupt mechanism.\n"
-               " 1 = enable MSI-X interrupt mechanism (Default).\n"
-               " 2 = enable MSI interrupt mechanism.");
+                " Set to enable MSI or MSI-X interrupt mechanism.\n"
+                "\t\t  0 = enable INTx interrupt mechanism.\n"
+                "\t\t  1 = enable MSI-X interrupt mechanism (Default).\n"
+                "\t\t  2 = enable MSI interrupt mechanism.");
 
 #define QL4_DEF_QDEPTH 32
 static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
 module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ql4xmaxqdepth,
-               "Maximum queue depth to report for target devices.\n"
-               " Default: 32.");
+                " Maximum queue depth to report for target devices.\n"
+                "\t\t  Default: 32.");
 
 static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
 module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
 MODULE_PARM_DESC(ql4xsess_recovery_tmo,
                "Target Session Recovery Timeout.\n"
-               " Default: 120 sec.");
+               "\t\t  Default: 120 sec.");
 
 static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
 /*
@@ -1630,7 +1631,9 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
 
        /* Update timers after login */
        ddb_entry->default_relogin_timeout =
-                               le16_to_cpu(fw_ddb_entry->def_timeout);
+               (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) &&
+                (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ?
+                le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV;
        ddb_entry->default_time2wait =
                                le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
 
@@ -1969,6 +1972,42 @@ mem_alloc_error_exit:
        return QLA_ERROR;
 }
 
+/**
+ * qla4_8xxx_check_temp - Check the ISP82XX temperature.
+ * @ha: adapter block pointer.
+ *
+ * Note: The caller should not hold the idc lock.
+ **/
+static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)
+{
+       uint32_t temp, temp_state, temp_val;
+       int status = QLA_SUCCESS;
+
+       temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE);
+
+       temp_state = qla82xx_get_temp_state(temp);
+       temp_val = qla82xx_get_temp_val(temp);
+
+       if (temp_state == QLA82XX_TEMP_PANIC) {
+               ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C"
+                          " exceeds maximum allowed. Hardware has been shut"
+                          " down.\n", temp_val);
+               status = QLA_ERROR;
+       } else if (temp_state == QLA82XX_TEMP_WARN) {
+               if (ha->temperature == QLA82XX_TEMP_NORMAL)
+                       ql4_printk(KERN_WARNING, ha, "Device temperature %d"
+                                  " degrees C exceeds operating range."
+                                  " Immediate action needed.\n", temp_val);
+       } else {
+               if (ha->temperature == QLA82XX_TEMP_WARN)
+                       ql4_printk(KERN_INFO, ha, "Device temperature is"
+                                  " now %d degrees C in normal range.\n",
+                                  temp_val);
+       }
+       ha->temperature = temp_state;
+       return status;
+}
+
 /**
  * qla4_8xxx_check_fw_alive  - Check firmware health
  * @ha: Pointer to host adapter structure.
@@ -2040,7 +2079,16 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
            test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
            test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {
                dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-               if (dev_state == QLA82XX_DEV_NEED_RESET &&
+
+               if (qla4_8xxx_check_temp(ha)) {
+                       ql4_printk(KERN_INFO, ha, "disabling pause"
+                                  " transmit on port 0 & 1.\n");
+                       qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+                                       CRB_NIU_XG_PAUSE_CTL_P0 |
+                                       CRB_NIU_XG_PAUSE_CTL_P1);
+                       set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
+                       qla4xxx_wake_dpc(ha);
+               } else if (dev_state == QLA82XX_DEV_NEED_RESET &&
                    !test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
                        if (!ql4xdontresethba) {
                                ql4_printk(KERN_INFO, ha, "%s: HW State: "
@@ -2057,9 +2105,21 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
                } else  {
                        /* Check firmware health */
                        if (qla4_8xxx_check_fw_alive(ha)) {
+                               ql4_printk(KERN_INFO, ha, "disabling pause"
+                                          " transmit on port 0 & 1.\n");
+                               qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+                                               CRB_NIU_XG_PAUSE_CTL_P0 |
+                                               CRB_NIU_XG_PAUSE_CTL_P1);
                                halt_status = qla4_8xxx_rd_32(ha,
                                                QLA82XX_PEG_HALT_STATUS1);
 
+                               if (LSW(MSB(halt_status)) == 0x67)
+                                       ql4_printk(KERN_ERR, ha, "%s:"
+                                                  " Firmware aborted with"
+                                                  " error code 0x00006700."
+                                                  " Device is being reset\n",
+                                                  __func__);
+
                                /* Since we cannot change dev_state in interrupt
                                 * context, set appropriate DPC flag then wakeup
                                 * DPC */
@@ -2078,7 +2138,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
        }
 }
 
-void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
+static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
 {
        struct iscsi_session *sess;
        struct ddb_entry *ddb_entry;
@@ -3826,16 +3886,14 @@ exit_check:
        return ret;
 }
 
-static void qla4xxx_free_nt_list(struct list_head *list_nt)
+static void qla4xxx_free_ddb_list(struct list_head *list_ddb)
 {
-       struct qla_ddb_index  *nt_ddb_idx, *nt_ddb_idx_tmp;
+       struct qla_ddb_index  *ddb_idx, *ddb_idx_tmp;
 
-       /* Free up the normaltargets list */
-       list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
-               list_del_init(&nt_ddb_idx->list);
-               vfree(nt_ddb_idx);
+       list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
+               list_del_init(&ddb_idx->list);
+               vfree(ddb_idx);
        }
-
 }
 
 static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
@@ -3884,6 +3942,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
 static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
                                          struct ddb_entry *ddb_entry)
 {
+       uint16_t def_timeout;
+
        ddb_entry->ddb_type = FLASH_DDB;
        ddb_entry->fw_ddb_index = INVALID_ENTRY;
        ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
@@ -3894,9 +3954,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
        atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
        atomic_set(&ddb_entry->relogin_timer, 0);
        atomic_set(&ddb_entry->relogin_retry_count, 0);
-
+       def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
        ddb_entry->default_relogin_timeout =
-               le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
+               (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ?
+               def_timeout : LOGIN_TOV;
        ddb_entry->default_time2wait =
                le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
 }
@@ -3934,7 +3995,6 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
                            ip_state == IP_ADDRSTATE_DEPRICATED ||
                            ip_state == IP_ADDRSTATE_DISABLING)
                                ip_idx[idx] = -1;
-
                }
 
                /* Break if all IP states checked */
@@ -3947,58 +4007,37 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
        } while (time_after(wtime, jiffies));
 }
 
-void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
+static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
+                                 struct list_head *list_st)
 {
+       struct qla_ddb_index  *st_ddb_idx;
        int max_ddbs;
+       int fw_idx_size;
+       struct dev_db_entry *fw_ddb_entry;
+       dma_addr_t fw_ddb_dma;
        int ret;
        uint32_t idx = 0, next_idx = 0;
        uint32_t state = 0, conn_err = 0;
-       uint16_t conn_id;
-       struct dev_db_entry *fw_ddb_entry;
-       struct ddb_entry *ddb_entry = NULL;
-       dma_addr_t fw_ddb_dma;
-       struct iscsi_cls_session *cls_sess;
-       struct iscsi_session *sess;
-       struct iscsi_cls_conn *cls_conn;
-       struct iscsi_endpoint *ep;
-       uint16_t cmds_max = 32, tmo = 0;
-       uint32_t initial_cmdsn = 0;
-       struct list_head list_st, list_nt; /* List of sendtargets */
-       struct qla_ddb_index  *st_ddb_idx, *st_ddb_idx_tmp;
-       int fw_idx_size;
-       unsigned long wtime;
-       struct qla_ddb_index  *nt_ddb_idx;
-
-       if (!test_bit(AF_LINK_UP, &ha->flags)) {
-               set_bit(AF_BUILD_DDB_LIST, &ha->flags);
-               ha->is_reset = is_reset;
-               return;
-       }
-       max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
-                                    MAX_DEV_DB_ENTRIES;
+       uint16_t conn_id = 0;
 
        fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
                                      &fw_ddb_dma);
        if (fw_ddb_entry == NULL) {
                DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
-               goto exit_ddb_list;
+               goto exit_st_list;
        }
 
-       INIT_LIST_HEAD(&list_st);
-       INIT_LIST_HEAD(&list_nt);
+       max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+                                    MAX_DEV_DB_ENTRIES;
        fw_idx_size = sizeof(struct qla_ddb_index);
 
        for (idx = 0; idx < max_ddbs; idx = next_idx) {
-               ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
-                                             fw_ddb_dma, NULL,
-                                             &next_idx, &state, &conn_err,
-                                             NULL, &conn_id);
+               ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
+                                             NULL, &next_idx, &state,
+                                             &conn_err, NULL, &conn_id);
                if (ret == QLA_ERROR)
                        break;
 
-               if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
-                       goto continue_next_st;
-
                /* Check if ST, add to the list_st */
                if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
                        goto continue_next_st;
@@ -4009,59 +4048,155 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
 
                st_ddb_idx->fw_ddb_idx = idx;
 
-               list_add_tail(&st_ddb_idx->list, &list_st);
+               list_add_tail(&st_ddb_idx->list, list_st);
 continue_next_st:
                if (next_idx == 0)
                        break;
        }
 
-       /* Before issuing conn open mbox, ensure all IPs states are configured
-        * Note, conn open fails if IPs are not configured
+exit_st_list:
+       if (fw_ddb_entry)
+               dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+}
+
+/**
+ * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list
+ * @ha: pointer to adapter structure
+ * @list_ddb: List from which failed ddb to be removed
+ *
+ * Iterate over the list of DDBs and find and remove DDBs that are either in
+ * no connection active state or failed state
+ **/
+static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
+                                     struct list_head *list_ddb)
+{
+       struct qla_ddb_index  *ddb_idx, *ddb_idx_tmp;
+       uint32_t next_idx = 0;
+       uint32_t state = 0, conn_err = 0;
+       int ret;
+
+       list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
+               ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,
+                                             NULL, 0, NULL, &next_idx, &state,
+                                             &conn_err, NULL, NULL);
+               if (ret == QLA_ERROR)
+                       continue;
+
+               if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+                   state == DDB_DS_SESSION_FAILED) {
+                       list_del_init(&ddb_idx->list);
+                       vfree(ddb_idx);
+               }
+       }
+}
+
+static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
+                                  struct dev_db_entry *fw_ddb_entry,
+                                  int is_reset)
+{
+       struct iscsi_cls_session *cls_sess;
+       struct iscsi_session *sess;
+       struct iscsi_cls_conn *cls_conn;
+       struct iscsi_endpoint *ep;
+       uint16_t cmds_max = 32;
+       uint16_t conn_id = 0;
+       uint32_t initial_cmdsn = 0;
+       int ret = QLA_SUCCESS;
+
+       struct ddb_entry *ddb_entry = NULL;
+
+       /* Create session object, with INVALID_ENTRY,
+        * the targer_id would get set when we issue the login
         */
-       qla4xxx_wait_for_ip_configuration(ha);
+       cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,
+                                      cmds_max, sizeof(struct ddb_entry),
+                                      sizeof(struct ql4_task_data),
+                                      initial_cmdsn, INVALID_ENTRY);
+       if (!cls_sess) {
+               ret = QLA_ERROR;
+               goto exit_setup;
+       }
 
-       /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
-       list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
-               qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
+       /*
+        * so calling module_put function to decrement the
+        * reference count.
+        **/
+       module_put(qla4xxx_iscsi_transport.owner);
+       sess = cls_sess->dd_data;
+       ddb_entry = sess->dd_data;
+       ddb_entry->sess = cls_sess;
+
+       cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
+       memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
+              sizeof(struct dev_db_entry));
+
+       qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
+
+       cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
+
+       if (!cls_conn) {
+               ret = QLA_ERROR;
+               goto exit_setup;
        }
 
-       /* Wait to ensure all sendtargets are done for min 12 sec wait */
-       tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
-       DEBUG2(ql4_printk(KERN_INFO, ha,
-                         "Default time to wait for build ddb %d\n", tmo));
+       ddb_entry->conn = cls_conn;
 
-       wtime = jiffies + (HZ * tmo);
-       do {
-               list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
-                                        list) {
-                       ret = qla4xxx_get_fwddb_entry(ha,
-                                                     st_ddb_idx->fw_ddb_idx,
-                                                     NULL, 0, NULL, &next_idx,
-                                                     &state, &conn_err, NULL,
-                                                     NULL);
-                       if (ret == QLA_ERROR)
-                               continue;
+       /* Setup ep, for displaying attributes in sysfs */
+       ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
+       if (ep) {
+               ep->conn = cls_conn;
+               cls_conn->ep = ep;
+       } else {
+               DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));
+               ret = QLA_ERROR;
+               goto exit_setup;
+       }
 
-                       if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
-                           state == DDB_DS_SESSION_FAILED) {
-                               list_del_init(&st_ddb_idx->list);
-                               vfree(st_ddb_idx);
-                       }
-               }
-               schedule_timeout_uninterruptible(HZ / 10);
-       } while (time_after(wtime, jiffies));
+       /* Update sess/conn params */
+       qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
 
-       /* Free up the sendtargets list */
-       list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
-               list_del_init(&st_ddb_idx->list);
-               vfree(st_ddb_idx);
+       if (is_reset == RESET_ADAPTER) {
+               iscsi_block_session(cls_sess);
+               /* Use the relogin path to discover new devices
+                *  by short-circuting the logic of setting
+                *  timer to relogin - instead set the flags
+                *  to initiate login right away.
+                */
+               set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
+               set_bit(DF_RELOGIN, &ddb_entry->flags);
        }
 
+exit_setup:
+       return ret;
+}
+
+static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
+                                 struct list_head *list_nt, int is_reset)
+{
+       struct dev_db_entry *fw_ddb_entry;
+       dma_addr_t fw_ddb_dma;
+       int max_ddbs;
+       int fw_idx_size;
+       int ret;
+       uint32_t idx = 0, next_idx = 0;
+       uint32_t state = 0, conn_err = 0;
+       uint16_t conn_id = 0;
+       struct qla_ddb_index  *nt_ddb_idx;
+
+       fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
+                                     &fw_ddb_dma);
+       if (fw_ddb_entry == NULL) {
+               DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
+               goto exit_nt_list;
+       }
+       max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+                                    MAX_DEV_DB_ENTRIES;
+       fw_idx_size = sizeof(struct qla_ddb_index);
+
        for (idx = 0; idx < max_ddbs; idx = next_idx) {
-               ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
-                                             fw_ddb_dma, NULL,
-                                             &next_idx, &state, &conn_err,
-                                             NULL, &conn_id);
+               ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
+                                             NULL, &next_idx, &state,
+                                             &conn_err, NULL, &conn_id);
                if (ret == QLA_ERROR)
                        break;
 
@@ -4072,107 +4207,113 @@ continue_next_st:
                if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
                        goto continue_next_nt;
 
-               if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
-                   state == DDB_DS_SESSION_FAILED) {
-                       DEBUG2(ql4_printk(KERN_INFO, ha,
-                                         "Adding  DDB to session = 0x%x\n",
-                                         idx));
-                       if (is_reset == INIT_ADAPTER) {
-                               nt_ddb_idx = vmalloc(fw_idx_size);
-                               if (!nt_ddb_idx)
-                                       break;
-
-                               nt_ddb_idx->fw_ddb_idx = idx;
-
-                               memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
-                                      sizeof(struct dev_db_entry));
-
-                               if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
-                                               fw_ddb_entry) == QLA_SUCCESS) {
-                                       vfree(nt_ddb_idx);
-                                       goto continue_next_nt;
-                               }
-                               list_add_tail(&nt_ddb_idx->list, &list_nt);
-                       } else if (is_reset == RESET_ADAPTER) {
-                               if (qla4xxx_is_session_exists(ha,
-                                                  fw_ddb_entry) == QLA_SUCCESS)
-                                       goto continue_next_nt;
-                       }
+               if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||
+                   state == DDB_DS_SESSION_FAILED))
+                       goto continue_next_nt;
 
-                       /* Create session object, with INVALID_ENTRY,
-                        * the targer_id would get set when we issue the login
-                        */
-                       cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
-                                               ha->host, cmds_max,
-                                               sizeof(struct ddb_entry),
-                                               sizeof(struct ql4_task_data),
-                                               initial_cmdsn, INVALID_ENTRY);
-                       if (!cls_sess)
-                               goto exit_ddb_list;
+               DEBUG2(ql4_printk(KERN_INFO, ha,
+                                 "Adding  DDB to session = 0x%x\n", idx));
+               if (is_reset == INIT_ADAPTER) {
+                       nt_ddb_idx = vmalloc(fw_idx_size);
+                       if (!nt_ddb_idx)
+                               break;
 
-                       /*
-                        * iscsi_session_setup increments the driver reference
-                        * count which wouldn't let the driver to be unloaded.
-                        * so calling module_put function to decrement the
-                        * reference count.
-                        **/
-                       module_put(qla4xxx_iscsi_transport.owner);
-                       sess = cls_sess->dd_data;
-                       ddb_entry = sess->dd_data;
-                       ddb_entry->sess = cls_sess;
+                       nt_ddb_idx->fw_ddb_idx = idx;
 
-                       cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
-                       memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
+                       memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
                               sizeof(struct dev_db_entry));
 
-                       qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
-
-                       cls_conn = iscsi_conn_setup(cls_sess,
-                                                   sizeof(struct qla_conn),
-                                                   conn_id);
-                       if (!cls_conn)
-                               goto exit_ddb_list;
-
-                       ddb_entry->conn = cls_conn;
-
-                       /* Setup ep, for displaying attributes in sysfs */
-                       ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
-                       if (ep) {
-                               ep->conn = cls_conn;
-                               cls_conn->ep = ep;
-                       } else {
-                               DEBUG2(ql4_printk(KERN_ERR, ha,
-                                                 "Unable to get ep\n"));
-                       }
-
-                       /* Update sess/conn params */
-                       qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
-                                                cls_conn);
-
-                       if (is_reset == RESET_ADAPTER) {
-                               iscsi_block_session(cls_sess);
-                               /* Use the relogin path to discover new devices
-                                *  by short-circuting the logic of setting
-                                *  timer to relogin - instead set the flags
-                                *  to initiate login right away.
-                                */
-                               set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
-                               set_bit(DF_RELOGIN, &ddb_entry->flags);
+                       if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
+                                       fw_ddb_entry) == QLA_SUCCESS) {
+                               vfree(nt_ddb_idx);
+                               goto continue_next_nt;
                        }
+                       list_add_tail(&nt_ddb_idx->list, list_nt);
+               } else if (is_reset == RESET_ADAPTER) {
+                       if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
+                                                               QLA_SUCCESS)
+                               goto continue_next_nt;
                }
+
+               ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
+               if (ret == QLA_ERROR)
+                       goto exit_nt_list;
+
 continue_next_nt:
                if (next_idx == 0)
                        break;
        }
-exit_ddb_list:
-       qla4xxx_free_nt_list(&list_nt);
+
+exit_nt_list:
        if (fw_ddb_entry)
                dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+}
+
+/**
+ * qla4xxx_build_ddb_list - Build ddb list and setup sessions
+ * @ha: pointer to adapter structure
+ * @is_reset: Is this init path or reset path
+ *
+ * Create a list of sendtargets (st) from firmware DDBs, issue send targets
+ * using connection open, then create the list of normal targets (nt)
+ * from firmware DDBs. Based on the list of nt setup session and connection
+ * objects.
+ **/
+void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
+{
+       uint16_t tmo = 0;
+       struct list_head list_st, list_nt;
+       struct qla_ddb_index  *st_ddb_idx, *st_ddb_idx_tmp;
+       unsigned long wtime;
+
+       if (!test_bit(AF_LINK_UP, &ha->flags)) {
+               set_bit(AF_BUILD_DDB_LIST, &ha->flags);
+               ha->is_reset = is_reset;
+               return;
+       }
+
+       INIT_LIST_HEAD(&list_st);
+       INIT_LIST_HEAD(&list_nt);
+
+       qla4xxx_build_st_list(ha, &list_st);
+
+       /* Before issuing conn open mbox, ensure all IPs states are configured
+        * Note, conn open fails if IPs are not configured
+        */
+       qla4xxx_wait_for_ip_configuration(ha);
+
+       /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
+       list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
+               qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
+       }
+
+       /* Wait to ensure all sendtargets are done for min 12 sec wait */
+       tmo = ((ha->def_timeout > LOGIN_TOV) &&
+              (ha->def_timeout < LOGIN_TOV * 10) ?
+              ha->def_timeout : LOGIN_TOV);
+
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+                         "Default time to wait for build ddb %d\n", tmo));
+
+       wtime = jiffies + (HZ * tmo);
+       do {
+               if (list_empty(&list_st))
+                       break;
+
+               qla4xxx_remove_failed_ddb(ha, &list_st);
+               schedule_timeout_uninterruptible(HZ / 10);
+       } while (time_after(wtime, jiffies));
+
+       /* Free up the sendtargets list */
+       qla4xxx_free_ddb_list(&list_st);
+
+       qla4xxx_build_nt_list(ha, &list_nt, is_reset);
+
+       qla4xxx_free_ddb_list(&list_nt);
 
        qla4xxx_free_ddb_index(ha);
 }
 
-
 /**
  * qla4xxx_probe_adapter - callback function to probe HBA
  * @pdev: pointer to pci_dev structure
index 26a3fa34a33c0594c3dfd4fa78f73c75db0fb28c..133989b3a9f4da0d7deed83682c6924c3a654330 100644 (file)
@@ -5,4 +5,4 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION "5.02.00-k10"
+#define QLA4XXX_DRIVER_VERSION "5.02.00-k12"
index f85cfa6c47b5212982bcbfcd9065936c27360f3d..b2c95dbe9d651d3a82b9e7a269ec3b5bd7e7c167 100644 (file)
@@ -1316,15 +1316,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
        }
 
        if (scsi_target_is_busy(starget)) {
-               if (list_empty(&sdev->starved_entry))
-                       list_add_tail(&sdev->starved_entry,
-                                     &shost->starved_list);
+               list_move_tail(&sdev->starved_entry, &shost->starved_list);
                return 0;
        }
 
-       /* We're OK to process the command, so we can't be starved */
-       if (!list_empty(&sdev->starved_entry))
-               list_del_init(&sdev->starved_entry);
        return 1;
 }
 
index 1b214910b71414804f6d0c6dee0932ead1f98156..f59d4a05ecd74168910790d2051673508d3a40e4 100644 (file)
@@ -3048,7 +3048,8 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
 
                spin_lock_irqsave(shost->host_lock, flags);
                rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
-                                 FC_RPORT_DEVLOSS_PENDING);
+                                 FC_RPORT_DEVLOSS_PENDING |
+                                 FC_RPORT_DEVLOSS_CALLBK_DONE);
                spin_unlock_irqrestore(shost->host_lock, flags);
 
                /* ensure any stgt delete functions are done */
index 02d99982a74d9048edfb73359ed2e38d08b163f8..eacd46bb36b95fe2b5caf6e82f3940427a250910 100644 (file)
@@ -2368,16 +2368,15 @@ static ssize_t
 sg_proc_write_adio(struct file *filp, const char __user *buffer,
                   size_t count, loff_t *off)
 {
-       int num;
-       char buff[11];
+       int err;
+       unsigned long num;
 
        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
                return -EACCES;
-       num = (count < 10) ? count : 10;
-       if (copy_from_user(buff, buffer, num))
-               return -EFAULT;
-       buff[num] = '\0';
-       sg_allow_dio = simple_strtoul(buff, NULL, 10) ? 1 : 0;
+       err = kstrtoul_from_user(buffer, count, 0, &num);
+       if (err)
+               return err;
+       sg_allow_dio = num ? 1 : 0;
        return count;
 }
 
@@ -2390,17 +2389,15 @@ static ssize_t
 sg_proc_write_dressz(struct file *filp, const char __user *buffer,
                     size_t count, loff_t *off)
 {
-       int num;
+       int err;
        unsigned long k = ULONG_MAX;
-       char buff[11];
 
        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
                return -EACCES;
-       num = (count < 10) ? count : 10;
-       if (copy_from_user(buff, buffer, num))
-               return -EFAULT;
-       buff[num] = '\0';
-       k = simple_strtoul(buff, NULL, 10);
+
+       err = kstrtoul_from_user(buffer, count, 0, &k);
+       if (err)
+               return err;
        if (k <= 1048576) {     /* limit "big buff" to 1 MB */
                sg_big_buff = k;
                return count;
index b4543f575f466fc3c7fed5f3edad05be9595d0cd..36d1ed7817ebf9d52631c970023d31b31ff494e0 100644 (file)
@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
        struct sym_lcb *lp = sym_lp(tp, sdev->lun);
        unsigned long flags;
 
+       /* if slave_alloc returned before allocating a sym_lcb, return */
+       if (!lp)
+               return;
+
        spin_lock_irqsave(np->s.host->host_lock, flags);
 
        if (lp->busy_itlq || lp->busy_itl) {
index 3f9a47ec67dc814764bbee0d22bdd03f7680400a..8293658e7cf910d12942ff0581a7f50735256c92 100644 (file)
@@ -299,7 +299,7 @@ config SPI_S3C24XX_FIQ
 
 config SPI_S3C64XX
        tristate "Samsung S3C64XX series type SPI"
-       depends on (ARCH_S3C64XX || ARCH_S5P64X0)
+       depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
        select S3C64XX_DMA if ARCH_S3C64XX
        help
          SPI driver for Samsung S3C64XX and newer SoCs.
index e743a45ee92c265bd8a2e13ecec9f98cf3eb926c..8418eb03665121db4a6caf809ea8efc4f12b170c 100644 (file)
@@ -131,7 +131,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        rxchan = dws->rxchan;
 
        /* 2. Prepare the TX dma transfer */
-       txconf.direction = DMA_TO_DEVICE;
+       txconf.direction = DMA_MEM_TO_DEV;
        txconf.dst_addr = dws->dma_addr;
        txconf.dst_maxburst = LNW_DMA_MSIZE_16;
        txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -147,13 +147,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        txdesc = txchan->device->device_prep_slave_sg(txchan,
                                &dws->tx_sgl,
                                1,
-                               DMA_TO_DEVICE,
+                               DMA_MEM_TO_DEV,
                                DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
        txdesc->callback = dw_spi_dma_done;
        txdesc->callback_param = dws;
 
        /* 3. Prepare the RX dma transfer */
-       rxconf.direction = DMA_FROM_DEVICE;
+       rxconf.direction = DMA_DEV_TO_MEM;
        rxconf.src_addr = dws->dma_addr;
        rxconf.src_maxburst = LNW_DMA_MSIZE_16;
        rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -169,7 +169,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
                                &dws->rx_sgl,
                                1,
-                               DMA_FROM_DEVICE,
+                               DMA_DEV_TO_MEM,
                                DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
        rxdesc->callback = dw_spi_dma_done;
        rxdesc->callback_param = dws;
index 0a282e5fcc9c3fe4931a871acd6d89708162bd0d..d46e55c720b7f71717d5772b034c5b7f3e159dc4 100644 (file)
@@ -551,6 +551,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
        struct dma_async_tx_descriptor *txd;
        enum dma_slave_buswidth buswidth;
        struct dma_slave_config conf;
+       enum dma_transfer_direction slave_dirn;
        struct scatterlist *sg;
        struct sg_table *sgt;
        struct dma_chan *chan;
@@ -573,6 +574,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
 
                conf.src_addr = espi->sspdr_phys;
                conf.src_addr_width = buswidth;
+               slave_dirn = DMA_DEV_TO_MEM;
        } else {
                chan = espi->dma_tx;
                buf = t->tx_buf;
@@ -580,6 +582,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
 
                conf.dst_addr = espi->sspdr_phys;
                conf.dst_addr_width = buswidth;
+               slave_dirn = DMA_MEM_TO_DEV;
        }
 
        ret = dmaengine_slave_config(chan, &conf);
@@ -631,7 +634,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
                return ERR_PTR(-ENOMEM);
 
        txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
-                                                dir, DMA_CTRL_ACK);
+                                                slave_dirn, DMA_CTRL_ACK);
        if (!txd) {
                dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
                return ERR_PTR(-ENOMEM);
@@ -979,7 +982,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
        dma_cap_set(DMA_SLAVE, mask);
 
        espi->dma_rx_data.port = EP93XX_DMA_SSP;
-       espi->dma_rx_data.direction = DMA_FROM_DEVICE;
+       espi->dma_rx_data.direction = DMA_DEV_TO_MEM;
        espi->dma_rx_data.name = "ep93xx-spi-rx";
 
        espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
@@ -990,7 +993,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
        }
 
        espi->dma_tx_data.port = EP93XX_DMA_SSP;
-       espi->dma_tx_data.direction = DMA_TO_DEVICE;
+       espi->dma_tx_data.direction = DMA_MEM_TO_DEV;
        espi->dma_tx_data.name = "ep93xx-spi-tx";
 
        espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
index f1f5efbc3404aefc4aa68dba8ded5a4c72275bdc..2f9cb43a239870b6db396b8507fb6a67893f1f37 100644 (file)
@@ -900,11 +900,11 @@ static int configure_dma(struct pl022 *pl022)
 {
        struct dma_slave_config rx_conf = {
                .src_addr = SSP_DR(pl022->phybase),
-               .direction = DMA_FROM_DEVICE,
+               .direction = DMA_DEV_TO_MEM,
        };
        struct dma_slave_config tx_conf = {
                .dst_addr = SSP_DR(pl022->phybase),
-               .direction = DMA_TO_DEVICE,
+               .direction = DMA_MEM_TO_DEV,
        };
        unsigned int pages;
        int ret;
@@ -1041,7 +1041,7 @@ static int configure_dma(struct pl022 *pl022)
        rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
                                      pl022->sgt_rx.sgl,
                                      rx_sglen,
-                                     DMA_FROM_DEVICE,
+                                     DMA_DEV_TO_MEM,
                                      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!rxdesc)
                goto err_rxdesc;
@@ -1049,7 +1049,7 @@ static int configure_dma(struct pl022 *pl022)
        txdesc = txchan->device->device_prep_slave_sg(txchan,
                                      pl022->sgt_tx.sgl,
                                      tx_sglen,
-                                     DMA_TO_DEVICE,
+                                     DMA_MEM_TO_DEV,
                                      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!txdesc)
                goto err_txdesc;
index 7086583b910708e80cf1b133187eb9be236ee4ff..10182eb500681719fc0f4db5e017c76d56f60370 100644 (file)
@@ -1079,7 +1079,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
        }
        sg = dma->sg_rx_p;
        desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg,
-                                       num, DMA_FROM_DEVICE,
+                                       num, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc_rx) {
                dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
@@ -1124,7 +1124,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
        }
        sg = dma->sg_tx_p;
        desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx,
-                                       sg, num, DMA_TO_DEVICE,
+                                       sg, num, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc_tx) {
                dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
@@ -1720,7 +1720,7 @@ static int pch_spi_resume(struct pci_dev *pdev)
 
 #endif
 
-static struct pci_driver pch_spi_pcidev = {
+static struct pci_driver pch_spi_pcidev_driver = {
        .name = "pch_spi",
        .id_table = pch_spi_pcidev_id,
        .probe = pch_spi_probe,
@@ -1736,7 +1736,7 @@ static int __init pch_spi_init(void)
        if (ret)
                return ret;
 
-       ret = pci_register_driver(&pch_spi_pcidev);
+       ret = pci_register_driver(&pch_spi_pcidev_driver);
        if (ret)
                return ret;
 
@@ -1746,7 +1746,7 @@ module_init(pch_spi_init);
 
 static void __exit pch_spi_exit(void)
 {
-       pci_unregister_driver(&pch_spi_pcidev);
+       pci_unregister_driver(&pch_spi_pcidev_driver);
        platform_driver_unregister(&pch_spi_pd_driver);
 }
 module_exit(pch_spi_exit);
index 520e8286db28f92cee618acdbaa00a310e5d41ab..49d209173f55b1de99e306dc105c7ebd5e52c1b5 100644 (file)
@@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
        u32 tmp;
 
        /* We do only have one cardbus device behind the bridge. */
-       if (pc->cardbusmode && (dev >= 1))
+       if (pc->cardbusmode && (dev > 1))
                goto out;
 
        if (bus == 0) {
index 21e2f4b87f1421f3780239543c2a90b1733ebb1c..9e6347249783d480b8051f85e84484be51d80b99 100644 (file)
@@ -60,8 +60,6 @@ source "drivers/staging/rts5139/Kconfig"
 
 source "drivers/staging/frontier/Kconfig"
 
-source "drivers/staging/pohmelfs/Kconfig"
-
 source "drivers/staging/phison/Kconfig"
 
 source "drivers/staging/line6/Kconfig"
@@ -120,8 +118,6 @@ source "drivers/staging/cptm1217/Kconfig"
 
 source "drivers/staging/ste_rmi4/Kconfig"
 
-source "drivers/staging/gma500/Kconfig"
-
 source "drivers/staging/mei/Kconfig"
 
 source "drivers/staging/nvec/Kconfig"
index 7c5808d7212d926c26dca0610c1d420657d0d988..943e14830753e8960dee1ab5a22a2d064f4038fb 100644 (file)
@@ -22,7 +22,6 @@ obj-$(CONFIG_R8712U)          += rtl8712/
 obj-$(CONFIG_RTS_PSTOR)                += rts_pstor/
 obj-$(CONFIG_RTS5139)          += rts5139/
 obj-$(CONFIG_TRANZPORT)                += frontier/
-obj-$(CONFIG_POHMELFS)         += pohmelfs/
 obj-$(CONFIG_IDE_PHISON)       += phison/
 obj-$(CONFIG_LINE6_USB)                += line6/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)      += serqt_usb2/
@@ -52,7 +51,6 @@ obj-$(CONFIG_FT1000)          += ft1000/
 obj-$(CONFIG_SPEAKUP)          += speakup/
 obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217)      += cptm1217/
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)   += ste_rmi4/
-obj-$(CONFIG_DRM_PSB)          += gma500/
 obj-$(CONFIG_INTEL_MEI)                += mei/
 obj-$(CONFIG_MFD_NVEC)         += nvec/
 obj-$(CONFIG_DRM_OMAP)         += omapdrm/
index becf711117efffb56afda428d38ed4dc5428c9df..fef3580ce8de023b1cf940556eb0a7b2cb90f777 100644 (file)
@@ -27,6 +27,7 @@ config ANDROID_LOGGER
 
 config ANDROID_RAM_CONSOLE
        bool "Android RAM buffer console"
+       depends on !S390 && !UML
        default n
 
 config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
@@ -99,10 +100,6 @@ config ANDROID_LOW_MEMORY_KILLER
        ---help---
          Register processes to be killed when memory is low
 
-config ANDROID_PMEM
-       bool "Android pmem allocator"
-       depends on ARM
-
 source "drivers/staging/android/switch/Kconfig"
 
 endif # if ANDROID
index eaed1ff64f0f74a286480c00d9535b8ccdc39846..5fcc24ffdd582e3a6ecf0495ada789033fc837de 100644 (file)
@@ -5,5 +5,4 @@ obj-$(CONFIG_ANDROID_RAM_CONSOLE)       += ram_console.o
 obj-$(CONFIG_ANDROID_TIMED_OUTPUT)     += timed_output.o
 obj-$(CONFIG_ANDROID_TIMED_GPIO)       += timed_gpio.o
 obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER)        += lowmemorykiller.o
-obj-$(CONFIG_ANDROID_PMEM)             += pmem.o
 obj-$(CONFIG_ANDROID_SWITCH)           += switch/
diff --git a/drivers/staging/android/android_pmem.h b/drivers/staging/android/android_pmem.h
deleted file mode 100644 (file)
index f633621..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* include/linux/android_pmem.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 _ANDROID_PMEM_H_
-#define _ANDROID_PMEM_H_
-
-#define PMEM_IOCTL_MAGIC 'p'
-#define PMEM_GET_PHYS          _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
-#define PMEM_MAP               _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
-#define PMEM_GET_SIZE          _IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
-#define PMEM_UNMAP             _IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
-/* This ioctl will allocate pmem space, backing the file, it will fail
- * if the file already has an allocation, pass it the len as the argument
- * to the ioctl */
-#define PMEM_ALLOCATE          _IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
-/* This will connect a one pmem file to another, pass the file that is already
- * backed in memory as the argument to the ioctl
- */
-#define PMEM_CONNECT           _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
-/* Returns the total size of the pmem region it is sent to as a pmem_region
- * struct (with offset set to 0). 
- */
-#define PMEM_GET_TOTAL_SIZE    _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
-#define PMEM_CACHE_FLUSH       _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
-
-struct android_pmem_platform_data
-{
-       const char* name;
-       /* starting physical address of memory region */
-       unsigned long start;
-       /* size of memory region */
-       unsigned long size;
-       /* set to indicate the region should not be managed with an allocator */
-       unsigned no_allocator;
-       /* set to indicate maps of this region should be cached, if a mix of
-        * cached and uncached is desired, set this and open the device with
-        * O_SYNC to get an uncached region */
-       unsigned cached;
-       /* The MSM7k has bits to enable a write buffer in the bus controller*/
-       unsigned buffered;
-};
-
-struct pmem_region {
-       unsigned long offset;
-       unsigned long len;
-};
-
-#ifdef CONFIG_ANDROID_PMEM
-int is_pmem_file(struct file *file);
-int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
-                 unsigned long *end, struct file **filp);
-int get_pmem_user_addr(struct file *file, unsigned long *start,
-                      unsigned long *end);
-void put_pmem_file(struct file* file);
-void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
-int pmem_setup(struct android_pmem_platform_data *pdata,
-              long (*ioctl)(struct file *, unsigned int, unsigned long),
-              int (*release)(struct inode *, struct file *));
-int pmem_remap(struct pmem_region *region, struct file *file,
-              unsigned operation);
-
-#else
-static inline int is_pmem_file(struct file *file) { return 0; }
-static inline int get_pmem_file(int fd, unsigned long *start,
-                               unsigned long *vstart, unsigned long *end,
-                               struct file **filp) { return -ENOSYS; }
-static inline int get_pmem_user_addr(struct file *file, unsigned long *start,
-                                    unsigned long *end) { return -ENOSYS; }
-static inline void put_pmem_file(struct file* file) { return; }
-static inline void flush_pmem_file(struct file *file, unsigned long start,
-                                  unsigned long len) { return; }
-static inline int pmem_setup(struct android_pmem_platform_data *pdata,
-             long (*ioctl)(struct file *, unsigned int, unsigned long),
-             int (*release)(struct inode *, struct file *)) { return -ENOSYS; }
-
-static inline int pmem_remap(struct pmem_region *region, struct file *file,
-                            unsigned operation) { return -ENOSYS; }
-#endif
-
-#endif //_ANDROID_PPP_H_
-
index 7491801a661c683f8b0f5fe9c11f8c7c1e1d1b33..f0b7e6605ab5e4969d88a2112498439362454f82 100644 (file)
@@ -38,6 +38,7 @@
 
 static DEFINE_MUTEX(binder_lock);
 static DEFINE_MUTEX(binder_deferred_lock);
+static DEFINE_MUTEX(binder_mmap_lock);
 
 static HLIST_HEAD(binder_procs);
 static HLIST_HEAD(binder_deferred_list);
@@ -632,6 +633,11 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
        if (mm) {
                down_write(&mm->mmap_sem);
                vma = proc->vma;
+               if (vma && mm != vma->vm_mm) {
+                       pr_err("binder: %d: vma mm and task mm mismatch\n",
+                               proc->pid);
+                       vma = NULL;
+               }
        }
 
        if (allocate == 0)
@@ -2759,7 +2765,6 @@ static void binder_vma_open(struct vm_area_struct *vma)
                     proc->pid, vma->vm_start, vma->vm_end,
                     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
                     (unsigned long)pgprot_val(vma->vm_page_prot));
-       dump_stack();
 }
 
 static void binder_vma_close(struct vm_area_struct *vma)
@@ -2803,6 +2808,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
        }
        vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
 
+       mutex_lock(&binder_mmap_lock);
        if (proc->buffer) {
                ret = -EBUSY;
                failure_string = "already mapped";
@@ -2817,6 +2823,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
        }
        proc->buffer = area->addr;
        proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
+       mutex_unlock(&binder_mmap_lock);
 
 #ifdef CONFIG_CPU_CACHE_VIPT
        if (cache_is_vipt_aliasing()) {
@@ -2849,7 +2856,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
        binder_insert_free_buffer(proc, buffer);
        proc->free_async_space = proc->buffer_size / 2;
        barrier();
-       proc->files = get_files_struct(current);
+       proc->files = get_files_struct(proc->tsk);
        proc->vma = vma;
 
        /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
@@ -2860,10 +2867,12 @@ err_alloc_small_buf_failed:
        kfree(proc->pages);
        proc->pages = NULL;
 err_alloc_pages_failed:
+       mutex_lock(&binder_mmap_lock);
        vfree(proc->buffer);
        proc->buffer = NULL;
 err_get_vm_area_failed:
 err_already_mapped:
+       mutex_unlock(&binder_mmap_lock);
 err_bad_arg:
        printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
               proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
index 2d8d2b79610190ade925b09250690cea52328fb7..efc7dc1f4831e2da6dc2c7cf5d605cb6ad27f00c 100644 (file)
@@ -54,6 +54,7 @@ static size_t lowmem_minfree[6] = {
 static int lowmem_minfree_size = 4;
 
 static struct task_struct *lowmem_deathpending;
+static unsigned long lowmem_deathpending_timeout;
 
 #define lowmem_print(level, x...)                      \
        do {                                            \
@@ -103,7 +104,8 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
         * Note: Currently you need CONFIG_PROFILING
         * for this to work correctly.
         */
-       if (lowmem_deathpending)
+       if (lowmem_deathpending &&
+           time_before_eq(jiffies, lowmem_deathpending_timeout))
                return 0;
 
        if (lowmem_adj_size < array_size)
@@ -178,6 +180,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
                 */
 #ifdef CONFIG_PROFILING
                lowmem_deathpending = selected;
+               lowmem_deathpending_timeout = jiffies + HZ;
                task_handoff_register(&task_nb);
 #endif
                force_sig(SIGKILL, selected);
diff --git a/drivers/staging/android/pmem.c b/drivers/staging/android/pmem.c
deleted file mode 100644 (file)
index 7d97032..0000000
+++ /dev/null
@@ -1,1345 +0,0 @@
-/* pmem.c
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/debugfs.h>
-#include <linux/mempolicy.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/cacheflush.h>
-#include "android_pmem.h"
-
-#define PMEM_MAX_DEVICES 10
-#define PMEM_MAX_ORDER 128
-#define PMEM_MIN_ALLOC PAGE_SIZE
-
-#define PMEM_DEBUG 1
-
-/* indicates that a refernce to this file has been taken via get_pmem_file,
- * the file should not be released until put_pmem_file is called */
-#define PMEM_FLAGS_BUSY 0x1
-/* indicates that this is a suballocation of a larger master range */
-#define PMEM_FLAGS_CONNECTED 0x1 << 1
-/* indicates this is a master and not a sub allocation and that it is mmaped */
-#define PMEM_FLAGS_MASTERMAP 0x1 << 2
-/* submap and unsubmap flags indicate:
- * 00: subregion has never been mmaped
- * 10: subregion has been mmaped, reference to the mm was taken
- * 11: subretion has ben released, refernece to the mm still held
- * 01: subretion has been released, reference to the mm has been released
- */
-#define PMEM_FLAGS_SUBMAP 0x1 << 3
-#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
-
-
-struct pmem_data {
-       /* in alloc mode: an index into the bitmap
-        * in no_alloc mode: the size of the allocation */
-       int index;
-       /* see flags above for descriptions */
-       unsigned int flags;
-       /* protects this data field, if the mm_mmap sem will be held at the
-        * same time as this sem, the mm sem must be taken first (as this is
-        * the order for vma_open and vma_close ops */
-       struct rw_semaphore sem;
-       /* info about the mmaping process */
-       struct vm_area_struct *vma;
-       /* task struct of the mapping process */
-       struct task_struct *task;
-       /* process id of teh mapping process */
-       pid_t pid;
-       /* file descriptor of the master */
-       int master_fd;
-       /* file struct of the master */
-       struct file *master_file;
-       /* a list of currently available regions if this is a suballocation */
-       struct list_head region_list;
-       /* a linked list of data so we can access them for debugging */
-       struct list_head list;
-#if PMEM_DEBUG
-       int ref;
-#endif
-};
-
-struct pmem_bits {
-       unsigned allocated:1;           /* 1 if allocated, 0 if free */
-       unsigned order:7;               /* size of the region in pmem space */
-};
-
-struct pmem_region_node {
-       struct pmem_region region;
-       struct list_head list;
-};
-
-#define PMEM_DEBUG_MSGS 0
-#if PMEM_DEBUG_MSGS
-#define DLOG(fmt,args...) \
-       do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
-                   ##args); } \
-       while (0)
-#else
-#define DLOG(x...) do {} while (0)
-#endif
-
-struct pmem_info {
-       struct miscdevice dev;
-       /* physical start address of the remaped pmem space */
-       unsigned long base;
-       /* vitual start address of the remaped pmem space */
-       unsigned char __iomem *vbase;
-       /* total size of the pmem space */
-       unsigned long size;
-       /* number of entries in the pmem space */
-       unsigned long num_entries;
-       /* pfn of the garbage page in memory */
-       unsigned long garbage_pfn;
-       /* index of the garbage page in the pmem space */
-       int garbage_index;
-       /* the bitmap for the region indicating which entries are allocated
-        * and which are free */
-       struct pmem_bits *bitmap;
-       /* indicates the region should not be managed with an allocator */
-       unsigned no_allocator;
-       /* indicates maps of this region should be cached, if a mix of
-        * cached and uncached is desired, set this and open the device with
-        * O_SYNC to get an uncached region */
-       unsigned cached;
-       unsigned buffered;
-       /* in no_allocator mode the first mapper gets the whole space and sets
-        * this flag */
-       unsigned allocated;
-       /* for debugging, creates a list of pmem file structs, the
-        * data_list_lock should be taken before pmem_data->sem if both are
-        * needed */
-       struct mutex data_list_lock;
-       struct list_head data_list;
-       /* pmem_sem protects the bitmap array
-        * a write lock should be held when modifying entries in bitmap
-        * a read lock should be held when reading data from bits or
-        * dereferencing a pointer into bitmap
-        *
-        * pmem_data->sem protects the pmem data of a particular file
-        * Many of the function that require the pmem_data->sem have a non-
-        * locking version for when the caller is already holding that sem.
-        *
-        * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER:
-        * down(pmem_data->sem) => down(bitmap_sem)
-        */
-       struct rw_semaphore bitmap_sem;
-
-       long (*ioctl)(struct file *, unsigned int, unsigned long);
-       int (*release)(struct inode *, struct file *);
-};
-
-static struct pmem_info pmem[PMEM_MAX_DEVICES];
-static int id_count;
-
-#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated)
-#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
-#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
-#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
-#define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC)
-#define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base)
-#define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC)
-#define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \
-       PMEM_LEN(id, index))
-#define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase)
-#define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \
-       PMEM_LEN(id, index))
-#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED)
-#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
-#define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \
-       (!(data->flags & PMEM_FLAGS_UNSUBMAP)))
-
-static int pmem_release(struct inode *, struct file *);
-static int pmem_mmap(struct file *, struct vm_area_struct *);
-static int pmem_open(struct inode *, struct file *);
-static long pmem_ioctl(struct file *, unsigned int, unsigned long);
-
-struct file_operations pmem_fops = {
-       .release = pmem_release,
-       .mmap = pmem_mmap,
-       .open = pmem_open,
-       .unlocked_ioctl = pmem_ioctl,
-};
-
-static int get_id(struct file *file)
-{
-       return MINOR(file->f_dentry->d_inode->i_rdev);
-}
-
-int is_pmem_file(struct file *file)
-{
-       int id;
-
-       if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))
-               return 0;
-       id = get_id(file);
-       if (unlikely(id >= PMEM_MAX_DEVICES))
-               return 0;
-       if (unlikely(file->f_dentry->d_inode->i_rdev !=
-            MKDEV(MISC_MAJOR, pmem[id].dev.minor)))
-               return 0;
-       return 1;
-}
-
-static int has_allocation(struct file *file)
-{
-       struct pmem_data *data;
-       /* check is_pmem_file first if not accessed via pmem_file_ops */
-
-       if (unlikely(!file->private_data))
-               return 0;
-       data = (struct pmem_data *)file->private_data;
-       if (unlikely(data->index < 0))
-               return 0;
-       return 1;
-}
-
-static int is_master_owner(struct file *file)
-{
-       struct file *master_file;
-       struct pmem_data *data;
-       int put_needed, ret = 0;
-
-       if (!is_pmem_file(file) || !has_allocation(file))
-               return 0;
-       data = (struct pmem_data *)file->private_data;
-       if (PMEM_FLAGS_MASTERMAP & data->flags)
-               return 1;
-       master_file = fget_light(data->master_fd, &put_needed);
-       if (master_file && data->master_file == master_file)
-               ret = 1;
-       fput_light(master_file, put_needed);
-       return ret;
-}
-
-static int pmem_free(int id, int index)
-{
-       /* caller should hold the write lock on pmem_sem! */
-       int buddy, curr = index;
-       DLOG("index %d\n", index);
-
-       if (pmem[id].no_allocator) {
-               pmem[id].allocated = 0;
-               return 0;
-       }
-       /* clean up the bitmap, merging any buddies */
-       pmem[id].bitmap[curr].allocated = 0;
-       /* find a slots buddy Buddy# = Slot# ^ (1 << order)
-        * if the buddy is also free merge them
-        * repeat until the buddy is not free or end of the bitmap is reached
-        */
-       do {
-               buddy = PMEM_BUDDY_INDEX(id, curr);
-               if (PMEM_IS_FREE(id, buddy) &&
-                               PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) {
-                       PMEM_ORDER(id, buddy)++;
-                       PMEM_ORDER(id, curr)++;
-                       curr = min(buddy, curr);
-               } else {
-                       break;
-               }
-       } while (curr < pmem[id].num_entries);
-
-       return 0;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data);
-
-static int pmem_release(struct inode *inode, struct file *file)
-{
-       struct pmem_data *data = (struct pmem_data *)file->private_data;
-       struct pmem_region_node *region_node;
-       struct list_head *elt, *elt2;
-       int id = get_id(file), ret = 0;
-
-
-       mutex_lock(&pmem[id].data_list_lock);
-       /* if this file is a master, revoke all the memory in the connected
-        *  files */
-       if (PMEM_FLAGS_MASTERMAP & data->flags) {
-               struct pmem_data *sub_data;
-               list_for_each(elt, &pmem[id].data_list) {
-                       sub_data = list_entry(elt, struct pmem_data, list);
-                       down_read(&sub_data->sem);
-                       if (PMEM_IS_SUBMAP(sub_data) &&
-                           file == sub_data->master_file) {
-                               up_read(&sub_data->sem);
-                               pmem_revoke(file, sub_data);
-                       }  else
-                               up_read(&sub_data->sem);
-               }
-       }
-       list_del(&data->list);
-       mutex_unlock(&pmem[id].data_list_lock);
-
-
-       down_write(&data->sem);
-
-       /* if its not a conencted file and it has an allocation, free it */
-       if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) {
-               down_write(&pmem[id].bitmap_sem);
-               ret = pmem_free(id, data->index);
-               up_write(&pmem[id].bitmap_sem);
-       }
-
-       /* if this file is a submap (mapped, connected file), downref the
-        * task struct */
-       if (PMEM_FLAGS_SUBMAP & data->flags)
-               if (data->task) {
-                       put_task_struct(data->task);
-                       data->task = NULL;
-               }
-
-       file->private_data = NULL;
-
-       list_for_each_safe(elt, elt2, &data->region_list) {
-               region_node = list_entry(elt, struct pmem_region_node, list);
-               list_del(elt);
-               kfree(region_node);
-       }
-       BUG_ON(!list_empty(&data->region_list));
-
-       up_write(&data->sem);
-       kfree(data);
-       if (pmem[id].release)
-               ret = pmem[id].release(inode, file);
-
-       return ret;
-}
-
-static int pmem_open(struct inode *inode, struct file *file)
-{
-       struct pmem_data *data;
-       int id = get_id(file);
-       int ret = 0;
-
-       DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file));
-       /* setup file->private_data to indicate its unmapped */
-       /*  you can only open a pmem device one time */
-       if (file->private_data != NULL)
-               return -1;
-       data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL);
-       if (!data) {
-               printk("pmem: unable to allocate memory for pmem metadata.");
-               return -1;
-       }
-       data->flags = 0;
-       data->index = -1;
-       data->task = NULL;
-       data->vma = NULL;
-       data->pid = 0;
-       data->master_file = NULL;
-#if PMEM_DEBUG
-       data->ref = 0;
-#endif
-       INIT_LIST_HEAD(&data->region_list);
-       init_rwsem(&data->sem);
-
-       file->private_data = data;
-       INIT_LIST_HEAD(&data->list);
-
-       mutex_lock(&pmem[id].data_list_lock);
-       list_add(&data->list, &pmem[id].data_list);
-       mutex_unlock(&pmem[id].data_list_lock);
-       return ret;
-}
-
-static unsigned long pmem_order(unsigned long len)
-{
-       int i;
-
-       len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC;
-       len--;
-       for (i = 0; i < sizeof(len)*8; i++)
-               if (len >> i == 0)
-                       break;
-       return i;
-}
-
-static int pmem_allocate(int id, unsigned long len)
-{
-       /* caller should hold the write lock on pmem_sem! */
-       /* return the corresponding pdata[] entry */
-       int curr = 0;
-       int end = pmem[id].num_entries;
-       int best_fit = -1;
-       unsigned long order = pmem_order(len);
-
-       if (pmem[id].no_allocator) {
-               DLOG("no allocator");
-               if ((len > pmem[id].size) || pmem[id].allocated)
-                       return -1;
-               pmem[id].allocated = 1;
-               return len;
-       }
-
-       if (order > PMEM_MAX_ORDER)
-               return -1;
-       DLOG("order %lx\n", order);
-
-       /* look through the bitmap:
-        *      if you find a free slot of the correct order use it
-        *      otherwise, use the best fit (smallest with size > order) slot
-        */
-       while (curr < end) {
-               if (PMEM_IS_FREE(id, curr)) {
-                       if (PMEM_ORDER(id, curr) == (unsigned char)order) {
-                               /* set the not free bit and clear others */
-                               best_fit = curr;
-                               break;
-                       }
-                       if (PMEM_ORDER(id, curr) > (unsigned char)order &&
-                           (best_fit < 0 ||
-                            PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit)))
-                               best_fit = curr;
-               }
-               curr = PMEM_NEXT_INDEX(id, curr);
-       }
-
-       /* if best_fit < 0, there are no suitable slots,
-        * return an error
-        */
-       if (best_fit < 0) {
-               printk("pmem: no space left to allocate!\n");
-               return -1;
-       }
-
-       /* now partition the best fit:
-        *      split the slot into 2 buddies of order - 1
-        *      repeat until the slot is of the correct order
-        */
-       while (PMEM_ORDER(id, best_fit) > (unsigned char)order) {
-               int buddy;
-               PMEM_ORDER(id, best_fit) -= 1;
-               buddy = PMEM_BUDDY_INDEX(id, best_fit);
-               PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit);
-       }
-       pmem[id].bitmap[best_fit].allocated = 1;
-       return best_fit;
-}
-
-static pgprot_t pmem_access_prot(struct file *file, pgprot_t vma_prot)
-{
-       int id = get_id(file);
-#ifdef pgprot_noncached
-       if (pmem[id].cached == 0 || file->f_flags & O_SYNC)
-               return pgprot_noncached(vma_prot);
-#endif
-#ifdef pgprot_ext_buffered
-       else if (pmem[id].buffered)
-               return pgprot_ext_buffered(vma_prot);
-#endif
-       return vma_prot;
-}
-
-static unsigned long pmem_start_addr(int id, struct pmem_data *data)
-{
-       if (pmem[id].no_allocator)
-               return PMEM_START_ADDR(id, 0);
-       else
-               return PMEM_START_ADDR(id, data->index);
-
-}
-
-static void *pmem_start_vaddr(int id, struct pmem_data *data)
-{
-       return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase;
-}
-
-static unsigned long pmem_len(int id, struct pmem_data *data)
-{
-       if (pmem[id].no_allocator)
-               return data->index;
-       else
-               return PMEM_LEN(id, data->index);
-}
-
-static int pmem_map_garbage(int id, struct vm_area_struct *vma,
-                           struct pmem_data *data, unsigned long offset,
-                           unsigned long len)
-{
-       int i, garbage_pages = len >> PAGE_SHIFT;
-
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE;
-       for (i = 0; i < garbage_pages; i++) {
-               if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE),
-                   pmem[id].garbage_pfn))
-                       return -EAGAIN;
-       }
-       return 0;
-}
-
-static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma,
-                               struct pmem_data *data, unsigned long offset,
-                               unsigned long len)
-{
-       int garbage_pages;
-       DLOG("unmap offset %lx len %lx\n", offset, len);
-
-       BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
-
-       garbage_pages = len >> PAGE_SHIFT;
-       zap_page_range(vma, vma->vm_start + offset, len, NULL);
-       pmem_map_garbage(id, vma, data, offset, len);
-       return 0;
-}
-
-static int pmem_map_pfn_range(int id, struct vm_area_struct *vma,
-                             struct pmem_data *data, unsigned long offset,
-                             unsigned long len)
-{
-       DLOG("map offset %lx len %lx\n", offset, len);
-       BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start));
-       BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end));
-       BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
-       BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset));
-
-       if (io_remap_pfn_range(vma, vma->vm_start + offset,
-               (pmem_start_addr(id, data) + offset) >> PAGE_SHIFT,
-               len, vma->vm_page_prot)) {
-               return -EAGAIN;
-       }
-       return 0;
-}
-
-static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma,
-                             struct pmem_data *data, unsigned long offset,
-                             unsigned long len)
-{
-       /* hold the mm semp for the vma you are modifying when you call this */
-       BUG_ON(!vma);
-       zap_page_range(vma, vma->vm_start + offset, len, NULL);
-       return pmem_map_pfn_range(id, vma, data, offset, len);
-}
-
-static void pmem_vma_open(struct vm_area_struct *vma)
-{
-       struct file *file = vma->vm_file;
-       struct pmem_data *data = file->private_data;
-       int id = get_id(file);
-       /* this should never be called as we don't support copying pmem
-        * ranges via fork */
-       BUG_ON(!has_allocation(file));
-       down_write(&data->sem);
-       /* remap the garbage pages, forkers don't get access to the data */
-       pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end);
-       up_write(&data->sem);
-}
-
-static void pmem_vma_close(struct vm_area_struct *vma)
-{
-       struct file *file = vma->vm_file;
-       struct pmem_data *data = file->private_data;
-
-       DLOG("current %u ppid %u file %p count %d\n", current->pid,
-            current->parent->pid, file, file_count(file));
-       if (unlikely(!is_pmem_file(file) || !has_allocation(file))) {
-               printk(KERN_WARNING "pmem: something is very wrong, you are "
-                      "closing a vm backing an allocation that doesn't "
-                      "exist!\n");
-               return;
-       }
-       down_write(&data->sem);
-       if (data->vma == vma) {
-               data->vma = NULL;
-               if ((data->flags & PMEM_FLAGS_CONNECTED) &&
-                   (data->flags & PMEM_FLAGS_SUBMAP))
-                       data->flags |= PMEM_FLAGS_UNSUBMAP;
-       }
-       /* the kernel is going to free this vma now anyway */
-       up_write(&data->sem);
-}
-
-static struct vm_operations_struct vm_ops = {
-       .open = pmem_vma_open,
-       .close = pmem_vma_close,
-};
-
-static int pmem_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct pmem_data *data;
-       int index;
-       unsigned long vma_size =  vma->vm_end - vma->vm_start;
-       int ret = 0, id = get_id(file);
-
-       if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) {
-#if PMEM_DEBUG
-               printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned"
-                               " and a multiple of pages_size.\n");
-#endif
-               return -EINVAL;
-       }
-
-       data = (struct pmem_data *)file->private_data;
-       down_write(&data->sem);
-       /* check this file isn't already mmaped, for submaps check this file
-        * has never been mmaped */
-       if ((data->flags & PMEM_FLAGS_SUBMAP) ||
-           (data->flags & PMEM_FLAGS_UNSUBMAP)) {
-#if PMEM_DEBUG
-               printk(KERN_ERR "pmem: you can only mmap a pmem file once, "
-                      "this file is already mmaped. %x\n", data->flags);
-#endif
-               ret = -EINVAL;
-               goto error;
-       }
-       /* if file->private_data == unalloced, alloc*/
-       if (data && data->index == -1) {
-               down_write(&pmem[id].bitmap_sem);
-               index = pmem_allocate(id, vma->vm_end - vma->vm_start);
-               up_write(&pmem[id].bitmap_sem);
-               data->index = index;
-       }
-       /* either no space was available or an error occured */
-       if (!has_allocation(file)) {
-               ret = -EINVAL;
-               printk("pmem: could not find allocation for map.\n");
-               goto error;
-       }
-
-       if (pmem_len(id, data) < vma_size) {
-#if PMEM_DEBUG
-               printk(KERN_WARNING "pmem: mmap size [%lu] does not match"
-                      "size of backing region [%lu].\n", vma_size,
-                      pmem_len(id, data));
-#endif
-               ret = -EINVAL;
-               goto error;
-       }
-
-       vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT;
-       vma->vm_page_prot = pmem_access_prot(file, vma->vm_page_prot);
-
-       if (data->flags & PMEM_FLAGS_CONNECTED) {
-               struct pmem_region_node *region_node;
-               struct list_head *elt;
-               if (pmem_map_garbage(id, vma, data, 0, vma_size)) {
-                       printk("pmem: mmap failed in kernel!\n");
-                       ret = -EAGAIN;
-                       goto error;
-               }
-               list_for_each(elt, &data->region_list) {
-                       region_node = list_entry(elt, struct pmem_region_node,
-                                                list);
-                       DLOG("remapping file: %p %lx %lx\n", file,
-                               region_node->region.offset,
-                               region_node->region.len);
-                       if (pmem_remap_pfn_range(id, vma, data,
-                                                region_node->region.offset,
-                                                region_node->region.len)) {
-                               ret = -EAGAIN;
-                               goto error;
-                       }
-               }
-               data->flags |= PMEM_FLAGS_SUBMAP;
-               get_task_struct(current->group_leader);
-               data->task = current->group_leader;
-               data->vma = vma;
-#if PMEM_DEBUG
-               data->pid = current->pid;
-#endif
-               DLOG("submmapped file %p vma %p pid %u\n", file, vma,
-                    current->pid);
-       } else {
-               if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) {
-                       printk(KERN_INFO "pmem: mmap failed in kernel!\n");
-                       ret = -EAGAIN;
-                       goto error;
-               }
-               data->flags |= PMEM_FLAGS_MASTERMAP;
-               data->pid = current->pid;
-       }
-       vma->vm_ops = &vm_ops;
-error:
-       up_write(&data->sem);
-       return ret;
-}
-
-/* the following are the api for accessing pmem regions by other drivers
- * from inside the kernel */
-int get_pmem_user_addr(struct file *file, unsigned long *start,
-                  unsigned long *len)
-{
-       struct pmem_data *data;
-       if (!is_pmem_file(file) || !has_allocation(file)) {
-#if PMEM_DEBUG
-               printk(KERN_INFO "pmem: requested pmem data from invalid"
-                                 "file.\n");
-#endif
-               return -1;
-       }
-       data = (struct pmem_data *)file->private_data;
-       down_read(&data->sem);
-       if (data->vma) {
-               *start = data->vma->vm_start;
-               *len = data->vma->vm_end - data->vma->vm_start;
-       } else {
-               *start = 0;
-               *len = 0;
-       }
-       up_read(&data->sem);
-       return 0;
-}
-
-int get_pmem_addr(struct file *file, unsigned long *start,
-                 unsigned long *vstart, unsigned long *len)
-{
-       struct pmem_data *data;
-       int id;
-
-       if (!is_pmem_file(file) || !has_allocation(file)) {
-               return -1;
-       }
-
-       data = (struct pmem_data *)file->private_data;
-       if (data->index == -1) {
-#if PMEM_DEBUG
-               printk(KERN_INFO "pmem: requested pmem data from file with no "
-                      "allocation.\n");
-               return -1;
-#endif
-       }
-       id = get_id(file);
-
-       down_read(&data->sem);
-       *start = pmem_start_addr(id, data);
-       *len = pmem_len(id, data);
-       *vstart = (unsigned long)pmem_start_vaddr(id, data);
-       up_read(&data->sem);
-#if PMEM_DEBUG
-       down_write(&data->sem);
-       data->ref++;
-       up_write(&data->sem);
-#endif
-       return 0;
-}
-
-int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
-                 unsigned long *len, struct file **filp)
-{
-       struct file *file;
-
-       file = fget(fd);
-       if (unlikely(file == NULL)) {
-               printk(KERN_INFO "pmem: requested data from file descriptor "
-                      "that doesn't exist.");
-               return -1;
-       }
-
-       if (get_pmem_addr(file, start, vstart, len))
-               goto end;
-
-       if (filp)
-               *filp = file;
-       return 0;
-end:
-       fput(file);
-       return -1;
-}
-
-void put_pmem_file(struct file *file)
-{
-       struct pmem_data *data;
-       int id;
-
-       if (!is_pmem_file(file))
-               return;
-       id = get_id(file);
-       data = (struct pmem_data *)file->private_data;
-#if PMEM_DEBUG
-       down_write(&data->sem);
-       if (data->ref == 0) {
-               printk("pmem: pmem_put > pmem_get %s (pid %d)\n",
-                      pmem[id].dev.name, data->pid);
-               BUG();
-       }
-       data->ref--;
-       up_write(&data->sem);
-#endif
-       fput(file);
-}
-
-void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
-{
-       struct pmem_data *data;
-       int id;
-       void *vaddr;
-       struct pmem_region_node *region_node;
-       struct list_head *elt;
-       void *flush_start, *flush_end;
-
-       if (!is_pmem_file(file) || !has_allocation(file)) {
-               return;
-       }
-
-       id = get_id(file);
-       data = (struct pmem_data *)file->private_data;
-       if (!pmem[id].cached || file->f_flags & O_SYNC)
-               return;
-
-       down_read(&data->sem);
-       vaddr = pmem_start_vaddr(id, data);
-       /* if this isn't a submmapped file, flush the whole thing */
-       if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) {
-               dmac_flush_range(vaddr, vaddr + pmem_len(id, data));
-               goto end;
-       }
-       /* otherwise, flush the region of the file we are drawing */
-       list_for_each(elt, &data->region_list) {
-               region_node = list_entry(elt, struct pmem_region_node, list);
-               if ((offset >= region_node->region.offset) &&
-                   ((offset + len) <= (region_node->region.offset +
-                       region_node->region.len))) {
-                       flush_start = vaddr + region_node->region.offset;
-                       flush_end = flush_start + region_node->region.len;
-                       dmac_flush_range(flush_start, flush_end);
-                       break;
-               }
-       }
-end:
-       up_read(&data->sem);
-}
-
-static int pmem_connect(unsigned long connect, struct file *file)
-{
-       struct pmem_data *data = (struct pmem_data *)file->private_data;
-       struct pmem_data *src_data;
-       struct file *src_file;
-       int ret = 0, put_needed;
-
-       down_write(&data->sem);
-       /* retrieve the src file and check it is a pmem file with an alloc */
-       src_file = fget_light(connect, &put_needed);
-       DLOG("connect %p to %p\n", file, src_file);
-       if (!src_file) {
-               printk("pmem: src file not found!\n");
-               ret = -EINVAL;
-               goto err_no_file;
-       }
-       if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) {
-               printk(KERN_INFO "pmem: src file is not a pmem file or has no "
-                      "alloc!\n");
-               ret = -EINVAL;
-               goto err_bad_file;
-       }
-       src_data = (struct pmem_data *)src_file->private_data;
-
-       if (has_allocation(file) && (data->index != src_data->index)) {
-               printk("pmem: file is already mapped but doesn't match this"
-                      " src_file!\n");
-               ret = -EINVAL;
-               goto err_bad_file;
-       }
-       data->index = src_data->index;
-       data->flags |= PMEM_FLAGS_CONNECTED;
-       data->master_fd = connect;
-       data->master_file = src_file;
-
-err_bad_file:
-       fput_light(src_file, put_needed);
-err_no_file:
-       up_write(&data->sem);
-       return ret;
-}
-
-static void pmem_unlock_data_and_mm(struct pmem_data *data,
-                                   struct mm_struct *mm)
-{
-       up_write(&data->sem);
-       if (mm != NULL) {
-               up_write(&mm->mmap_sem);
-               mmput(mm);
-       }
-}
-
-static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data,
-                                struct mm_struct **locked_mm)
-{
-       int ret = 0;
-       struct mm_struct *mm = NULL;
-       *locked_mm = NULL;
-lock_mm:
-       down_read(&data->sem);
-       if (PMEM_IS_SUBMAP(data)) {
-               mm = get_task_mm(data->task);
-               if (!mm) {
-#if PMEM_DEBUG
-                       printk("pmem: can't remap task is gone!\n");
-#endif
-                       up_read(&data->sem);
-                       return -1;
-               }
-       }
-       up_read(&data->sem);
-
-       if (mm)
-               down_write(&mm->mmap_sem);
-
-       down_write(&data->sem);
-       /* check that the file didn't get mmaped before we could take the
-        * data sem, this should be safe b/c you can only submap each file
-        * once */
-       if (PMEM_IS_SUBMAP(data) && !mm) {
-               pmem_unlock_data_and_mm(data, mm);
-               up_write(&data->sem);
-               goto lock_mm;
-       }
-       /* now check that vma.mm is still there, it could have been
-        * deleted by vma_close before we could get the data->sem */
-       if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) {
-               /* might as well release this */
-               if (data->flags & PMEM_FLAGS_SUBMAP) {
-                       put_task_struct(data->task);
-                       data->task = NULL;
-                       /* lower the submap flag to show the mm is gone */
-                       data->flags &= ~(PMEM_FLAGS_SUBMAP);
-               }
-               pmem_unlock_data_and_mm(data, mm);
-               return -1;
-       }
-       *locked_mm = mm;
-       return ret;
-}
-
-int pmem_remap(struct pmem_region *region, struct file *file,
-                     unsigned operation)
-{
-       int ret;
-       struct pmem_region_node *region_node;
-       struct mm_struct *mm = NULL;
-       struct list_head *elt, *elt2;
-       int id = get_id(file);
-       struct pmem_data *data = (struct pmem_data *)file->private_data;
-
-       /* pmem region must be aligned on a page boundry */
-       if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
-                !PMEM_IS_PAGE_ALIGNED(region->len))) {
-#if PMEM_DEBUG
-               printk("pmem: request for unaligned pmem suballocation "
-                      "%lx %lx\n", region->offset, region->len);
-#endif
-               return -EINVAL;
-       }
-
-       /* if userspace requests a region of len 0, there's nothing to do */
-       if (region->len == 0)
-               return 0;
-
-       /* lock the mm and data */
-       ret = pmem_lock_data_and_mm(file, data, &mm);
-       if (ret)
-               return 0;
-
-       /* only the owner of the master file can remap the client fds
-        * that back in it */
-       if (!is_master_owner(file)) {
-#if PMEM_DEBUG
-               printk("pmem: remap requested from non-master process\n");
-#endif
-               ret = -EINVAL;
-               goto err;
-       }
-
-       /* check that the requested range is within the src allocation */
-       if (unlikely((region->offset > pmem_len(id, data)) ||
-                    (region->len > pmem_len(id, data)) ||
-                    (region->offset + region->len > pmem_len(id, data)))) {
-#if PMEM_DEBUG
-               printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n");
-#endif
-               ret = -EINVAL;
-               goto err;
-       }
-
-       if (operation == PMEM_MAP) {
-               region_node = kmalloc(sizeof(struct pmem_region_node),
-                             GFP_KERNEL);
-               if (!region_node) {
-                       ret = -ENOMEM;
-#if PMEM_DEBUG
-                       printk(KERN_INFO "No space to allocate metadata!");
-#endif
-                       goto err;
-               }
-               region_node->region = *region;
-               list_add(&region_node->list, &data->region_list);
-       } else if (operation == PMEM_UNMAP) {
-               int found = 0;
-               list_for_each_safe(elt, elt2, &data->region_list) {
-                       region_node = list_entry(elt, struct pmem_region_node,
-                                     list);
-                       if (region->len == 0 ||
-                           (region_node->region.offset == region->offset &&
-                           region_node->region.len == region->len)) {
-                               list_del(elt);
-                               kfree(region_node);
-                               found = 1;
-                       }
-               }
-               if (!found) {
-#if PMEM_DEBUG
-                       printk("pmem: Unmap region does not map any mapped "
-                               "region!");
-#endif
-                       ret = -EINVAL;
-                       goto err;
-               }
-       }
-
-       if (data->vma && PMEM_IS_SUBMAP(data)) {
-               if (operation == PMEM_MAP)
-                       ret = pmem_remap_pfn_range(id, data->vma, data,
-                                                  region->offset, region->len);
-               else if (operation == PMEM_UNMAP)
-                       ret = pmem_unmap_pfn_range(id, data->vma, data,
-                                                  region->offset, region->len);
-       }
-
-err:
-       pmem_unlock_data_and_mm(data, mm);
-       return ret;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data)
-{
-       struct pmem_region_node *region_node;
-       struct list_head *elt, *elt2;
-       struct mm_struct *mm = NULL;
-       int id = get_id(file);
-       int ret = 0;
-
-       data->master_file = NULL;
-       ret = pmem_lock_data_and_mm(file, data, &mm);
-       /* if lock_data_and_mm fails either the task that mapped the fd, or
-        * the vma that mapped it have already gone away, nothing more
-        * needs to be done */
-       if (ret)
-               return;
-       /* unmap everything */
-       /* delete the regions and region list nothing is mapped any more */
-       if (data->vma)
-               list_for_each_safe(elt, elt2, &data->region_list) {
-                       region_node = list_entry(elt, struct pmem_region_node,
-                                                list);
-                       pmem_unmap_pfn_range(id, data->vma, data,
-                                            region_node->region.offset,
-                                            region_node->region.len);
-                       list_del(elt);
-                       kfree(region_node);
-       }
-       /* delete the master file */
-       pmem_unlock_data_and_mm(data, mm);
-}
-
-static void pmem_get_size(struct pmem_region *region, struct file *file)
-{
-       struct pmem_data *data = (struct pmem_data *)file->private_data;
-       int id = get_id(file);
-
-       if (!has_allocation(file)) {
-               region->offset = 0;
-               region->len = 0;
-               return;
-       } else {
-               region->offset = pmem_start_addr(id, data);
-               region->len = pmem_len(id, data);
-       }
-       DLOG("offset %lx len %lx\n", region->offset, region->len);
-}
-
-
-static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct pmem_data *data;
-       int id = get_id(file);
-
-       switch (cmd) {
-       case PMEM_GET_PHYS:
-               {
-                       struct pmem_region region;
-                       DLOG("get_phys\n");
-                       if (!has_allocation(file)) {
-                               region.offset = 0;
-                               region.len = 0;
-                       } else {
-                               data = (struct pmem_data *)file->private_data;
-                               region.offset = pmem_start_addr(id, data);
-                               region.len = pmem_len(id, data);
-                       }
-                       printk(KERN_INFO "pmem: request for physical address of pmem region "
-                                       "from process %d.\n", current->pid);
-                       if (copy_to_user((void __user *)arg, &region,
-                                               sizeof(struct pmem_region)))
-                               return -EFAULT;
-                       break;
-               }
-       case PMEM_MAP:
-               {
-                       struct pmem_region region;
-                       if (copy_from_user(&region, (void __user *)arg,
-                                               sizeof(struct pmem_region)))
-                               return -EFAULT;
-                       data = (struct pmem_data *)file->private_data;
-                       return pmem_remap(&region, file, PMEM_MAP);
-               }
-               break;
-       case PMEM_UNMAP:
-               {
-                       struct pmem_region region;
-                       if (copy_from_user(&region, (void __user *)arg,
-                                               sizeof(struct pmem_region)))
-                               return -EFAULT;
-                       data = (struct pmem_data *)file->private_data;
-                       return pmem_remap(&region, file, PMEM_UNMAP);
-                       break;
-               }
-       case PMEM_GET_SIZE:
-               {
-                       struct pmem_region region;
-                       DLOG("get_size\n");
-                       pmem_get_size(&region, file);
-                       if (copy_to_user((void __user *)arg, &region,
-                                               sizeof(struct pmem_region)))
-                               return -EFAULT;
-                       break;
-               }
-       case PMEM_GET_TOTAL_SIZE:
-               {
-                       struct pmem_region region;
-                       DLOG("get total size\n");
-                       region.offset = 0;
-                       get_id(file);
-                       region.len = pmem[id].size;
-                       if (copy_to_user((void __user *)arg, &region,
-                                               sizeof(struct pmem_region)))
-                               return -EFAULT;
-                       break;
-               }
-       case PMEM_ALLOCATE:
-               {
-                       if (has_allocation(file))
-                               return -EINVAL;
-                       data = (struct pmem_data *)file->private_data;
-                       data->index = pmem_allocate(id, arg);
-                       break;
-               }
-       case PMEM_CONNECT:
-               DLOG("connect\n");
-               return pmem_connect(arg, file);
-               break;
-       case PMEM_CACHE_FLUSH:
-               {
-                       struct pmem_region region;
-                       DLOG("flush\n");
-                       if (copy_from_user(&region, (void __user *)arg,
-                                          sizeof(struct pmem_region)))
-                               return -EFAULT;
-                       flush_pmem_file(file, region.offset, region.len);
-                       break;
-               }
-       default:
-               if (pmem[id].ioctl)
-                       return pmem[id].ioctl(file, cmd, arg);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-#if PMEM_DEBUG
-static ssize_t debug_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
-static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
-                         loff_t *ppos)
-{
-       struct list_head *elt, *elt2;
-       struct pmem_data *data;
-       struct pmem_region_node *region_node;
-       int id = (int)file->private_data;
-       const int debug_bufmax = 4096;
-       static char buffer[4096];
-       int n = 0;
-
-       DLOG("debug open\n");
-       n = scnprintf(buffer, debug_bufmax,
-                     "pid #: mapped regions (offset, len) (offset,len)...\n");
-
-       mutex_lock(&pmem[id].data_list_lock);
-       list_for_each(elt, &pmem[id].data_list) {
-               data = list_entry(elt, struct pmem_data, list);
-               down_read(&data->sem);
-               n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:",
-                               data->pid);
-               list_for_each(elt2, &data->region_list) {
-                       region_node = list_entry(elt2, struct pmem_region_node,
-                                     list);
-                       n += scnprintf(buffer + n, debug_bufmax - n,
-                                       "(%lx,%lx) ",
-                                       region_node->region.offset,
-                                       region_node->region.len);
-               }
-               n += scnprintf(buffer + n, debug_bufmax - n, "\n");
-               up_read(&data->sem);
-       }
-       mutex_unlock(&pmem[id].data_list_lock);
-
-       n++;
-       buffer[n] = 0;
-       return simple_read_from_buffer(buf, count, ppos, buffer, n);
-}
-
-static struct file_operations debug_fops = {
-       .read = debug_read,
-       .open = debug_open,
-};
-#endif
-
-#if 0
-static struct miscdevice pmem_dev = {
-       .name = "pmem",
-       .fops = &pmem_fops,
-};
-#endif
-
-int pmem_setup(struct android_pmem_platform_data *pdata,
-              long (*ioctl)(struct file *, unsigned int, unsigned long),
-              int (*release)(struct inode *, struct file *))
-{
-       int err = 0;
-       int i, index = 0;
-       int id = id_count;
-       id_count++;
-
-       pmem[id].no_allocator = pdata->no_allocator;
-       pmem[id].cached = pdata->cached;
-       pmem[id].buffered = pdata->buffered;
-       pmem[id].base = pdata->start;
-       pmem[id].size = pdata->size;
-       pmem[id].ioctl = ioctl;
-       pmem[id].release = release;
-       init_rwsem(&pmem[id].bitmap_sem);
-       mutex_init(&pmem[id].data_list_lock);
-       INIT_LIST_HEAD(&pmem[id].data_list);
-       pmem[id].dev.name = pdata->name;
-       pmem[id].dev.minor = id;
-       pmem[id].dev.fops = &pmem_fops;
-       printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached);
-
-       err = misc_register(&pmem[id].dev);
-       if (err) {
-               printk(KERN_ALERT "Unable to register pmem driver!\n");
-               goto err_cant_register_device;
-       }
-       pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC;
-
-       pmem[id].bitmap = kmalloc(pmem[id].num_entries *
-                                 sizeof(struct pmem_bits), GFP_KERNEL);
-       if (!pmem[id].bitmap)
-               goto err_no_mem_for_metadata;
-
-       memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) *
-                                         pmem[id].num_entries);
-
-       for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) {
-               if ((pmem[id].num_entries) &  1<<i) {
-                       PMEM_ORDER(id, index) = i;
-                       index = PMEM_NEXT_INDEX(id, index);
-               }
-       }
-
-       if (pmem[id].cached)
-               pmem[id].vbase = ioremap_cached(pmem[id].base,
-                                               pmem[id].size);
-#ifdef ioremap_ext_buffered
-       else if (pmem[id].buffered)
-               pmem[id].vbase = ioremap_ext_buffered(pmem[id].base,
-                                                     pmem[id].size);
-#endif
-       else
-               pmem[id].vbase = ioremap(pmem[id].base, pmem[id].size);
-
-       if (pmem[id].vbase == 0)
-               goto error_cant_remap;
-
-       pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
-       if (pmem[id].no_allocator)
-               pmem[id].allocated = 0;
-
-#if PMEM_DEBUG
-       debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)id,
-                           &debug_fops);
-#endif
-       return 0;
-error_cant_remap:
-       kfree(pmem[id].bitmap);
-err_no_mem_for_metadata:
-       misc_deregister(&pmem[id].dev);
-err_cant_register_device:
-       return -1;
-}
-
-static int pmem_probe(struct platform_device *pdev)
-{
-       struct android_pmem_platform_data *pdata;
-
-       if (!pdev || !pdev->dev.platform_data) {
-               printk(KERN_ALERT "Unable to probe pmem!\n");
-               return -1;
-       }
-       pdata = pdev->dev.platform_data;
-       return pmem_setup(pdata, NULL, NULL);
-}
-
-
-static int pmem_remove(struct platform_device *pdev)
-{
-       int id = pdev->id;
-       __free_page(pfn_to_page(pmem[id].garbage_pfn));
-       misc_deregister(&pmem[id].dev);
-       return 0;
-}
-
-static struct platform_driver pmem_driver = {
-       .probe = pmem_probe,
-       .remove = pmem_remove,
-       .driver = { .name = "android_pmem" }
-};
-
-
-static int __init pmem_init(void)
-{
-       return platform_driver_register(&pmem_driver);
-}
-
-static void __exit pmem_exit(void)
-{
-       platform_driver_unregister(&pmem_driver);
-}
-
-module_init(pmem_init);
-module_exit(pmem_exit);
-
index e77e4e0396cf9f4debc146e7a4816e01c4928271..1df9586f273088744c45b51254f5de273b32c389 100644 (file)
@@ -355,7 +355,14 @@ static void send_data(struct asus_oled_dev *odev)
 
 static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
 {
-       while (count-- > 0 && val) {
+       odev->last_val = val;
+
+       if (val == 0) {
+               odev->buf_offs += count;
+               return 0;
+       }
+
+       while (count-- > 0) {
                size_t x = odev->buf_offs % odev->width;
                size_t y = odev->buf_offs / odev->width;
                size_t i;
@@ -406,7 +413,6 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
                        ;
                }
 
-               odev->last_val = val;
                odev->buf_offs++;
        }
 
@@ -805,10 +811,9 @@ error:
 
 static void __exit asus_oled_exit(void)
 {
+       usb_deregister(&oled_driver);
        class_remove_file(oled_class, &class_attr_version.attr);
        class_destroy(oled_class);
-
-       usb_deregister(&oled_driver);
 }
 
 module_init(asus_oled_init);
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
deleted file mode 100644 (file)
index c7a2b3b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-config DRM_PSB
-       tristate "Intel GMA5/600 KMS Framebuffer"
-       depends on DRM && PCI && X86 && BROKEN
-       select FB_CFB_COPYAREA
-        select FB_CFB_FILLRECT
-        select FB_CFB_IMAGEBLIT
-        select DRM_KMS_HELPER
-        select DRM_TTM
-       help
-         Say yes for an experimental 2D KMS framebuffer driver for the
-         Intel GMA500 ('Poulsbo') and other Intel IMG based graphics
-         devices.
-
-config DRM_PSB_MRST
-       bool "Intel GMA600 support (Experimental)"
-       depends on DRM_PSB
-       help
-         Say yes to include support for GMA600 (Intel Moorestown/Oaktrail)
-         platforms with LVDS ports. HDMI and MIPI are not currently
-         supported.
-
-config DRM_PSB_MFLD
-       bool "Intel Medfield support (Experimental)"
-       depends on DRM_PSB
-       help
-         Say yes to include support for Intel Medfield platforms with MIPI
-         interfaces.
-       
-config DRM_PSB_CDV
-       bool "Intel Cedarview support (Experimental)"
-       depends on DRM_PSB
-       help
-         Say yes to include support for Intel Cedarview platforms
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
deleted file mode 100644 (file)
index c729868..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-#      KMS driver for the GMA500
-#
-ccflags-y += -Iinclude/drm
-
-psb_gfx-y += gem_glue.o \
-         accel_2d.o \
-         backlight.o \
-         framebuffer.o \
-         gem.o \
-         gtt.o \
-         intel_bios.o \
-         intel_i2c.o \
-         intel_opregion.o \
-         mmu.o \
-         power.o \
-         psb_drv.o \
-         psb_intel_display.o \
-         psb_intel_lvds.o \
-         psb_intel_modes.o \
-         psb_intel_sdvo.o \
-         psb_lid.o \
-         psb_irq.o \
-         psb_device.o \
-         mid_bios.o
-
-psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o \
-         cdv_intel_crt.o \
-         cdv_intel_display.o \
-         cdv_intel_hdmi.o \
-         cdv_intel_lvds.o
-
-psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
-         mrst_crtc.o \
-         mrst_lvds.o \
-         mrst_hdmi.o \
-         mrst_hdmi_i2c.o
-
-psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
-         mdfld_output.o \
-         mdfld_pyr_cmd.o \
-         mdfld_tmd_vid.o \
-         mdfld_tpo_cmd.o \
-         mdfld_tpo_vid.o \
-         mdfld_dsi_pkg_sender.o \
-         mdfld_dsi_dpi.o \
-         mdfld_dsi_output.o \
-         mdfld_dsi_dbi.o \
-         mdfld_dsi_dbi_dpu.o \
-         mdfld_intel_display.o
-
-obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO
deleted file mode 100644 (file)
index fc83615..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
--      Sort out the power management side. Not important for Poulsbo but
-       matters for Moorestown/Medfield
--      Debug Oaktrail/Moorestown support (single pipe, no BIOS on mrst,
-                                       some other differences)
--      Add 2D acceleration via console and DRM
--      Add scrolling acceleration using the GTT to do remapping on the main
-       framebuffer.
--      HDMI testing
--      Oaktrail HDMI and other features
--      Oaktrail MIPI
--      Medfield needs a lot of further love
-
-As per kernel policy and the in the interest of the safety of various
-kittens there is no support or plans to add hooks for the closed user space
-stuff.
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
deleted file mode 100644 (file)
index b8f78eb..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "framebuffer.h"
-
-/**
- *     psb_spank               -       reset the 2D engine
- *     @dev_priv: our PSB DRM device
- *
- *     Soft reset the graphics engine and then reload the necessary registers.
- *     We use this at initialisation time but it will become relevant for
- *     accelerated X later
- */
-void psb_spank(struct drm_psb_private *dev_priv)
-{
-       PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
-               _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
-               _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
-               _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
-       PSB_RSGX32(PSB_CR_SOFT_RESET);
-
-       msleep(1);
-
-       PSB_WSGX32(0, PSB_CR_SOFT_RESET);
-       wmb();
-       PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
-                  PSB_CR_BIF_CTRL);
-       wmb();
-       (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-
-       msleep(1);
-       PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
-                  PSB_CR_BIF_CTRL);
-       (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-       PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-}
-
-/**
- *     psb2_2d_wait_available  -       wait for FIFO room
- *     @dev_priv: our DRM device
- *     @size: size (in dwords) of the command we want to issue
- *
- *     Wait until there is room to load the FIFO with our data. If the
- *     device is not responding then reset it
- */
-static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
-                         unsigned size)
-{
-       uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
-       unsigned long t = jiffies + HZ;
-
-       while (avail < size) {
-               avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
-               if (time_after(jiffies, t)) {
-                       psb_spank(dev_priv);
-                       return -EIO;
-               }
-       }
-       return 0;
-}
-
-/**
- *     psb_2d_submit           -       submit a 2D command
- *     @dev_priv: our DRM device
- *     @cmdbuf: command to issue
- *     @size: length (in dwords)
- *
- *     Issue one or more 2D commands to the accelerator. This needs to be
- *     serialized later when we add the GEM interfaces for acceleration
- */
-static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
-                                                               unsigned size)
-{
-       int ret = 0;
-       int i;
-       unsigned submit_size;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev_priv->lock_2d, flags);
-       while (size > 0) {
-               submit_size = (size < 0x60) ? size : 0x60;
-               size -= submit_size;
-               ret = psb_2d_wait_available(dev_priv, submit_size);
-               if (ret)
-                       break;
-
-               submit_size <<= 2;
-
-               for (i = 0; i < submit_size; i += 4)
-                       PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
-
-               (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
-       }
-       spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
-       return ret;
-}
-
-
-/**
- *     psb_accel_2d_copy_direction     -       compute blit order
- *     @xdir: X direction of move
- *     @ydir: Y direction of move
- *
- *     Compute the correct order setings to ensure that an overlapping blit
- *     correctly copies all the pixels.
- */
-static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
-{
-       if (xdir < 0)
-               return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
-                                               PSB_2D_COPYORDER_TR2BL;
-       else
-               return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
-                                               PSB_2D_COPYORDER_TL2BR;
-}
-
-/**
- *     psb_accel_2d_copy               -       accelerated 2D copy
- *     @dev_priv: our DRM device
- *     @src_offset in bytes
- *     @src_stride in bytes
- *     @src_format psb 2D format defines
- *     @dst_offset in bytes
- *     @dst_stride in bytes
- *     @dst_format psb 2D format defines
- *     @src_x offset in pixels
- *     @src_y offset in pixels
- *     @dst_x offset in pixels
- *     @dst_y offset in pixels
- *     @size_x of the copied area
- *     @size_y of the copied area
- *
- *     Format and issue a 2D accelerated copy command.
- */
-static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
-                            uint32_t src_offset, uint32_t src_stride,
-                            uint32_t src_format, uint32_t dst_offset,
-                            uint32_t dst_stride, uint32_t dst_format,
-                            uint16_t src_x, uint16_t src_y,
-                            uint16_t dst_x, uint16_t dst_y,
-                            uint16_t size_x, uint16_t size_y)
-{
-       uint32_t blit_cmd;
-       uint32_t buffer[10];
-       uint32_t *buf;
-       uint32_t direction;
-
-       buf = buffer;
-
-       direction =
-           psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
-
-       if (direction == PSB_2D_COPYORDER_BR2TL ||
-           direction == PSB_2D_COPYORDER_TR2BL) {
-               src_x += size_x - 1;
-               dst_x += size_x - 1;
-       }
-       if (direction == PSB_2D_COPYORDER_BR2TL ||
-           direction == PSB_2D_COPYORDER_BL2TR) {
-               src_y += size_y - 1;
-               dst_y += size_y - 1;
-       }
-
-       blit_cmd =
-           PSB_2D_BLIT_BH |
-           PSB_2D_ROT_NONE |
-           PSB_2D_DSTCK_DISABLE |
-           PSB_2D_SRCCK_DISABLE |
-           PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
-
-       *buf++ = PSB_2D_FENCE_BH;
-       *buf++ =
-           PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
-                                              PSB_2D_DST_STRIDE_SHIFT);
-       *buf++ = dst_offset;
-       *buf++ =
-           PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
-                                              PSB_2D_SRC_STRIDE_SHIFT);
-       *buf++ = src_offset;
-       *buf++ =
-           PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
-           (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
-       *buf++ = blit_cmd;
-       *buf++ =
-           (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
-                                                 PSB_2D_DST_YSTART_SHIFT);
-       *buf++ =
-           (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
-                                                 PSB_2D_DST_YSIZE_SHIFT);
-       *buf++ = PSB_2D_FLUSH_BH;
-
-       return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-/**
- *     psbfb_copyarea_accel    -       copyarea acceleration for /dev/fb
- *     @info: our framebuffer
- *     @a: copyarea parameters from the framebuffer core
- *
- *     Perform a 2D copy via the accelerator
- */
-static void psbfb_copyarea_accel(struct fb_info *info,
-                                const struct fb_copyarea *a)
-{
-       struct psb_fbdev *fbdev = info->par;
-       struct psb_framebuffer *psbfb = &fbdev->pfb;
-       struct drm_device *dev = psbfb->base.dev;
-       struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       uint32_t offset;
-       uint32_t stride;
-       uint32_t src_format;
-       uint32_t dst_format;
-
-       if (!fb)
-               return;
-
-       offset = psbfb->gtt->offset;
-       stride = fb->pitches[0];
-
-       switch (fb->depth) {
-       case 8:
-               src_format = PSB_2D_SRC_332RGB;
-               dst_format = PSB_2D_DST_332RGB;
-               break;
-       case 15:
-               src_format = PSB_2D_SRC_555RGB;
-               dst_format = PSB_2D_DST_555RGB;
-               break;
-       case 16:
-               src_format = PSB_2D_SRC_565RGB;
-               dst_format = PSB_2D_DST_565RGB;
-               break;
-       case 24:
-       case 32:
-               /* this is wrong but since we don't do blending its okay */
-               src_format = PSB_2D_SRC_8888ARGB;
-               dst_format = PSB_2D_DST_8888ARGB;
-               break;
-       default:
-               /* software fallback */
-               cfb_copyarea(info, a);
-               return;
-       }
-
-       if (!gma_power_begin(dev, false)) {
-               cfb_copyarea(info, a);
-               return;
-       }
-       psb_accel_2d_copy(dev_priv,
-                         offset, stride, src_format,
-                         offset, stride, dst_format,
-                         a->sx, a->sy, a->dx, a->dy, a->width, a->height);
-       gma_power_end(dev);
-}
-
-/**
- *     psbfb_copyarea  -       2D copy interface
- *     @info: our framebuffer
- *     @region: region to copy
- *
- *     Copy an area of the framebuffer console either by the accelerator
- *     or directly using the cfb helpers according to the request
- */
-void psbfb_copyarea(struct fb_info *info,
-                          const struct fb_copyarea *region)
-{
-       if (unlikely(info->state != FBINFO_STATE_RUNNING))
-               return;
-
-       /* Avoid the 8 pixel erratum */
-       if (region->width == 8 || region->height == 8 ||
-               (info->flags & FBINFO_HWACCEL_DISABLED))
-               return cfb_copyarea(info, region);
-
-       psbfb_copyarea_accel(info, region);
-}
-
-/**
- *     psbfb_sync      -       synchronize 2D
- *     @info: our framebuffer
- *
- *     Wait for the 2D engine to quiesce so that we can do CPU
- *     access to the framebuffer again
- */
-int psbfb_sync(struct fb_info *info)
-{
-       struct psb_fbdev *fbdev = info->par;
-       struct psb_framebuffer *psbfb = &fbdev->pfb;
-       struct drm_device *dev = psbfb->base.dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long _end = jiffies + DRM_HZ;
-       int busy = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev_priv->lock_2d, flags);
-       /*
-        * First idle the 2D engine.
-        */
-
-       if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
-           ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
-               goto out;
-
-       do {
-               busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
-               cpu_relax();
-       } while (busy && !time_after_eq(jiffies, _end));
-
-       if (busy)
-               busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
-       if (busy)
-               goto out;
-
-       do {
-               busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
-                                               _PSB_C2B_STATUS_BUSY) != 0);
-               cpu_relax();
-       } while (busy && !time_after_eq(jiffies, _end));
-       if (busy)
-               busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
-                                       _PSB_C2B_STATUS_BUSY) != 0);
-
-out:
-       spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
-       return (busy) ? -EBUSY : 0;
-}
-
-int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_psb_2d_op *op = data;
-       u32 *op_ptr = &op->cmd[0];
-       int i;
-       struct drm_gem_object *obj;
-       struct gtt_range *gtt;
-       int err = -EINVAL;
-
-       if (!dev_priv->ops->accel_2d)
-               return -EOPNOTSUPP;
-       if (op->size > PSB_2D_OP_BUFLEN)
-               return -EINVAL;
-
-       /* The GEM object being used. We need to support separate src/dst/etc
-          in the end but for now keep them all the same */
-       obj = drm_gem_object_lookup(dev, file, op->src);
-       if (obj == NULL)
-               return -ENOENT;
-       gtt = container_of(obj, struct gtt_range, gem);
-
-       if (psb_gtt_pin(gtt) < 0)
-               goto bad_2;
-       for (i = 0; i < op->size; i++, op_ptr++) {
-               u32 r = *op_ptr & 0xF0000000;
-               /* Fill in the GTT offsets for the command buffer */
-               if (r == PSB_2D_SRC_SURF_BH ||
-                       r == PSB_2D_DST_SURF_BH ||
-                       r == PSB_2D_MASK_SURF_BH ||
-                       r == PSB_2D_PAT_SURF_BH) {
-                       i++;
-                       op_ptr++;
-                       if (i == op->size)
-                               goto bad;
-                       if (*op_ptr)
-                               goto bad;
-                       *op_ptr = gtt->offset;
-                       continue;
-               }
-       }
-       psbfb_2d_submit(dev_priv, op->cmd, op->size);
-       err = 0;
-bad:
-       psb_gtt_unpin(gtt);
-bad_2:
-       drm_gem_object_unreference(obj);
-       return err;
-}
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
deleted file mode 100644 (file)
index 2079395..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * GMA500 Backlight Interface
- *
- * Copyright (c) 2009-2011, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors: Eric Knopp
- *
- */
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "intel_bios.h"
-#include "power.h"
-
-int gma_backlight_init(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       return dev_priv->ops->backlight_init(dev);
-#else
-       return 0;
-#endif
-}
-
-void gma_backlight_exit(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       if (dev_priv->backlight_device) {
-               dev_priv->backlight_device->props.brightness = 0;
-               backlight_update_status(dev_priv->backlight_device);
-               backlight_device_unregister(dev_priv->backlight_device);
-       }
-#endif
-}
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
deleted file mode 100644 (file)
index 8ec10ca..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#include "cdv_device.h"
-
-#define VGA_SR_INDEX           0x3c4
-#define VGA_SR_DATA            0x3c5
-
-static void cdv_disable_vga(struct drm_device *dev)
-{
-       u8 sr1;
-       u32 vga_reg;
-
-       vga_reg = VGACNTRL;
-
-       outb(1, VGA_SR_INDEX);
-       sr1 = inb(VGA_SR_DATA);
-       outb(sr1 | 1<<5, VGA_SR_DATA);
-       udelay(300);
-
-       REG_WRITE(vga_reg, VGA_DISP_DISABLE);
-       REG_READ(vga_reg);
-}
-
-static int cdv_output_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       cdv_disable_vga(dev);
-
-       cdv_intel_crt_init(dev, &dev_priv->mode_dev);
-       cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
-
-       /* These bits indicate HDMI not SDVO on CDV, but we don't yet support
-          the HDMI interface */
-       if (REG_READ(SDVOB) & SDVO_DETECTED)
-               cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
-       if (REG_READ(SDVOC) & SDVO_DETECTED)
-               cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
-       return 0;
-}
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-/*
- *     Poulsbo Backlight Interfaces
- */
-
-#define BLC_PWM_PRECISION_FACTOR 100   /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-
-#define PSB_BLC_PWM_PRECISION_FACTOR    10
-#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT    (16)
-
-static int cdv_brightness;
-static struct backlight_device *cdv_backlight_device;
-
-static int cdv_get_brightness(struct backlight_device *bd)
-{
-       /* return locally cached var instead of HW read (due to DPST etc.) */
-       /* FIXME: ideally return actual value in case firmware fiddled with
-          it */
-       return cdv_brightness;
-}
-
-
-static int cdv_backlight_setup(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long core_clock;
-       /* u32 bl_max_freq; */
-       /* unsigned long value; */
-       u16 bl_max_freq;
-       uint32_t value;
-       uint32_t blc_pwm_precision_factor;
-
-       /* get bl_max_freq and pol from dev_priv*/
-       if (!dev_priv->lvds_bl) {
-               dev_err(dev->dev, "Has no valid LVDS backlight info\n");
-               return -ENOENT;
-       }
-       bl_max_freq = dev_priv->lvds_bl->freq;
-       blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
-
-       core_clock = dev_priv->core_freq;
-
-       value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
-       value *= blc_pwm_precision_factor;
-       value /= bl_max_freq;
-       value /= blc_pwm_precision_factor;
-
-       if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
-                value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
-                               return -ERANGE;
-       else {
-               /* FIXME */
-       }
-       return 0;
-}
-
-static int cdv_set_brightness(struct backlight_device *bd)
-{
-       int level = bd->props.brightness;
-
-       /* Percentage 1-100% being valid */
-       if (level < 1)
-               level = 1;
-
-       /*cdv_intel_lvds_set_brightness(dev, level); FIXME */
-       cdv_brightness = level;
-       return 0;
-}
-
-static const struct backlight_ops cdv_ops = {
-       .get_brightness = cdv_get_brightness,
-       .update_status  = cdv_set_brightness,
-};
-
-static int cdv_backlight_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int ret;
-       struct backlight_properties props;
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.max_brightness = 100;
-       props.type = BACKLIGHT_PLATFORM;
-
-       cdv_backlight_device = backlight_device_register("psb-bl",
-                                       NULL, (void *)dev, &cdv_ops, &props);
-       if (IS_ERR(cdv_backlight_device))
-               return PTR_ERR(cdv_backlight_device);
-
-       ret = cdv_backlight_setup(dev);
-       if (ret < 0) {
-               backlight_device_unregister(cdv_backlight_device);
-               cdv_backlight_device = NULL;
-               return ret;
-       }
-       cdv_backlight_device->props.brightness = 100;
-       cdv_backlight_device->props.max_brightness = 100;
-       backlight_update_status(cdv_backlight_device);
-       dev_priv->backlight_device = cdv_backlight_device;
-       return 0;
-}
-
-#endif
-
-/*
- *     Provide the Cedarview specific chip logic and low level methods
- *     for power management
- *
- *     FIXME: we need to implement the apm/ospm base management bits
- *     for this and the MID devices.
- */
-
-static inline u32 CDV_MSG_READ32(uint port, uint offset)
-{
-       int mcr = (0x10<<24) | (port << 16) | (offset << 8);
-       uint32_t ret_val = 0;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       pci_write_config_dword(pci_root, 0xD0, mcr);
-       pci_read_config_dword(pci_root, 0xD4, &ret_val);
-       pci_dev_put(pci_root);
-       return ret_val;
-}
-
-static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
-{
-       int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       pci_write_config_dword(pci_root, 0xD4, value);
-       pci_write_config_dword(pci_root, 0xD0, mcr);
-       pci_dev_put(pci_root);
-}
-
-#define PSB_APM_CMD                    0x0
-#define PSB_APM_STS                    0x04
-#define PSB_PM_SSC                     0x20
-#define PSB_PM_SSS                     0x30
-#define PSB_PWRGT_GFX_MASK             0x3
-#define CDV_PWRGT_DISPLAY_CNTR         0x000fc00c
-#define CDV_PWRGT_DISPLAY_STS          0x000fc00c
-
-static void cdv_init_pm(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 pwr_cnt;
-       int i;
-
-       dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
-                                                       PSB_APMBA) & 0xFFFF;
-       dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
-                                                       PSB_OSPMBA) & 0xFFFF;
-
-       /* Force power on for now */
-       pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
-       pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
-
-       outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
-       for (i = 0; i < 5; i++) {
-               u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
-               if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
-                       break;
-               udelay(10);
-       }
-       pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
-       pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
-       outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
-       for (i = 0; i < 5; i++) {
-               u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-               if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
-                       break;
-               udelay(10);
-       }
-}
-
-/**
- *     cdv_save_display_registers      -       save registers lost on suspend
- *     @dev: our DRM device
- *
- *     Save the state we need in order to be able to restore the interface
- *     upon resume from suspend
- *
- *     FIXME: review
- */
-static int cdv_save_display_registers(struct drm_device *dev)
-{
-       return 0;
-}
-
-/**
- *     cdv_restore_display_registers   -       restore lost register state
- *     @dev: our DRM device
- *
- *     Restore register state that was lost during suspend and resume.
- *
- *     FIXME: review
- */
-static int cdv_restore_display_registers(struct drm_device *dev)
-{
-       return 0;
-}
-
-static int cdv_power_down(struct drm_device *dev)
-{
-       return 0;
-}
-
-static int cdv_power_up(struct drm_device *dev)
-{
-       return 0;
-}
-
-/* FIXME ? - shared with Poulsbo */
-static void cdv_get_core_freq(struct drm_device *dev)
-{
-       uint32_t clock;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
-       pci_read_config_dword(pci_root, 0xD4, &clock);
-       pci_dev_put(pci_root);
-
-       switch (clock & 0x07) {
-       case 0:
-               dev_priv->core_freq = 100;
-               break;
-       case 1:
-               dev_priv->core_freq = 133;
-               break;
-       case 2:
-               dev_priv->core_freq = 150;
-               break;
-       case 3:
-               dev_priv->core_freq = 178;
-               break;
-       case 4:
-               dev_priv->core_freq = 200;
-               break;
-       case 5:
-       case 6:
-       case 7:
-               dev_priv->core_freq = 266;
-       default:
-               dev_priv->core_freq = 0;
-       }
-}
-
-static int cdv_chip_setup(struct drm_device *dev)
-{
-       cdv_get_core_freq(dev);
-       gma_intel_opregion_init(dev);
-       psb_intel_init_bios(dev);
-       return 0;
-}
-
-/* CDV is much like Poulsbo but has MID like SGX offsets and PM */
-
-const struct psb_ops cdv_chip_ops = {
-       .name = "Cedartrail",
-       .accel_2d = 0,
-       .pipes = 2,
-       .sgx_offset = MRST_SGX_OFFSET,
-       .chip_setup = cdv_chip_setup,
-
-       .crtc_helper = &cdv_intel_helper_funcs,
-       .crtc_funcs = &cdv_intel_crtc_funcs,
-
-       .output_init = cdv_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       .backlight_init = cdv_backlight_init,
-#endif
-
-       .init_pm = cdv_init_pm,
-       .save_regs = cdv_save_display_registers,
-       .restore_regs = cdv_restore_display_registers,
-       .power_down = cdv_power_down,
-       .power_up = cdv_power_up,
-};
diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h
deleted file mode 100644 (file)
index 2a88b7b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright Â© 2011 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
-extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
-extern void cdv_intel_crt_init(struct drm_device *dev,
-                       struct psb_intel_mode_device *mode_dev);
-extern void cdv_intel_lvds_init(struct drm_device *dev,
-                       struct psb_intel_mode_device *mode_dev);
-extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev,
-                       int reg);
-extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
-                                            struct drm_crtc *crtc);
-
-extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
-{
-       /* Wait for 20ms, i.e. one cycle at 50hz. */
-        /* FIXME: msleep ?? */
-       mdelay(20);
-}
-
-
diff --git a/drivers/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c
deleted file mode 100644 (file)
index efda63b..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright Â© 2006-2007 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-
-static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       u32 temp, reg;
-       reg = ADPA;
-
-       temp = REG_READ(reg);
-       temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-       temp &= ~ADPA_DAC_ENABLE;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               temp |= ADPA_DAC_ENABLE;
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-               temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
-               break;
-       case DRM_MODE_DPMS_SUSPEND:
-               temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
-               break;
-       case DRM_MODE_DPMS_OFF:
-               temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-               break;
-       }
-
-       REG_WRITE(reg, temp);
-}
-
-static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
-{
-       int max_clock = 0;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return MODE_NO_DBLESCAN;
-
-       /* The lowest clock for CDV is 20000KHz */
-       if (mode->clock < 20000)
-               return MODE_CLOCK_LOW;
-
-       /* The max clock for CDV is 355 instead of 400 */
-       max_clock = 355000;
-       if (mode->clock > max_clock)
-               return MODE_CLOCK_HIGH;
-
-       if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
-               return MODE_PANEL;
-
-       return MODE_OK;
-}
-
-static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
-                                struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static void cdv_intel_crt_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_crtc *crtc = encoder->crtc;
-       struct psb_intel_crtc *psb_intel_crtc =
-                                       to_psb_intel_crtc(crtc);
-       int dpll_md_reg;
-       u32 adpa, dpll_md;
-       u32 adpa_reg;
-
-       if (psb_intel_crtc->pipe == 0)
-               dpll_md_reg = DPLL_A_MD;
-       else
-               dpll_md_reg = DPLL_B_MD;
-
-       adpa_reg = ADPA;
-
-       /*
-        * Disable separate mode multiplier used when cloning SDVO to CRT
-        * XXX this needs to be adjusted when we really are cloning
-        */
-       {
-               dpll_md = REG_READ(dpll_md_reg);
-               REG_WRITE(dpll_md_reg,
-                          dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
-       }
-
-       adpa = 0;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-               adpa |= ADPA_HSYNC_ACTIVE_HIGH;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-               adpa |= ADPA_VSYNC_ACTIVE_HIGH;
-
-       if (psb_intel_crtc->pipe == 0)
-               adpa |= ADPA_PIPE_A_SELECT;
-       else
-               adpa |= ADPA_PIPE_B_SELECT;
-
-       REG_WRITE(adpa_reg, adpa);
-}
-
-
-/**
- * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
- *
- * \return true if CRT is connected.
- * \return false if CRT is disconnected.
- */
-static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
-                                                               bool force)
-{
-       struct drm_device *dev = connector->dev;
-       u32 hotplug_en;
-       int i, tries = 0, ret = false;
-       u32 adpa_orig;
-
-       /* disable the DAC when doing the hotplug detection */
-
-       adpa_orig = REG_READ(ADPA);
-
-       REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
-
-       /*
-        * On a CDV thep, CRT detect sequence need to be done twice
-        * to get a reliable result.
-        */
-       tries = 2;
-
-       hotplug_en = REG_READ(PORT_HOTPLUG_EN);
-       hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
-       hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
-
-       hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
-       for (i = 0; i < tries ; i++) {
-               unsigned long timeout;
-               /* turn on the FORCE_DETECT */
-               REG_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-               timeout = jiffies + msecs_to_jiffies(1000);
-               /* wait for FORCE_DETECT to go off */
-               do {
-                       if (!(REG_READ(PORT_HOTPLUG_EN) &
-                                       CRT_HOTPLUG_FORCE_DETECT))
-                               break;
-                       msleep(1);
-               } while (time_after(timeout, jiffies));
-       }
-
-       if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
-           CRT_HOTPLUG_MONITOR_NONE)
-               ret = true;
-
-       /* Restore the saved ADPA */
-       REG_WRITE(ADPA, adpa_orig);
-       return ret;
-}
-
-static enum drm_connector_status cdv_intel_crt_detect(
-                               struct drm_connector *connector, bool force)
-{
-       if (cdv_intel_crt_detect_hotplug(connector, force))
-               return connector_status_connected;
-       else
-               return connector_status_disconnected;
-}
-
-static void cdv_intel_crt_destroy(struct drm_connector *connector)
-{
-       struct psb_intel_output *intel_output = to_psb_intel_output(connector);
-
-       psb_intel_i2c_destroy(intel_output->ddc_bus);
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
-static int cdv_intel_crt_get_modes(struct drm_connector *connector)
-{
-       struct psb_intel_output *intel_output =
-                               to_psb_intel_output(connector);
-       return psb_intel_ddc_get_modes(intel_output);
-}
-
-static int cdv_intel_crt_set_property(struct drm_connector *connector,
-                                 struct drm_property *property,
-                                 uint64_t value)
-{
-       return 0;
-}
-
-/*
- * Routines for controlling stuff on the analog port
- */
-
-static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
-       .dpms = cdv_intel_crt_dpms,
-       .mode_fixup = cdv_intel_crt_mode_fixup,
-       .prepare = psb_intel_encoder_prepare,
-       .commit = psb_intel_encoder_commit,
-       .mode_set = cdv_intel_crt_mode_set,
-};
-
-static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .detect = cdv_intel_crt_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = cdv_intel_crt_destroy,
-       .set_property = cdv_intel_crt_set_property,
-};
-
-static const struct drm_connector_helper_funcs
-                               cdv_intel_crt_connector_helper_funcs = {
-       .mode_valid = cdv_intel_crt_mode_valid,
-       .get_modes = cdv_intel_crt_get_modes,
-       .best_encoder = psb_intel_best_encoder,
-};
-
-static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = {
-       .destroy = cdv_intel_crt_enc_destroy,
-};
-
-void cdv_intel_crt_init(struct drm_device *dev,
-                       struct psb_intel_mode_device *mode_dev)
-{
-
-       struct psb_intel_output *psb_intel_output;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-
-       u32 i2c_reg;
-
-       psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       psb_intel_output->mode_dev = mode_dev;
-       connector = &psb_intel_output->base;
-       drm_connector_init(dev, connector,
-               &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
-
-       encoder = &psb_intel_output->enc;
-       drm_encoder_init(dev, encoder,
-               &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-
-       /* Set up the DDC bus. */
-       i2c_reg = GPIOA;
-       /* Remove the following code for CDV */
-       /*
-       if (dev_priv->crt_ddc_bus != 0)
-               i2c_reg = dev_priv->crt_ddc_bus;
-       }*/
-       psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
-                                               i2c_reg, "CRTDDC_A");
-       if (!psb_intel_output->ddc_bus) {
-               dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
-                          "failed.\n");
-               goto failed_ddc;
-       }
-
-       psb_intel_output->type = INTEL_OUTPUT_ANALOG;
-       /*
-       psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
-       psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
-       */
-       connector->interlace_allowed = 0;
-       connector->doublescan_allowed = 0;
-
-       drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs);
-       drm_connector_helper_add(connector,
-                                       &cdv_intel_crt_connector_helper_funcs);
-
-       drm_sysfs_connector_add(connector);
-
-       return;
-failed_ddc:
-       drm_encoder_cleanup(&psb_intel_output->enc);
-       drm_connector_cleanup(&psb_intel_output->base);
-       kfree(psb_intel_output);
-       return;
-}
diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c
deleted file mode 100644 (file)
index c63a327..0000000
+++ /dev/null
@@ -1,1508 +0,0 @@
-/*
- * Copyright Â© 2006-2011 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "framebuffer.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-#include "cdv_device.h"
-
-
-struct cdv_intel_range_t {
-       int min, max;
-};
-
-struct cdv_intel_p2_t {
-       int dot_limit;
-       int p2_slow, p2_fast;
-};
-
-struct cdv_intel_clock_t {
-       /* given values */
-       int n;
-       int m1, m2;
-       int p1, p2;
-       /* derived values */
-       int dot;
-       int vco;
-       int m;
-       int p;
-};
-
-#define INTEL_P2_NUM                 2
-
-struct cdv_intel_limit_t {
-       struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
-       struct cdv_intel_p2_t p2;
-};
-
-#define CDV_LIMIT_SINGLE_LVDS_96       0
-#define CDV_LIMIT_SINGLE_LVDS_100      1
-#define CDV_LIMIT_DAC_HDMI_27          2
-#define CDV_LIMIT_DAC_HDMI_96          3
-
-static const struct cdv_intel_limit_t cdv_intel_limits[] = {
-       {                       /* CDV_SIGNLE_LVDS_96MHz */
-        .dot = {.min = 20000, .max = 115500},
-        .vco = {.min = 1800000, .max = 3600000},
-        .n = {.min = 2, .max = 6},
-        .m = {.min = 60, .max = 160},
-        .m1 = {.min = 0, .max = 0},
-        .m2 = {.min = 58, .max = 158},
-        .p = {.min = 28, .max = 140},
-        .p1 = {.min = 2, .max = 10},
-        .p2 = {.dot_limit = 200000,
-               .p2_slow = 14, .p2_fast = 14},
-        },
-       {                       /* CDV_SINGLE_LVDS_100MHz */
-        .dot = {.min = 20000, .max = 115500},
-        .vco = {.min = 1800000, .max = 3600000},
-        .n = {.min = 2, .max = 6},
-        .m = {.min = 60, .max = 160},
-        .m1 = {.min = 0, .max = 0},
-        .m2 = {.min = 58, .max = 158},
-        .p = {.min = 28, .max = 140},
-        .p1 = {.min = 2, .max = 10},
-        /* The single-channel range is 25-112Mhz, and dual-channel
-         * is 80-224Mhz.  Prefer single channel as much as possible.
-         */
-        .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
-        },
-       {                       /* CDV_DAC_HDMI_27MHz */
-        .dot = {.min = 20000, .max = 400000},
-        .vco = {.min = 1809000, .max = 3564000},
-        .n = {.min = 1, .max = 1},
-        .m = {.min = 67, .max = 132},
-        .m1 = {.min = 0, .max = 0},
-        .m2 = {.min = 65, .max = 130},
-        .p = {.min = 5, .max = 90},
-        .p1 = {.min = 1, .max = 9},
-        .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
-        },
-       {                       /* CDV_DAC_HDMI_96MHz */
-        .dot = {.min = 20000, .max = 400000},
-        .vco = {.min = 1800000, .max = 3600000},
-        .n = {.min = 2, .max = 6},
-        .m = {.min = 60, .max = 160},
-        .m1 = {.min = 0, .max = 0},
-        .m2 = {.min = 58, .max = 158},
-        .p = {.min = 5, .max = 100},
-        .p1 = {.min = 1, .max = 10},
-        .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
-        },
-};
-
-#define _wait_for(COND, MS, W) ({ \
-       unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);       \
-       int ret__ = 0;                                                  \
-       while (!(COND)) {                                               \
-               if (time_after(jiffies, timeout__)) {                   \
-                       ret__ = -ETIMEDOUT;                             \
-                       break;                                          \
-               }                                                       \
-               if (W && !in_dbg_master())                              \
-                       msleep(W);                                      \
-       }                                                               \
-       ret__;                                                          \
-})
-
-#define wait_for(COND, MS) _wait_for(COND, MS, 1)
-
-
-static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
-{
-       int ret;
-
-       ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
-       if (ret) {
-               DRM_ERROR("timeout waiting for SB to idle before read\n");
-               return ret;
-       }
-
-       REG_WRITE(SB_ADDR, reg);
-       REG_WRITE(SB_PCKT,
-                  SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
-                  SET_FIELD(SB_DEST_DPLL, SB_DEST) |
-                  SET_FIELD(0xf, SB_BYTE_ENABLE));
-
-       ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
-       if (ret) {
-               DRM_ERROR("timeout waiting for SB to idle after read\n");
-               return ret;
-       }
-
-       *val = REG_READ(SB_DATA);
-
-       return 0;
-}
-
-static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
-{
-       int ret;
-       static bool dpio_debug = true;
-       u32 temp;
-
-       if (dpio_debug) {
-               if (cdv_sb_read(dev, reg, &temp) == 0)
-                       DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
-               DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
-       }
-
-       ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
-       if (ret) {
-               DRM_ERROR("timeout waiting for SB to idle before write\n");
-               return ret;
-       }
-
-       REG_WRITE(SB_ADDR, reg);
-       REG_WRITE(SB_DATA, val);
-       REG_WRITE(SB_PCKT,
-                  SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
-                  SET_FIELD(SB_DEST_DPLL, SB_DEST) |
-                  SET_FIELD(0xf, SB_BYTE_ENABLE));
-
-       ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
-       if (ret) {
-               DRM_ERROR("timeout waiting for SB to idle after write\n");
-               return ret;
-       }
-
-       if (dpio_debug) {
-               if (cdv_sb_read(dev, reg, &temp) == 0)
-                       DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
-       }
-
-       return 0;
-}
-
-/* Reset the DPIO configuration register.  The BIOS does this at every
- * mode set.
- */
-static void cdv_sb_reset(struct drm_device *dev)
-{
-
-       REG_WRITE(DPIO_CFG, 0);
-       REG_READ(DPIO_CFG);
-       REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
-}
-
-/* Unlike most Intel display engines, on Cedarview the DPLL registers
- * are behind this sideband bus.  They must be programmed while the
- * DPLL reference clock is on in the DPLL control register, but before
- * the DPLL is enabled in the DPLL control register.
- */
-static int
-cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
-                              struct cdv_intel_clock_t *clock)
-{
-       struct psb_intel_crtc *psb_crtc =
-                               to_psb_intel_crtc(crtc);
-       int pipe = psb_crtc->pipe;
-       u32 m, n_vco, p;
-       int ret = 0;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       u32 ref_value;
-
-       cdv_sb_reset(dev);
-
-       if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
-               DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
-               return -EBUSY;
-       }
-
-       /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
-       ref_value = 0x68A701;
-
-       cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
-
-       /* We don't know what the other fields of these regs are, so
-        * leave them in place.
-        */
-       ret = cdv_sb_read(dev, SB_M(pipe), &m);
-       if (ret)
-               return ret;
-       m &= ~SB_M_DIVIDER_MASK;
-       m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
-       ret = cdv_sb_write(dev, SB_M(pipe), m);
-       if (ret)
-               return ret;
-
-       ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
-       if (ret)
-               return ret;
-
-       /* Follow the BIOS to program the N_DIVIDER REG */
-       n_vco &= 0xFFFF;
-       n_vco |= 0x107;
-       n_vco &= ~(SB_N_VCO_SEL_MASK |
-                  SB_N_DIVIDER_MASK |
-                  SB_N_CB_TUNE_MASK);
-
-       n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
-
-       if (clock->vco < 2250000) {
-               n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
-               n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
-       } else if (clock->vco < 2750000) {
-               n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
-               n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
-       } else if (clock->vco < 3300000) {
-               n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
-               n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
-       } else {
-               n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
-               n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
-       }
-
-       ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
-       if (ret)
-               return ret;
-
-       ret = cdv_sb_read(dev, SB_P(pipe), &p);
-       if (ret)
-               return ret;
-       p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
-       p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
-       switch (clock->p2) {
-       case 5:
-               p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
-               break;
-       case 10:
-               p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
-               break;
-       case 14:
-               p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
-               break;
-       case 7:
-               p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
-               break;
-       default:
-               DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
-               return -EINVAL;
-       }
-       ret = cdv_sb_write(dev, SB_P(pipe), p);
-       if (ret)
-               return ret;
-
-       /* always Program the Lane Register for the Pipe A*/
-       if (pipe == 0) {
-               /* Program the Lane0/1 for HDMI B */
-               u32 lane_reg, lane_value;
-
-               lane_reg = PSB_LANE0;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-
-               lane_reg = PSB_LANE1;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-
-               /* Program the Lane2/3 for HDMI C */
-               lane_reg = PSB_LANE2;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-
-               lane_reg = PSB_LANE3;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-       }
-
-       return 0;
-}
-
-/*
- * Returns whether any output on the specified pipe is of the specified type
- */
-bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *l_entry;
-
-       list_for_each_entry(l_entry, &mode_config->connector_list, head) {
-               if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
-                       struct psb_intel_output *psb_intel_output =
-                           to_psb_intel_output(l_entry);
-                       if (psb_intel_output->type == type)
-                               return true;
-               }
-       }
-       return false;
-}
-
-static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
-                                                       int refclk)
-{
-       const struct cdv_intel_limit_t *limit;
-       if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               /*
-                * Now only single-channel LVDS is supported on CDV. If it is
-                * incorrect, please add the dual-channel LVDS.
-                */
-               if (refclk == 96000)
-                       limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
-               else
-                       limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
-       } else {
-               if (refclk == 27000)
-                       limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
-               else
-                       limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
-       }
-       return limit;
-}
-
-/* m1 is reserved as 0 in CDV, n is a ring counter */
-static void cdv_intel_clock(struct drm_device *dev,
-                       int refclk, struct cdv_intel_clock_t *clock)
-{
-       clock->m = clock->m2 + 2;
-       clock->p = clock->p1 * clock->p2;
-       clock->vco = (refclk * clock->m) / clock->n;
-       clock->dot = clock->vco / clock->p;
-}
-
-
-#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
-static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
-                               const struct cdv_intel_limit_t *limit,
-                              struct cdv_intel_clock_t *clock)
-{
-       if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
-               INTELPllInvalid("p1 out of range\n");
-       if (clock->p < limit->p.min || limit->p.max < clock->p)
-               INTELPllInvalid("p out of range\n");
-       /* unnecessary to check the range of m(m1/M2)/n again */
-       if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
-               INTELPllInvalid("vco out of range\n");
-       /* XXX: We may need to be checking "Dot clock"
-        * depending on the multiplier, connector, etc.,
-        * rather than just a single range.
-        */
-       if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
-               INTELPllInvalid("dot out of range\n");
-
-       return true;
-}
-
-static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
-                               int refclk,
-                               struct cdv_intel_clock_t *best_clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct cdv_intel_clock_t clock;
-       const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
-       int err = target;
-
-
-       if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-           (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
-               /*
-                * For LVDS, if the panel is on, just rely on its current
-                * settings for dual-channel.  We haven't figured out how to
-                * reliably set up different single/dual channel state, if we
-                * even can.
-                */
-               if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
-                       clock.p2 = limit->p2.p2_fast;
-               else
-                       clock.p2 = limit->p2.p2_slow;
-       } else {
-               if (target < limit->p2.dot_limit)
-                       clock.p2 = limit->p2.p2_slow;
-               else
-                       clock.p2 = limit->p2.p2_fast;
-       }
-
-       memset(best_clock, 0, sizeof(*best_clock));
-       clock.m1 = 0;
-       /* m1 is reserved as 0 in CDV, n is a ring counter.
-          So skip the m1 loop */
-       for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
-               for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
-                                            clock.m2++) {
-                       for (clock.p1 = limit->p1.min;
-                                       clock.p1 <= limit->p1.max;
-                                       clock.p1++) {
-                               int this_err;
-
-                               cdv_intel_clock(dev, refclk, &clock);
-
-                               if (!cdv_intel_PLL_is_valid(crtc,
-                                                               limit, &clock))
-                                               continue;
-
-                               this_err = abs(clock.dot - target);
-                               if (this_err < err) {
-                                       *best_clock = clock;
-                                       err = this_err;
-                               }
-                       }
-               }
-       }
-
-       return err != target;
-}
-
-int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
-                           int x, int y, struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
-       int pipe = psb_intel_crtc->pipe;
-       unsigned long start, offset;
-       int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
-       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       u32 dspcntr;
-       int ret = 0;
-
-       if (!gma_power_begin(dev, true))
-               return 0;
-
-       /* no fb bound */
-       if (!crtc->fb) {
-               dev_err(dev->dev, "No FB bound\n");
-               goto psb_intel_pipe_cleaner;
-       }
-
-
-       /* We are displaying this buffer, make sure it is actually loaded
-          into the GTT */
-       ret = psb_gtt_pin(psbfb->gtt);
-       if (ret < 0)
-               goto psb_intel_pipe_set_base_exit;
-       start = psbfb->gtt->offset;
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
-
-       dspcntr = REG_READ(dspcntr_reg);
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               dspcntr |= DISPPLANE_8BPP;
-               break;
-       case 16:
-               if (crtc->fb->depth == 15)
-                       dspcntr |= DISPPLANE_15_16BPP;
-               else
-                       dspcntr |= DISPPLANE_16BPP;
-               break;
-       case 24:
-       case 32:
-               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-               break;
-       default:
-               dev_err(dev->dev, "Unknown color depth\n");
-               ret = -EINVAL;
-               goto psb_intel_pipe_set_base_exit;
-       }
-       REG_WRITE(dspcntr_reg, dspcntr);
-
-       dev_dbg(dev->dev,
-               "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
-
-       REG_WRITE(dspbase, offset);
-       REG_READ(dspbase);
-       REG_WRITE(dspsurf, start);
-       REG_READ(dspsurf);
-
-psb_intel_pipe_cleaner:
-       /* If there was a previous display we can now unpin it */
-       if (old_fb)
-               psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
-       gma_power_end(dev);
-       return ret;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       u32 temp;
-       bool enabled;
-
-       /* XXX: When our outputs are all unaware of DPMS modes other than off
-        * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-        */
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-               /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-               }
-
-               /* Jim Bish - switch plan and pipe per scott */
-               /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp | DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-               }
-
-               udelay(150);
-
-               /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) == 0)
-                       REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
-
-               psb_intel_crtc_load_lut(crtc);
-
-               /* Give the overlay scaler a chance to enable
-                * if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, true); TODO */
-               break;
-       case DRM_MODE_DPMS_OFF:
-               /* Give the overlay scaler a chance to disable
-                * if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-
-               /* Disable the VGA plane that we never use */
-               REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
-               /* Jim Bish - changed pipe/plane here as well. */
-
-               /* Wait for vblank for the disable to take effect */
-               cdv_intel_wait_for_vblank(dev);
-
-               /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(pipeconf_reg);
-               }
-
-               /* Wait for vblank for the disable to take effect. */
-               cdv_intel_wait_for_vblank(dev);
-
-               udelay(150);
-
-               /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp & ~DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
-               }
-
-               temp = REG_READ(dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) != 0) {
-                       REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-               }
-
-               /* Wait for the clocks to turn off. */
-               udelay(150);
-               break;
-       }
-       enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-       /*Set FIFO Watermarks*/
-       REG_WRITE(DSPARB, 0x3F3E);
-}
-
-static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
-{
-       struct drm_encoder_helper_funcs *encoder_funcs =
-           encoder->helper_private;
-       /* lvds has its own version of prepare see cdv_intel_lvds_prepare */
-       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-void cdv_intel_encoder_commit(struct drm_encoder *encoder)
-{
-       struct drm_encoder_helper_funcs *encoder_funcs =
-           encoder->helper_private;
-       /* lvds has its own version of commit see cdv_intel_lvds_commit */
-       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
-{
-       u32 pfit_control;
-
-       pfit_control = REG_READ(PFIT_CONTROL);
-
-       /* See if the panel fitter is in use */
-       if ((pfit_control & PFIT_ENABLE) == 0)
-               return -1;
-       return (pfit_control >> 29) & 0x3;
-}
-
-static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y,
-                              struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
-       int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-       int refclk;
-       struct cdv_intel_clock_t clock;
-       u32 dpll = 0, dspcntr, pipeconf;
-       bool ok, is_sdvo = false, is_dvo = false;
-       bool is_crt = false, is_lvds = false, is_tv = false;
-       bool is_hdmi = false;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *connector;
-
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               struct psb_intel_output *psb_intel_output =
-                   to_psb_intel_output(connector);
-
-               if (!connector->encoder
-                   || connector->encoder->crtc != crtc)
-                       continue;
-
-               switch (psb_intel_output->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_SDVO:
-                       is_sdvo = true;
-                       break;
-               case INTEL_OUTPUT_DVO:
-                       is_dvo = true;
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       is_tv = true;
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       is_crt = true;
-                       break;
-               case INTEL_OUTPUT_HDMI:
-                       is_hdmi = true;
-                       break;
-               }
-       }
-
-       refclk = 96000;
-
-       /* Hack selection about ref clk for CRT */
-       /* Select 27MHz as the reference clk for HDMI */
-       if (is_crt || is_hdmi)
-               refclk = 27000;
-
-       drm_mode_debug_printmodeline(adjusted_mode);
-
-       ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
-                                &clock);
-       if (!ok) {
-               dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
-               return 0;
-       }
-
-       dpll = DPLL_VGA_MODE_DIS;
-       if (is_tv) {
-               /* XXX: just matching BIOS for now */
-/*     dpll |= PLL_REF_INPUT_TVCLKINBC; */
-               dpll |= 3;
-       }
-               dpll |= PLL_REF_INPUT_DREFCLK;
-
-       dpll |= DPLL_SYNCLOCK_ENABLE;
-       dpll |= DPLL_VGA_MODE_DIS;
-       if (is_lvds)
-               dpll |= DPLLB_MODE_LVDS;
-       else
-               dpll |= DPLLB_MODE_DAC_SERIAL;
-       /* dpll |= (2 << 11); */
-
-       /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
-
-       /* Set up the display plane register */
-       dspcntr = DISPPLANE_GAMMA_ENABLE;
-
-       if (pipe == 0)
-               dspcntr |= DISPPLANE_SEL_PIPE_A;
-       else
-               dspcntr |= DISPPLANE_SEL_PIPE_B;
-
-       dspcntr |= DISPLAY_PLANE_ENABLE;
-       pipeconf |= PIPEACONF_ENABLE;
-
-       REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
-       REG_READ(dpll_reg);
-
-       cdv_dpll_set_clock_cdv(dev, crtc, &clock);
-
-       udelay(150);
-
-
-       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
-        * This is an exception to the general rule that mode_set doesn't turn
-        * things on.
-        */
-       if (is_lvds) {
-               u32 lvds = REG_READ(LVDS);
-
-               lvds |=
-                   LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
-                   LVDS_PIPEB_SELECT;
-               /* Set the B0-B3 data pairs corresponding to
-                * whether we're going to
-                * set the DPLLs for dual-channel mode or not.
-                */
-               if (clock.p2 == 7)
-                       lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-               else
-                       lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
-               /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-                * appropriately here, but we need to look more
-                * thoroughly into how panels behave in the two modes.
-                */
-
-               REG_WRITE(LVDS, lvds);
-               REG_READ(LVDS);
-       }
-
-       dpll |= DPLL_VCO_ENABLE;
-
-       /* Disable the panel fitter if it was on our pipe */
-       if (cdv_intel_panel_fitter_pipe(dev) == pipe)
-               REG_WRITE(PFIT_CONTROL, 0);
-
-       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
-       drm_mode_debug_printmodeline(mode);
-
-       REG_WRITE(dpll_reg,
-               (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
-       REG_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150); /* 42 usec w/o calibration, 110 with.  rounded up. */
-
-       if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
-               dev_err(dev->dev, "Failed to get DPLL lock\n");
-               return -EBUSY;
-       }
-
-       {
-               int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
-               REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
-       }
-
-       REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
-                 ((adjusted_mode->crtc_htotal - 1) << 16));
-       REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
-                 ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
-                 ((adjusted_mode->crtc_hsync_end - 1) << 16));
-       REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
-                 ((adjusted_mode->crtc_vtotal - 1) << 16));
-       REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
-                 ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
-                 ((adjusted_mode->crtc_vsync_end - 1) << 16));
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
-       REG_WRITE(dspsize_reg,
-                 ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-       REG_WRITE(dsppos_reg, 0);
-       REG_WRITE(pipesrc_reg,
-                 ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
-
-       cdv_intel_wait_for_vblank(dev);
-
-       REG_WRITE(dspcntr_reg, dspcntr);
-
-       /* Flush the plane changes */
-       {
-               struct drm_crtc_helper_funcs *crtc_funcs =
-                   crtc->helper_private;
-               crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-       }
-
-       cdv_intel_wait_for_vblank(dev);
-
-       return 0;
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv =
-                               (struct drm_psb_private *)dev->dev_private;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int palreg = PALETTE_A;
-       int i;
-
-       /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled)
-               return;
-
-       switch (psb_intel_crtc->pipe) {
-       case 0:
-               break;
-       case 1:
-               palreg = PALETTE_B;
-               break;
-       case 2:
-               palreg = PALETTE_C;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number.\n");
-               return;
-       }
-
-       if (gma_power_begin(dev, false)) {
-               for (i = 0; i < 256; i++) {
-                       REG_WRITE(palreg + 4 * i,
-                                 ((psb_intel_crtc->lut_r[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 16) |
-                                 ((psb_intel_crtc->lut_g[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 8) |
-                                 (psb_intel_crtc->lut_b[i] +
-                                 psb_intel_crtc->lut_adj[i]));
-               }
-               gma_power_end(dev);
-       } else {
-               for (i = 0; i < 256; i++) {
-                       dev_priv->save_palette_a[i] =
-                                 ((psb_intel_crtc->lut_r[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 16) |
-                                 ((psb_intel_crtc->lut_g[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 8) |
-                                 (psb_intel_crtc->lut_b[i] +
-                                 psb_intel_crtc->lut_adj[i]);
-               }
-
-       }
-}
-
-/**
- * Save HW states of giving crtc
- */
-static void cdv_intel_crtc_save(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private *dev_priv =
-                       (struct drm_psb_private *)dev->dev_private; */
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       int pipeA = (psb_intel_crtc->pipe == 0);
-       uint32_t paletteReg;
-       int i;
-
-       if (!crtc_state) {
-               dev_dbg(dev->dev, "No CRTC state found\n");
-               return;
-       }
-
-       crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
-       crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
-       crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
-       crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
-       crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
-       crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
-       crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
-       crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
-       crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
-       crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
-       crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
-       crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
-       crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
-
-       /*NOTE: DSPSIZE DSPPOS only for psb*/
-       crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
-       crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
-
-       crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
-
-       DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-                       crtc_state->saveDSPCNTR,
-                       crtc_state->savePIPECONF,
-                       crtc_state->savePIPESRC,
-                       crtc_state->saveFP0,
-                       crtc_state->saveFP1,
-                       crtc_state->saveDPLL,
-                       crtc_state->saveHTOTAL,
-                       crtc_state->saveHBLANK,
-                       crtc_state->saveHSYNC,
-                       crtc_state->saveVTOTAL,
-                       crtc_state->saveVBLANK,
-                       crtc_state->saveVSYNC,
-                       crtc_state->saveDSPSTRIDE,
-                       crtc_state->saveDSPSIZE,
-                       crtc_state->saveDSPPOS,
-                       crtc_state->saveDSPBASE
-               );
-
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
-       for (i = 0; i < 256; ++i)
-               crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
-}
-
-/**
- * Restore HW states of giving crtc
- */
-static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private * dev_priv =
-                               (struct drm_psb_private *)dev->dev_private; */
-       struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
-       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
-       int pipeA = (psb_intel_crtc->pipe == 0);
-       uint32_t paletteReg;
-       int i;
-
-       if (!crtc_state) {
-               dev_dbg(dev->dev, "No crtc state\n");
-               return;
-       }
-
-       DRM_DEBUG(
-               "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-               REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
-               REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
-               REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
-               REG_READ(pipeA ? FPA0 : FPB0),
-               REG_READ(pipeA ? FPA1 : FPB1),
-               REG_READ(pipeA ? DPLL_A : DPLL_B),
-               REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
-               REG_READ(pipeA ? HBLANK_A : HBLANK_B),
-               REG_READ(pipeA ? HSYNC_A : HSYNC_B),
-               REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
-               REG_READ(pipeA ? VBLANK_A : VBLANK_B),
-               REG_READ(pipeA ? VSYNC_A : VSYNC_B),
-               REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
-               REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
-               REG_READ(pipeA ? DSPAPOS : DSPBPOS),
-               REG_READ(pipeA ? DSPABASE : DSPBBASE)
-               );
-
-       DRM_DEBUG(
-               "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-               crtc_state->saveDSPCNTR,
-               crtc_state->savePIPECONF,
-               crtc_state->savePIPESRC,
-               crtc_state->saveFP0,
-               crtc_state->saveFP1,
-               crtc_state->saveDPLL,
-               crtc_state->saveHTOTAL,
-               crtc_state->saveHBLANK,
-               crtc_state->saveHSYNC,
-               crtc_state->saveVTOTAL,
-               crtc_state->saveVBLANK,
-               crtc_state->saveVSYNC,
-               crtc_state->saveDSPSTRIDE,
-               crtc_state->saveDSPSIZE,
-               crtc_state->saveDSPPOS,
-               crtc_state->saveDSPBASE
-               );
-
-
-       if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
-               REG_WRITE(pipeA ? DPLL_A : DPLL_B,
-                       crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
-               REG_READ(pipeA ? DPLL_A : DPLL_B);
-               DRM_DEBUG("write dpll: %x\n",
-                               REG_READ(pipeA ? DPLL_A : DPLL_B));
-               udelay(150);
-       }
-
-       REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
-       REG_READ(pipeA ? FPA0 : FPB0);
-
-       REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
-       REG_READ(pipeA ? FPA1 : FPB1);
-
-       REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
-       REG_READ(pipeA ? DPLL_A : DPLL_B);
-       udelay(150);
-
-       REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
-       REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
-       REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
-       REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
-       REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
-       REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
-       REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
-
-       REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
-       REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
-
-       REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-       REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
-
-       cdv_intel_wait_for_vblank(dev);
-
-       REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-
-       cdv_intel_wait_for_vblank(dev);
-
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
-       for (i = 0; i < 256; ++i)
-               REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
-}
-
-static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
-                                struct drm_file *file_priv,
-                                uint32_t handle,
-                                uint32_t width, uint32_t height)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
-       uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
-       uint32_t temp;
-       size_t addr = 0;
-       struct gtt_range *gt;
-       struct drm_gem_object *obj;
-       int ret;
-
-       /* if we want to turn of the cursor ignore width and height */
-       if (!handle) {
-               /* turn off the cursor */
-               temp = CURSOR_MODE_DISABLE;
-
-               if (gma_power_begin(dev, false)) {
-                       REG_WRITE(control, temp);
-                       REG_WRITE(base, 0);
-                       gma_power_end(dev);
-               }
-
-               /* unpin the old GEM object */
-               if (psb_intel_crtc->cursor_obj) {
-                       gt = container_of(psb_intel_crtc->cursor_obj,
-                                                       struct gtt_range, gem);
-                       psb_gtt_unpin(gt);
-                       drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-                       psb_intel_crtc->cursor_obj = NULL;
-               }
-
-               return 0;
-       }
-
-       /* Currently we only support 64x64 cursors */
-       if (width != 64 || height != 64) {
-               dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
-               return -EINVAL;
-       }
-
-       obj = drm_gem_object_lookup(dev, file_priv, handle);
-       if (!obj)
-               return -ENOENT;
-
-       if (obj->size < width * height * 4) {
-               dev_dbg(dev->dev, "buffer is to small\n");
-               return -ENOMEM;
-       }
-
-       gt = container_of(obj, struct gtt_range, gem);
-
-       /* Pin the memory into the GTT */
-       ret = psb_gtt_pin(gt);
-       if (ret) {
-               dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
-               return ret;
-       }
-
-       addr = gt->offset;      /* Or resource.start ??? */
-
-       psb_intel_crtc->cursor_addr = addr;
-
-       temp = 0;
-       /* set the pipe for the cursor */
-       temp |= (pipe << 28);
-       temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
-       if (gma_power_begin(dev, false)) {
-               REG_WRITE(control, temp);
-               REG_WRITE(base, addr);
-               gma_power_end(dev);
-       }
-
-       /* unpin the old GEM object */
-       if (psb_intel_crtc->cursor_obj) {
-               gt = container_of(psb_intel_crtc->cursor_obj,
-                                                       struct gtt_range, gem);
-               psb_gtt_unpin(gt);
-               drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-               psb_intel_crtc->cursor_obj = obj;
-       }
-       return 0;
-}
-
-static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       uint32_t temp = 0;
-       uint32_t adder;
-
-
-       if (x < 0) {
-               temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
-               x = -x;
-       }
-       if (y < 0) {
-               temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
-               y = -y;
-       }
-
-       temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
-       temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
-       adder = psb_intel_crtc->cursor_addr;
-
-       if (gma_power_begin(dev, false)) {
-               REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
-               REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
-               gma_power_end(dev);
-       }
-       return 0;
-}
-
-static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
-                        u16 *green, u16 *blue, uint32_t start, uint32_t size)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int i;
-       int end = (start + size > 256) ? 256 : start + size;
-
-       for (i = start; i < end; i++) {
-               psb_intel_crtc->lut_r[i] = red[i] >> 8;
-               psb_intel_crtc->lut_g[i] = green[i] >> 8;
-               psb_intel_crtc->lut_b[i] = blue[i] >> 8;
-       }
-
-       cdv_intel_crtc_load_lut(crtc);
-}
-
-static int cdv_crtc_set_config(struct drm_mode_set *set)
-{
-       int ret = 0;
-       struct drm_device *dev = set->crtc->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (!dev_priv->rpm_enabled)
-               return drm_crtc_helper_set_config(set);
-
-       pm_runtime_forbid(&dev->pdev->dev);
-
-       ret = drm_crtc_helper_set_config(set);
-
-       pm_runtime_allow(&dev->pdev->dev);
-
-       return ret;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-
-/* FIXME: why are we using this, should it be cdv_ in this tree ? */
-
-static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
-{
-       clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
-       clock->p = clock->p1 * clock->p2;
-       clock->vco = refclk * clock->m / (clock->n + 2);
-       clock->dot = clock->vco / clock->p;
-}
-
-/* Returns the clock of the currently programmed mode of the given pipe. */
-static int cdv_intel_crtc_clock_get(struct drm_device *dev,
-                               struct drm_crtc *crtc)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       u32 dpll;
-       u32 fp;
-       struct cdv_intel_clock_t clock;
-       bool is_lvds;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (gma_power_begin(dev, false)) {
-               dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
-               if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
-               else
-                       fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
-               is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
-               gma_power_end(dev);
-       } else {
-               dpll = (pipe == 0) ?
-                       dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
-
-               if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = (pipe == 0) ?
-                               dev_priv->saveFPA0 :
-                               dev_priv->saveFPB0;
-               else
-                       fp = (pipe == 0) ?
-                               dev_priv->saveFPA1 :
-                               dev_priv->saveFPB1;
-
-               is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
-       }
-
-       clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
-       clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
-       clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
-
-       if (is_lvds) {
-               clock.p1 =
-                   ffs((dpll &
-                        DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
-                       DPLL_FPA01_P1_POST_DIV_SHIFT);
-               if (clock.p1 == 0) {
-                       clock.p1 = 4;
-                       dev_err(dev->dev, "PLL %d\n", dpll);
-               }
-               clock.p2 = 14;
-
-               if ((dpll & PLL_REF_INPUT_MASK) ==
-                   PLLB_REF_INPUT_SPREADSPECTRUMIN) {
-                       /* XXX: might not be 66MHz */
-                       i8xx_clock(66000, &clock);
-               } else
-                       i8xx_clock(48000, &clock);
-       } else {
-               if (dpll & PLL_P1_DIVIDE_BY_TWO)
-                       clock.p1 = 2;
-               else {
-                       clock.p1 =
-                           ((dpll &
-                             DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
-                            DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
-               }
-               if (dpll & PLL_P2_DIVIDE_BY_4)
-                       clock.p2 = 4;
-               else
-                       clock.p2 = 2;
-
-               i8xx_clock(48000, &clock);
-       }
-
-       /* XXX: It would be nice to validate the clocks, but we can't reuse
-        * i830PllIsValid() because it relies on the xf86_config connector
-        * configuration being accurate, which it isn't necessarily.
-        */
-
-       return clock.dot;
-}
-
-/** Returns the currently programmed mode of the given pipe. */
-struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
-                                            struct drm_crtc *crtc)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       struct drm_display_mode *mode;
-       int htot;
-       int hsync;
-       int vtot;
-       int vsync;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (gma_power_begin(dev, false)) {
-               htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
-               hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
-               vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
-               vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
-               gma_power_end(dev);
-       } else {
-               htot = (pipe == 0) ?
-                       dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
-               hsync = (pipe == 0) ?
-                       dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
-               vtot = (pipe == 0) ?
-                       dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
-               vsync = (pipe == 0) ?
-                       dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
-       }
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode)
-               return NULL;
-
-       mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
-       mode->hdisplay = (htot & 0xffff) + 1;
-       mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
-       mode->hsync_start = (hsync & 0xffff) + 1;
-       mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
-       mode->vdisplay = (vtot & 0xffff) + 1;
-       mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
-       mode->vsync_start = (vsync & 0xffff) + 1;
-       mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       return mode;
-}
-
-static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-
-       kfree(psb_intel_crtc->crtc_state);
-       drm_crtc_cleanup(crtc);
-       kfree(psb_intel_crtc);
-}
-
-const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
-       .dpms = cdv_intel_crtc_dpms,
-       .mode_fixup = cdv_intel_crtc_mode_fixup,
-       .mode_set = cdv_intel_crtc_mode_set,
-       .mode_set_base = cdv_intel_pipe_set_base,
-       .prepare = cdv_intel_crtc_prepare,
-       .commit = cdv_intel_crtc_commit,
-};
-
-const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
-       .save = cdv_intel_crtc_save,
-       .restore = cdv_intel_crtc_restore,
-       .cursor_set = cdv_intel_crtc_cursor_set,
-       .cursor_move = cdv_intel_crtc_cursor_move,
-       .gamma_set = cdv_intel_crtc_gamma_set,
-       .set_config = cdv_crtc_set_config,
-       .destroy = cdv_intel_crtc_destroy,
-};
-
-/*
- * Set the default value of cursor control and base register
- * to zero. This is a workaround for h/w defect on oaktrail
- */
-void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
-{
-       uint32_t control;
-       uint32_t base;
-
-       switch (pipe) {
-       case 0:
-               control = CURACNTR;
-               base = CURABASE;
-               break;
-       case 1:
-               control = CURBCNTR;
-               base = CURBBASE;
-               break;
-       case 2:
-               control = CURCCNTR;
-               base = CURCBASE;
-               break;
-       default:
-               return;
-       }
-
-       REG_WRITE(control, 0);
-       REG_WRITE(base, 0);
-}
-
diff --git a/drivers/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c
deleted file mode 100644 (file)
index cbca2b0..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright Â© 2006-2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     jim liu <jim.liu@intel.com>
- *
- * FIXME:
- *     We should probably make this generic and share it with Medfield
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-#include "psb_intel_drv.h"
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include <linux/pm_runtime.h>
-
-/* hdmi control bits */
-#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
-#define HDMI_BORDER_ENABLE             (1 << 7)
-#define HDMI_AUDIO_ENABLE              (1 << 6)
-#define HDMI_VSYNC_ACTIVE_HIGH         (1 << 4)
-#define HDMI_HSYNC_ACTIVE_HIGH         (1 << 3)
-/* hdmi-b control bits */
-#define        HDMIB_PIPE_B_SELECT             (1 << 30)
-
-
-struct mid_intel_hdmi_priv {
-       u32 hdmi_reg;
-       u32 save_HDMIB;
-       bool has_hdmi_sink;
-       bool has_hdmi_audio;
-       /* Should set this when detect hotplug */
-       bool hdmi_device_connected;
-       struct mdfld_hdmi_i2c *i2c_bus;
-       struct i2c_adapter *hdmi_i2c_adapter;   /* for control functions */
-       struct drm_device *dev;
-};
-
-static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
-       u32 hdmib;
-       struct drm_crtc *crtc = encoder->crtc;
-       struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
-
-       hdmib = (2 << 10);
-
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-               hdmib |= HDMI_VSYNC_ACTIVE_HIGH;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-               hdmib |= HDMI_HSYNC_ACTIVE_HIGH;
-
-       if (intel_crtc->pipe == 1)
-               hdmib |= HDMIB_PIPE_B_SELECT;
-
-       if (hdmi_priv->has_hdmi_audio) {
-               hdmib |= HDMI_AUDIO_ENABLE;
-               hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC;
-       }
-
-       REG_WRITE(hdmi_priv->hdmi_reg, hdmib);
-       REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
-       u32 hdmib;
-
-       hdmib = REG_READ(hdmi_priv->hdmi_reg);
-
-       if (mode != DRM_MODE_DPMS_ON)
-               REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN);
-       else
-               REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN);
-       REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static void cdv_hdmi_save(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct psb_intel_output *output = to_psb_intel_output(connector);
-       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
-
-       hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static void cdv_hdmi_restore(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct psb_intel_output *output = to_psb_intel_output(connector);
-       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
-
-       REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB);
-       REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static enum drm_connector_status cdv_hdmi_detect(
-                               struct drm_connector *connector, bool force)
-{
-       struct psb_intel_output *psb_intel_output =
-                                               to_psb_intel_output(connector);
-       struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv;
-       struct edid *edid = NULL;
-       enum drm_connector_status status = connector_status_disconnected;
-
-       edid = drm_get_edid(&psb_intel_output->base,
-                        psb_intel_output->hdmi_i2c_adapter);
-
-       hdmi_priv->has_hdmi_sink = false;
-       hdmi_priv->has_hdmi_audio = false;
-       if (edid) {
-               if (edid->input & DRM_EDID_INPUT_DIGITAL) {
-                       status = connector_status_connected;
-                       hdmi_priv->has_hdmi_sink =
-                                               drm_detect_hdmi_monitor(edid);
-                       hdmi_priv->has_hdmi_audio =
-                                               drm_detect_monitor_audio(edid);
-               }
-
-               psb_intel_output->base.display_info.raw_edid = NULL;
-               kfree(edid);
-       }
-       return status;
-}
-
-static int cdv_hdmi_set_property(struct drm_connector *connector,
-                                      struct drm_property *property,
-                                      uint64_t value)
-{
-       struct drm_encoder *encoder = connector->encoder;
-
-       if (!strcmp(property->name, "scaling mode") && encoder) {
-               struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc);
-               bool centre;
-               uint64_t curValue;
-
-               if (!crtc)
-                       return -1;
-
-               switch (value) {
-               case DRM_MODE_SCALE_FULLSCREEN:
-                       break;
-               case DRM_MODE_SCALE_NO_SCALE:
-                       break;
-               case DRM_MODE_SCALE_ASPECT:
-                       break;
-               default:
-                       return -1;
-               }
-
-               if (drm_connector_property_get_value(connector,
-                                                       property, &curValue))
-                       return -1;
-
-               if (curValue == value)
-                       return 0;
-
-               if (drm_connector_property_set_value(connector,
-                                                       property, value))
-                       return -1;
-
-               centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
-                       (value == DRM_MODE_SCALE_NO_SCALE);
-
-               if (crtc->saved_mode.hdisplay != 0 &&
-                   crtc->saved_mode.vdisplay != 0) {
-                       if (centre) {
-                               if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
-                                           encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
-                                       return -1;
-                       } else {
-                               struct drm_encoder_helper_funcs *helpers
-                                                   = encoder->helper_private;
-                               helpers->mode_set(encoder, &crtc->saved_mode,
-                                            &crtc->saved_adjusted_mode);
-                       }
-               }
-       }
-       return 0;
-}
-
-/*
- * Return the list of HDMI DDC modes if available.
- */
-static int cdv_hdmi_get_modes(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-       struct edid *edid = NULL;
-       int ret = 0;
-
-       edid = drm_get_edid(&psb_intel_output->base,
-                        psb_intel_output->hdmi_i2c_adapter);
-       if (edid) {
-               drm_mode_connector_update_edid_property(&psb_intel_output->
-                                                       base, edid);
-               ret = drm_add_edid_modes(&psb_intel_output->base, edid);
-               kfree(edid);
-       }
-       return ret;
-}
-
-static int cdv_hdmi_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
-{
-
-       if (mode->clock > 165000)
-               return MODE_CLOCK_HIGH;
-       if (mode->clock < 20000)
-               return MODE_CLOCK_HIGH;
-
-       /* just in case */
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return MODE_NO_DBLESCAN;
-
-       /* just in case */
-       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-               return MODE_NO_INTERLACE;
-
-       /*
-        * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it
-        * will go beyond the stolen memory size allocated to the framebuffer
-        */
-       if (mode->hdisplay > 1680)
-               return MODE_PANEL;
-       if (mode->vdisplay > 1050)
-               return MODE_PANEL;
-       return MODE_OK;
-}
-
-static void cdv_hdmi_destroy(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       if (psb_intel_output->ddc_bus)
-               psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
-static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
-       .dpms = cdv_hdmi_dpms,
-       .mode_fixup = cdv_hdmi_mode_fixup,
-       .prepare = psb_intel_encoder_prepare,
-       .mode_set = cdv_hdmi_mode_set,
-       .commit = psb_intel_encoder_commit,
-};
-
-static const struct drm_connector_helper_funcs
-                                       cdv_hdmi_connector_helper_funcs = {
-       .get_modes = cdv_hdmi_get_modes,
-       .mode_valid = cdv_hdmi_mode_valid,
-       .best_encoder = psb_intel_best_encoder,
-};
-
-static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .save = cdv_hdmi_save,
-       .restore = cdv_hdmi_restore,
-       .detect = cdv_hdmi_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .set_property = cdv_hdmi_set_property,
-       .destroy = cdv_hdmi_destroy,
-};
-
-void cdv_hdmi_init(struct drm_device *dev,
-                       struct psb_intel_mode_device *mode_dev, int reg)
-{
-       struct psb_intel_output *psb_intel_output;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-       struct mid_intel_hdmi_priv *hdmi_priv;
-       int ddc_bus;
-
-       psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
-                              sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
-       psb_intel_output->mode_dev = mode_dev;
-       connector = &psb_intel_output->base;
-       encoder = &psb_intel_output->enc;
-       drm_connector_init(dev, &psb_intel_output->base,
-                          &cdv_hdmi_connector_funcs,
-                          DRM_MODE_CONNECTOR_DVID);
-
-       drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
-                        DRM_MODE_ENCODER_TMDS);
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-       psb_intel_output->type = INTEL_OUTPUT_HDMI;
-       hdmi_priv->hdmi_reg = reg;
-       hdmi_priv->has_hdmi_sink = false;
-       psb_intel_output->dev_priv = hdmi_priv;
-
-       drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs);
-       drm_connector_helper_add(connector,
-                                &cdv_hdmi_connector_helper_funcs);
-       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-
-       drm_connector_attach_property(connector,
-           dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
-
-       switch (reg) {
-       case SDVOB:
-               ddc_bus = GPIOE;
-               break;
-       case SDVOC:
-               ddc_bus = GPIOD;
-               break;
-       default:
-               DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
-               goto failed_ddc;
-               break;
-       }
-
-       psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
-                               ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC");
-
-       if (!psb_intel_output->ddc_bus) {
-               dev_err(dev->dev, "No ddc adapter available!\n");
-               goto failed_ddc;
-       }
-       psb_intel_output->hdmi_i2c_adapter =
-                               &(psb_intel_output->ddc_bus->adapter);
-       hdmi_priv->dev = dev;
-       drm_sysfs_connector_add(connector);
-       return;
-
-failed_ddc:
-       drm_encoder_cleanup(&psb_intel_output->enc);
-       drm_connector_cleanup(&psb_intel_output->base);
-       kfree(psb_intel_output);
-}
diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c
deleted file mode 100644 (file)
index 988b2d0..0000000
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Copyright Â© 2006-2011 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- *     Dave Airlie <airlied@linux.ie>
- *     Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/dmi.h>
-#include <drm/drmP.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-#include "cdv_device.h"
-
-/**
- * LVDS I2C backlight control macros
- */
-#define BRIGHTNESS_MAX_LEVEL 100
-#define BRIGHTNESS_MASK 0xFF
-#define BLC_I2C_TYPE   0x01
-#define BLC_PWM_TYPT   0x02
-
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-
-#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
-#define PSB_BLC_MIN_PWM_REG_FREQ       (0x2)
-#define PSB_BLC_PWM_PRECISION_FACTOR   (10)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT    (16)
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-
-struct cdv_intel_lvds_priv {
-       /**
-        * Saved LVDO output states
-        */
-       uint32_t savePP_ON;
-       uint32_t savePP_OFF;
-       uint32_t saveLVDS;
-       uint32_t savePP_CONTROL;
-       uint32_t savePP_CYCLE;
-       uint32_t savePFIT_CONTROL;
-       uint32_t savePFIT_PGM_RATIOS;
-       uint32_t saveBLC_PWM_CTL;
-};
-
-/*
- * Returns the maximum level of the backlight duty cycle field.
- */
-static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 retval;
-
-       if (gma_power_begin(dev, false)) {
-               retval = ((REG_READ(BLC_PWM_CTL) &
-                         BACKLIGHT_MODULATION_FREQ_MASK) >>
-                         BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
-               gma_power_end(dev);
-       } else
-               retval = ((dev_priv->saveBLC_PWM_CTL &
-                         BACKLIGHT_MODULATION_FREQ_MASK) >>
-                         BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
-       return retval;
-}
-
-/*
- * Set LVDS backlight level by I2C command
- */
-static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
-                                       unsigned int level)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
-       u8 out_buf[2];
-       unsigned int blc_i2c_brightness;
-
-       struct i2c_msg msgs[] = {
-               {
-                       .addr = lvds_i2c_bus->slave_addr,
-                       .flags = 0,
-                       .len = 2,
-                       .buf = out_buf,
-               }
-       };
-
-       blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
-                            BRIGHTNESS_MASK /
-                            BRIGHTNESS_MAX_LEVEL);
-
-       if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
-               blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
-
-       out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
-       out_buf[1] = (u8)blc_i2c_brightness;
-
-       if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
-               return 0;
-
-       DRM_ERROR("I2C transfer error\n");
-       return -1;
-}
-
-
-static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       u32 max_pwm_blc;
-       u32 blc_pwm_duty_cycle;
-
-       max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
-
-       /*BLC_PWM_CTL Should be initiated while backlight device init*/
-       BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
-
-       blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
-
-       if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
-               blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
-
-       blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
-       REG_WRITE(BLC_PWM_CTL,
-                 (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
-                 (blc_pwm_duty_cycle));
-
-       return 0;
-}
-
-/*
- * Set LVDS backlight level either by I2C or PWM
- */
-void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (!dev_priv->lvds_bl) {
-               DRM_ERROR("NO LVDS Backlight Info\n");
-               return;
-       }
-
-       if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
-               cdv_lvds_i2c_set_brightness(dev, level);
-       else
-               cdv_lvds_pwm_set_brightness(dev, level);
-}
-
-/**
- * Sets the backlight level.
- *
- * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
- */
-static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 blc_pwm_ctl;
-
-       if (gma_power_begin(dev, false)) {
-               blc_pwm_ctl =
-                       REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
-               REG_WRITE(BLC_PWM_CTL,
-                               (blc_pwm_ctl |
-                               (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
-               gma_power_end(dev);
-       } else {
-               blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
-                               ~BACKLIGHT_DUTY_CYCLE_MASK;
-               dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
-                                       (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
-       }
-}
-
-/**
- * Sets the power state for the panel.
- */
-static void cdv_intel_lvds_set_power(struct drm_device *dev,
-                                struct psb_intel_output *output, bool on)
-{
-       u32 pp_status;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       if (on) {
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
-                         POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-
-               cdv_intel_lvds_set_backlight(dev,
-                                        output->
-                                        mode_dev->backlight_duty_cycle);
-       } else {
-               cdv_intel_lvds_set_backlight(dev, 0);
-
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
-                         ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while (pp_status & PP_ON);
-       }
-       gma_power_end(dev);
-}
-
-static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       if (mode == DRM_MODE_DPMS_ON)
-               cdv_intel_lvds_set_power(dev, output, true);
-       else
-               cdv_intel_lvds_set_power(dev, output, false);
-       /* XXX: We never power down the LVDS pairs. */
-}
-
-static void cdv_intel_lvds_save(struct drm_connector *connector)
-{
-}
-
-static void cdv_intel_lvds_restore(struct drm_connector *connector)
-{
-}
-
-int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
-{
-       struct psb_intel_output *psb_intel_output =
-                               to_psb_intel_output(connector);
-       struct drm_display_mode *fixed_mode =
-           psb_intel_output->mode_dev->panel_fixed_mode;
-
-       /* just in case */
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return MODE_NO_DBLESCAN;
-
-       /* just in case */
-       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-               return MODE_NO_INTERLACE;
-
-       if (fixed_mode) {
-               if (mode->hdisplay > fixed_mode->hdisplay)
-                       return MODE_PANEL;
-               if (mode->vdisplay > fixed_mode->vdisplay)
-                       return MODE_PANEL;
-       }
-       return MODE_OK;
-}
-
-bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       struct psb_intel_mode_device *mode_dev =
-           enc_to_psb_intel_output(encoder)->mode_dev;
-       struct drm_device *dev = encoder->dev;
-       struct drm_encoder *tmp_encoder;
-       struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
-
-       /* Should never happen!! */
-       list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
-                           head) {
-               if (tmp_encoder != encoder
-                   && tmp_encoder->crtc == encoder->crtc) {
-                       printk(KERN_ERR "Can't enable LVDS and another "
-                              "encoder on the same pipe\n");
-                       return false;
-               }
-       }
-
-       /*
-        * If we have timings from the BIOS for the panel, put them in
-        * to the adjusted mode.  The CRTC will be set up for this mode,
-        * with the panel scaling set up to source from the H/VDisplay
-        * of the original mode.
-        */
-       if (panel_fixed_mode != NULL) {
-               adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
-               adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
-               adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
-               adjusted_mode->htotal = panel_fixed_mode->htotal;
-               adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
-               adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
-               adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
-               adjusted_mode->vtotal = panel_fixed_mode->vtotal;
-               adjusted_mode->clock = panel_fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode,
-                                     CRTC_INTERLACE_HALVE_V);
-       }
-
-       /*
-        * XXX: It would be nice to support lower refresh rates on the
-        * panels to reduce power consumption, and perhaps match the
-        * user's requested refresh rate.
-        */
-
-       return true;
-}
-
-static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
-       mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
-                                         BACKLIGHT_DUTY_CYCLE_MASK);
-
-       cdv_intel_lvds_set_power(dev, output, false);
-
-       gma_power_end(dev);
-}
-
-static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
-       if (mode_dev->backlight_duty_cycle == 0)
-               mode_dev->backlight_duty_cycle =
-                   cdv_intel_lvds_get_max_backlight(dev);
-
-       cdv_intel_lvds_set_power(dev, output, true);
-}
-
-static void cdv_intel_lvds_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_psb_private *dev_priv = dev->dev_private;
-       u32 pfit_control;
-
-       /*
-        * The LVDS pin pair will already have been turned on in the
-        * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
-        * settings.
-        */
-
-       /*
-        * Enable automatic panel scaling so that non-native modes fill the
-        * screen.  Should be enabled before the pipe is enabled, according to
-        * register description and PRM.
-        */
-       if (mode->hdisplay != adjusted_mode->hdisplay ||
-           mode->vdisplay != adjusted_mode->vdisplay)
-               pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
-                               HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
-                               HORIZ_INTERP_BILINEAR);
-       else
-               pfit_control = 0;
-
-       if (dev_priv->lvds_dither)
-               pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
-       REG_WRITE(PFIT_CONTROL, pfit_control);
-}
-
-/**
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status cdv_intel_lvds_detect(
-                               struct drm_connector *connector, bool force)
-{
-       return connector_status_connected;
-}
-
-/**
- * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
- */
-static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-       struct psb_intel_mode_device *mode_dev =
-                                       psb_intel_output->mode_dev;
-       int ret;
-
-       ret = psb_intel_ddc_get_modes(psb_intel_output);
-
-       if (ret)
-               return ret;
-
-       /* Didn't get an EDID, so
-        * Set wide sync ranges so we get all modes
-        * handed to valid_mode for checking
-        */
-       connector->display_info.min_vfreq = 0;
-       connector->display_info.max_vfreq = 200;
-       connector->display_info.min_hfreq = 0;
-       connector->display_info.max_hfreq = 200;
-       if (mode_dev->panel_fixed_mode != NULL) {
-               struct drm_display_mode *mode =
-                   drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
-               drm_mode_probed_add(connector, mode);
-               return 1;
-       }
-
-       return 0;
-}
-
-/**
- * cdv_intel_lvds_destroy - unregister and free LVDS structures
- * @connector: connector to free
- *
- * Unregister the DDC bus for this connector then free the driver private
- * structure.
- */
-void cdv_intel_lvds_destroy(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       if (psb_intel_output->ddc_bus)
-               psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
-int cdv_intel_lvds_set_property(struct drm_connector *connector,
-                                      struct drm_property *property,
-                                      uint64_t value)
-{
-       struct drm_encoder *encoder = connector->encoder;
-
-       if (!strcmp(property->name, "scaling mode") && encoder) {
-               struct psb_intel_crtc *crtc =
-                                       to_psb_intel_crtc(encoder->crtc);
-               uint64_t curValue;
-
-               if (!crtc)
-                       return -1;
-
-               switch (value) {
-               case DRM_MODE_SCALE_FULLSCREEN:
-                       break;
-               case DRM_MODE_SCALE_NO_SCALE:
-                       break;
-               case DRM_MODE_SCALE_ASPECT:
-                       break;
-               default:
-                       return -1;
-               }
-
-               if (drm_connector_property_get_value(connector,
-                                                    property,
-                                                    &curValue))
-                       return -1;
-
-               if (curValue == value)
-                       return 0;
-
-               if (drm_connector_property_set_value(connector,
-                                                       property,
-                                                       value))
-                       return -1;
-
-               if (crtc->saved_mode.hdisplay != 0 &&
-                   crtc->saved_mode.vdisplay != 0) {
-                       if (!drm_crtc_helper_set_mode(encoder->crtc,
-                                                     &crtc->saved_mode,
-                                                     encoder->crtc->x,
-                                                     encoder->crtc->y,
-                                                     encoder->crtc->fb))
-                               return -1;
-               }
-       } else if (!strcmp(property->name, "backlight") && encoder) {
-               if (drm_connector_property_set_value(connector,
-                                                       property,
-                                                       value))
-                       return -1;
-               else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-                       struct drm_psb_private *dev_priv =
-                                               encoder->dev->dev_private;
-                       struct backlight_device *bd =
-                                               dev_priv->backlight_device;
-                       bd->props.brightness = value;
-                       backlight_update_status(bd);
-#endif
-               }
-       } else if (!strcmp(property->name, "DPMS") && encoder) {
-               struct drm_encoder_helper_funcs *helpers =
-                                       encoder->helper_private;
-               helpers->dpms(encoder, value);
-       }
-       return 0;
-}
-
-static const struct drm_encoder_helper_funcs
-                                       cdv_intel_lvds_helper_funcs = {
-       .dpms = cdv_intel_lvds_encoder_dpms,
-       .mode_fixup = cdv_intel_lvds_mode_fixup,
-       .prepare = cdv_intel_lvds_prepare,
-       .mode_set = cdv_intel_lvds_mode_set,
-       .commit = cdv_intel_lvds_commit,
-};
-
-static const struct drm_connector_helper_funcs
-                               cdv_intel_lvds_connector_helper_funcs = {
-       .get_modes = cdv_intel_lvds_get_modes,
-       .mode_valid = cdv_intel_lvds_mode_valid,
-       .best_encoder = psb_intel_best_encoder,
-};
-
-static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .save = cdv_intel_lvds_save,
-       .restore = cdv_intel_lvds_restore,
-       .detect = cdv_intel_lvds_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .set_property = cdv_intel_lvds_set_property,
-       .destroy = cdv_intel_lvds_destroy,
-};
-
-
-static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
-       .destroy = cdv_intel_lvds_enc_destroy,
-};
-
-/**
- * cdv_intel_lvds_init - setup LVDS connectors on this device
- * @dev: drm device
- *
- * Create the connector, register the LVDS DDC bus, and try to figure out what
- * modes we can display on the LVDS panel (if present).
- */
-void cdv_intel_lvds_init(struct drm_device *dev,
-                    struct psb_intel_mode_device *mode_dev)
-{
-       struct psb_intel_output *psb_intel_output;
-       struct cdv_intel_lvds_priv *lvds_priv;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-       struct drm_display_mode *scan;
-       struct drm_crtc *crtc;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 lvds;
-       int pipe;
-
-       psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
-                       sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
-
-       psb_intel_output->dev_priv = lvds_priv;
-
-       psb_intel_output->mode_dev = mode_dev;
-       connector = &psb_intel_output->base;
-       encoder = &psb_intel_output->enc;
-
-
-       drm_connector_init(dev, &psb_intel_output->base,
-                          &cdv_intel_lvds_connector_funcs,
-                          DRM_MODE_CONNECTOR_LVDS);
-
-       drm_encoder_init(dev, &psb_intel_output->enc,
-                        &cdv_intel_lvds_enc_funcs,
-                        DRM_MODE_ENCODER_LVDS);
-
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-       psb_intel_output->type = INTEL_OUTPUT_LVDS;
-
-       drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
-       drm_connector_helper_add(connector,
-                                &cdv_intel_lvds_connector_helper_funcs);
-       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-
-       /*Attach connector properties*/
-       drm_connector_attach_property(connector,
-                                     dev->mode_config.scaling_mode_property,
-                                     DRM_MODE_SCALE_FULLSCREEN);
-       drm_connector_attach_property(connector,
-                                     dev_priv->backlight_property,
-                                     BRIGHTNESS_MAX_LEVEL);
-
-       /**
-        * Set up I2C bus
-        * FIXME: distroy i2c_bus when exit
-        */
-       psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
-                                                        GPIOB,
-                                                        "LVDSBLC_B");
-       if (!psb_intel_output->i2c_bus) {
-               dev_printk(KERN_ERR,
-                       &dev->pdev->dev, "I2C bus registration failed.\n");
-               goto failed_blc_i2c;
-       }
-       psb_intel_output->i2c_bus->slave_addr = 0x2C;
-       dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus;
-
-       /*
-        * LVDS discovery:
-        * 1) check for EDID on DDC
-        * 2) check for VBT data
-        * 3) check to see if LVDS is already on
-        *    if none of the above, no panel
-        * 4) make sure lid is open
-        *    if closed, act like it's not there for now
-        */
-
-       /* Set up the DDC bus. */
-       psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
-                                                        GPIOC,
-                                                        "LVDSDDC_C");
-       if (!psb_intel_output->ddc_bus) {
-               dev_printk(KERN_ERR, &dev->pdev->dev,
-                          "DDC bus registration " "failed.\n");
-               goto failed_ddc;
-       }
-
-       /*
-        * Attempt to get the fixed panel mode from DDC.  Assume that the
-        * preferred mode is the right one.
-        */
-       psb_intel_ddc_get_modes(psb_intel_output);
-       list_for_each_entry(scan, &connector->probed_modes, head) {
-               if (scan->type & DRM_MODE_TYPE_PREFERRED) {
-                       mode_dev->panel_fixed_mode =
-                           drm_mode_duplicate(dev, scan);
-                       goto out;       /* FIXME: check for quirks */
-               }
-       }
-
-       /* Failed to get EDID, what about VBT? do we need this?*/
-       if (dev_priv->lfp_lvds_vbt_mode) {
-               mode_dev->panel_fixed_mode =
-                       drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
-               if (mode_dev->panel_fixed_mode) {
-                       mode_dev->panel_fixed_mode->type |=
-                               DRM_MODE_TYPE_PREFERRED;
-                       goto out;       /* FIXME: check for quirks */
-               }
-       }
-       /*
-        * If we didn't get EDID, try checking if the panel is already turned
-        * on.  If so, assume that whatever is currently programmed is the
-        * correct mode.
-        */
-       lvds = REG_READ(LVDS);
-       pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
-       crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
-
-       if (crtc && (lvds & LVDS_PORT_EN)) {
-               mode_dev->panel_fixed_mode =
-                   cdv_intel_crtc_mode_get(dev, crtc);
-               if (mode_dev->panel_fixed_mode) {
-                       mode_dev->panel_fixed_mode->type |=
-                           DRM_MODE_TYPE_PREFERRED;
-                       goto out;       /* FIXME: check for quirks */
-               }
-       }
-
-       /* If we still don't have a mode after all that, give up. */
-       if (!mode_dev->panel_fixed_mode) {
-               DRM_DEBUG
-                       ("Found no modes on the lvds, ignoring the LVDS\n");
-               goto failed_find;
-       }
-
-out:
-       drm_sysfs_connector_add(connector);
-       return;
-
-failed_find:
-       printk(KERN_ERR "Failed find\n");
-       if (psb_intel_output->ddc_bus)
-               psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-failed_ddc:
-       printk(KERN_ERR "Failed DDC\n");
-       if (psb_intel_output->i2c_bus)
-               psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-failed_blc_i2c:
-       printk(KERN_ERR "Failed BLC\n");
-       drm_encoder_cleanup(encoder);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h
deleted file mode 100644 (file)
index d58ba9b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef HDMI_H
-#define HDMI_H
-
-extern void hdmi_init(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h
deleted file mode 100644 (file)
index 84bae5c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef PYR_CMD_H
-#define PYR_CMD_H
-
-extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-
-#endif
-
diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h
deleted file mode 100644 (file)
index ce98860..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef PYR_VID_H
-#define PYR_VID_H
-
-extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h
deleted file mode 100644 (file)
index 641e85e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef TMD_CMD_H
-#define TMD_CMD_H
-
-extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h
deleted file mode 100644 (file)
index 7a5fa3b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef TMD_VID_H
-#define TMD_VID_H
-
-extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h
deleted file mode 100644 (file)
index 6105527..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef TPO_CMD_H
-#define TPO_CMD_H
-
-extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-/* extern struct drm_display_mode * */
-/* tpo_cmd_get_config_mode(struct drm_device *dev); */
-
-#endif
diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h
deleted file mode 100644 (file)
index c24f057..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef TPO_VID_H
-#define TPO_VID_H
-
-extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-
-#endif
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
deleted file mode 100644 (file)
index b00761c..0000000
+++ /dev/null
@@ -1,856 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "framebuffer.h"
-#include "gtt.h"
-
-#include "mdfld_output.h"
-
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-                                             struct drm_file *file_priv,
-                                             unsigned int *handle);
-
-static const struct drm_framebuffer_funcs psb_fb_funcs = {
-       .destroy = psb_user_framebuffer_destroy,
-       .create_handle = psb_user_framebuffer_create_handle,
-};
-
-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-                          unsigned blue, unsigned transp,
-                          struct fb_info *info)
-{
-       struct psb_fbdev *fbdev = info->par;
-       struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-       uint32_t v;
-
-       if (!fb)
-               return -ENOMEM;
-
-       if (regno > 255)
-               return 1;
-
-       red = CMAP_TOHW(red, info->var.red.length);
-       blue = CMAP_TOHW(blue, info->var.blue.length);
-       green = CMAP_TOHW(green, info->var.green.length);
-       transp = CMAP_TOHW(transp, info->var.transp.length);
-
-       v = (red << info->var.red.offset) |
-           (green << info->var.green.offset) |
-           (blue << info->var.blue.offset) |
-           (transp << info->var.transp.offset);
-
-       if (regno < 16) {
-               switch (fb->bits_per_pixel) {
-               case 16:
-                       ((uint32_t *) info->pseudo_palette)[regno] = v;
-                       break;
-               case 24:
-               case 32:
-                       ((uint32_t *) info->pseudo_palette)[regno] = v;
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-       struct psb_fbdev *fbdev = info->par;
-       struct psb_framebuffer *psbfb = &fbdev->pfb;
-       struct drm_device *dev = psbfb->base.dev;
-
-       /*
-        *      We have to poke our nose in here. The core fb code assumes
-        *      panning is part of the hardware that can be invoked before
-        *      the actual fb is mapped. In our case that isn't quite true.
-        */
-       if (psbfb->gtt->npage)
-               psb_gtt_roll(dev, psbfb->gtt, var->yoffset);
-       return 0;
-}
-
-void psbfb_suspend(struct drm_device *dev)
-{
-       struct drm_framebuffer *fb = 0;
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-       console_lock();
-       mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-               struct fb_info *info = psbfb->fbdev;
-               fb_set_suspend(info, 1);
-               drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
-       }
-       mutex_unlock(&dev->mode_config.mutex);
-       console_unlock();
-}
-
-void psbfb_resume(struct drm_device *dev)
-{
-       struct drm_framebuffer *fb = 0;
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-       console_lock();
-       mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-               struct fb_info *info = psbfb->fbdev;
-               fb_set_suspend(info, 0);
-               drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
-       }
-       mutex_unlock(&dev->mode_config.mutex);
-       console_unlock();
-       drm_helper_disable_unused_functions(dev);
-}
-
-static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct psb_framebuffer *psbfb = vma->vm_private_data;
-       struct drm_device *dev = psbfb->base.dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int page_num;
-       int i;
-       unsigned long address;
-       int ret;
-       unsigned long pfn;
-       /* FIXME: assumes fb at stolen base which may not be true */
-       unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
-
-       page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-       address = (unsigned long)vmf->virtual_address;
-
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-       for (i = 0; i < page_num; i++) {
-               pfn = (phys_addr >> PAGE_SHIFT);
-
-               ret = vm_insert_mixed(vma, address, pfn);
-               if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
-                       break;
-               else if (unlikely(ret != 0)) {
-                       ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
-                       return ret;
-               }
-               address += PAGE_SIZE;
-               phys_addr += PAGE_SIZE;
-       }
-       return VM_FAULT_NOPAGE;
-}
-
-static void psbfb_vm_open(struct vm_area_struct *vma)
-{
-}
-
-static void psbfb_vm_close(struct vm_area_struct *vma)
-{
-}
-
-static struct vm_operations_struct psbfb_vm_ops = {
-       .fault  = psbfb_vm_fault,
-       .open   = psbfb_vm_open,
-       .close  = psbfb_vm_close
-};
-
-static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-       struct psb_fbdev *fbdev = info->par;
-       struct psb_framebuffer *psbfb = &fbdev->pfb;
-
-       if (vma->vm_pgoff != 0)
-               return -EINVAL;
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-
-       if (!psbfb->addr_space)
-               psbfb->addr_space = vma->vm_file->f_mapping;
-       /*
-        * If this is a GEM object then info->screen_base is the virtual
-        * kernel remapping of the object. FIXME: Review if this is
-        * suitable for our mmap work
-        */
-       vma->vm_ops = &psbfb_vm_ops;
-       vma->vm_private_data = (void *)psbfb;
-       vma->vm_flags |= VM_RESERVED | VM_IO |
-                                       VM_MIXEDMAP | VM_DONTEXPAND;
-       return 0;
-}
-
-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
-                                               unsigned long arg)
-{
-       return -ENOTTY;
-}
-
-static struct fb_ops psbfb_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcolreg = psbfb_setcolreg,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = psbfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
-       .fb_mmap = psbfb_mmap,
-       .fb_sync = psbfb_sync,
-       .fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_roll_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcolreg = psbfb_setcolreg,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
-       .fb_pan_display = psbfb_pan,
-       .fb_mmap = psbfb_mmap,
-       .fb_sync = psbfb_sync,
-       .fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_unaccel_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcolreg = psbfb_setcolreg,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
-       .fb_mmap = psbfb_mmap,
-       .fb_ioctl = psbfb_ioctl,
-};
-
-/**
- *     psb_framebuffer_init    -       initialize a framebuffer
- *     @dev: our DRM device
- *     @fb: framebuffer to set up
- *     @mode_cmd: mode description
- *     @gt: backing object
- *
- *     Configure and fill in the boilerplate for our frame buffer. Return
- *     0 on success or an error code if we fail.
- */
-static int psb_framebuffer_init(struct drm_device *dev,
-                                       struct psb_framebuffer *fb,
-                                       struct drm_mode_fb_cmd2 *mode_cmd,
-                                       struct gtt_range *gt)
-{
-       u32 bpp, depth;
-       int ret;
-
-       drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
-
-       if (mode_cmd->pitches[0] & 63)
-               return -EINVAL;
-       switch (bpp) {
-       case 8:
-       case 16:
-       case 24:
-       case 32:
-               break;
-       default:
-               return -EINVAL;
-       }
-       ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
-       if (ret) {
-               dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
-               return ret;
-       }
-       drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
-       fb->gtt = gt;
-       return 0;
-}
-
-/**
- *     psb_framebuffer_create  -       create a framebuffer backed by gt
- *     @dev: our DRM device
- *     @mode_cmd: the description of the requested mode
- *     @gt: the backing object
- *
- *     Create a framebuffer object backed by the gt, and fill in the
- *     boilerplate required
- *
- *     TODO: review object references
- */
-
-static struct drm_framebuffer *psb_framebuffer_create
-                       (struct drm_device *dev,
-                        struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct gtt_range *gt)
-{
-       struct psb_framebuffer *fb;
-       int ret;
-
-       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-       if (!fb)
-               return ERR_PTR(-ENOMEM);
-
-       ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
-       if (ret) {
-               kfree(fb);
-               return ERR_PTR(ret);
-       }
-       return &fb->base;
-}
-
-/**
- *     psbfb_alloc             -       allocate frame buffer memory
- *     @dev: the DRM device
- *     @aligned_size: space needed
- *     @force: fall back to GEM buffers if need be
- *
- *     Allocate the frame buffer. In the usual case we get a GTT range that
- *     is stolen memory backed and life is simple. If there isn't sufficient
- *     stolen memory or the system has no stolen memory we allocate a range
- *     and back it with a GEM object.
- *
- *     In this case the GEM object has no handle.
- */
-static struct gtt_range *psbfb_alloc(struct drm_device *dev,
-                                               int aligned_size, int force)
-{
-       struct gtt_range *backing;
-       /* Begin by trying to use stolen memory backing */
-       backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
-       if (backing) {
-               if (drm_gem_private_object_init(dev,
-                                       &backing->gem, aligned_size) == 0)
-                       return backing;
-               psb_gtt_free_range(dev, backing);
-       }
-       if (!force)
-               return NULL;
-
-       /* Next try using GEM host memory */
-       backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
-       if (backing == NULL)
-               return NULL;
-
-       /* Now back it with an object */
-       if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
-               psb_gtt_free_range(dev, backing);
-               return NULL;
-       }
-       return backing;
-}
-
-/**
- *     psbfb_create            -       create a framebuffer
- *     @fbdev: the framebuffer device
- *     @sizes: specification of the layout
- *
- *     Create a framebuffer to the specifications provided
- */
-static int psbfb_create(struct psb_fbdev *fbdev,
-                               struct drm_fb_helper_surface_size *sizes)
-{
-       struct drm_device *dev = fbdev->psb_fb_helper.dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
-       struct psb_framebuffer *psbfb = &fbdev->pfb;
-       struct drm_mode_fb_cmd2 mode_cmd;
-       struct device *device = &dev->pdev->dev;
-       int size;
-       int ret;
-       struct gtt_range *backing;
-       int gtt_roll = 1;
-       u32 bpp, depth;
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       bpp = sizes->surface_bpp;
-
-       /* No 24bit packed */
-       if (bpp == 24)
-               bpp = 32;
-
-       /* Acceleration via the GTT requires pitch to be 4096 byte aligned 
-          (ie 1024 or 2048 pixels in normal use) */
-       mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096);
-       depth = sizes->surface_depth;
-
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-       size = ALIGN(size, PAGE_SIZE);
-
-       /* Allocate the framebuffer in the GTT with stolen page backing */
-       backing = psbfb_alloc(dev, size, 0);
-       if (backing == NULL) {
-               /*
-                *      We couldn't get the space we wanted, fall back to the
-                *      display engine requirement instead.  The HW requires
-                *      the pitch to be 64 byte aligned
-                */
-
-               gtt_roll = 0;   /* Don't use GTT accelerated scrolling */
-
-               mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
-               depth = sizes->surface_depth;
-
-               size = mode_cmd.pitches[0] * mode_cmd.height;
-               size = ALIGN(size, PAGE_SIZE);
-
-               /* Allocate the framebuffer in the GTT with stolen page
-                  backing when there is room */
-               backing = psbfb_alloc(dev, size, 1);
-               if (backing == NULL)
-                       return -ENOMEM;
-       }
-
-       mutex_lock(&dev->struct_mutex);
-
-       info = framebuffer_alloc(0, device);
-       if (!info) {
-               ret = -ENOMEM;
-               goto out_err1;
-       }
-       info->par = fbdev;
-
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
-
-       ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
-       if (ret)
-               goto out_unref;
-
-       fb = &psbfb->base;
-       psbfb->fbdev = info;
-
-       fbdev->psb_fb_helper.fb = fb;
-       fbdev->psb_fb_helper.fbdev = info;
-
-       strcpy(info->fix.id, "psbfb");
-
-       info->flags = FBINFO_DEFAULT;
-       if (gtt_roll) { /* GTT rolling seems best */
-               info->fbops = &psbfb_roll_ops;
-               info->flags |= FBINFO_HWACCEL_YPAN;
-        }
-       else if (dev_priv->ops->accel_2d)       /* 2D engine */
-               info->fbops = &psbfb_ops;
-       else    /* Software */
-               info->fbops = &psbfb_unaccel_ops;
-
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_unref;
-       }
-
-       info->fix.smem_start = dev->mode_config.fb_base;
-       info->fix.smem_len = size;
-       info->fix.ywrapstep = gtt_roll;
-       info->fix.ypanstep = gtt_roll;
-
-       if (backing->stolen) {
-               /* Accessed stolen memory directly */
-               info->screen_base = (char *)dev_priv->vram_addr +
-                                                       backing->offset;
-       } else {
-               /* Pin the pages into the GTT and create a mapping to them */
-               psb_gtt_pin(backing);
-               info->screen_base = vm_map_ram(backing->pages, backing->npage,
-                               -1, PAGE_KERNEL);
-               if (info->screen_base == NULL) {
-                       psb_gtt_unpin(backing);
-                       ret = -ENOMEM;
-                       goto out_unref;
-               }
-               psbfb->vm_map = 1;
-       }
-       info->screen_size = size;
-
-       if (dev_priv->gtt.stolen_size) {
-               info->apertures = alloc_apertures(1);
-               if (!info->apertures) {
-                       ret = -ENOMEM;
-                       goto out_unref;
-               }
-               info->apertures->ranges[0].base = dev->mode_config.fb_base;
-               info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
-       }
-
-       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
-       drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
-                               sizes->fb_width, sizes->fb_height);
-
-       info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
-       info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
-
-       info->pixmap.size = 64 * 1024;
-       info->pixmap.buf_align = 8;
-       info->pixmap.access_align = 32;
-       info->pixmap.flags = FB_PIXMAP_SYSTEM;
-       info->pixmap.scan_align = 1;
-
-       dev_info(dev->dev, "allocated %dx%d fb\n",
-                                       psbfb->base.width, psbfb->base.height);
-
-       mutex_unlock(&dev->struct_mutex);
-       return 0;
-out_unref:
-       if (backing->stolen)
-               psb_gtt_free_range(dev, backing);
-       else {
-               if (psbfb->vm_map)
-                       vm_unmap_ram(info->screen_base, backing->npage);
-               drm_gem_object_unreference(&backing->gem);
-       }
-out_err1:
-       mutex_unlock(&dev->struct_mutex);
-       psb_gtt_free_range(dev, backing);
-       return ret;
-}
-
-/**
- *     psb_user_framebuffer_create     -       create framebuffer
- *     @dev: our DRM device
- *     @filp: client file
- *     @cmd: mode request
- *
- *     Create a new framebuffer backed by a userspace GEM object
- */
-static struct drm_framebuffer *psb_user_framebuffer_create
-                       (struct drm_device *dev, struct drm_file *filp,
-                        struct drm_mode_fb_cmd2 *cmd)
-{
-       struct gtt_range *r;
-       struct drm_gem_object *obj;
-
-       /*
-        *      Find the GEM object and thus the gtt range object that is
-        *      to back this space
-        */
-       obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]);
-       if (obj == NULL)
-               return ERR_PTR(-ENOENT);
-
-       /* Let the core code do all the work */
-       r = container_of(obj, struct gtt_range, gem);
-       return psb_framebuffer_create(dev, cmd, r);
-}
-
-static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
-                                                       u16 blue, int regno)
-{
-}
-
-static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
-                                       u16 *green, u16 *blue, int regno)
-{
-}
-
-static int psbfb_probe(struct drm_fb_helper *helper,
-                               struct drm_fb_helper_surface_size *sizes)
-{
-       struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
-       int new_fb = 0;
-       int ret;
-
-       if (!helper->fb) {
-               ret = psbfb_create(psb_fbdev, sizes);
-               if (ret)
-                       return ret;
-               new_fb = 1;
-       }
-       return new_fb;
-}
-
-struct drm_fb_helper_funcs psb_fb_helper_funcs = {
-       .gamma_set = psbfb_gamma_set,
-       .gamma_get = psbfb_gamma_get,
-       .fb_probe = psbfb_probe,
-};
-
-int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
-{
-       struct fb_info *info;
-       struct psb_framebuffer *psbfb = &fbdev->pfb;
-
-       if (fbdev->psb_fb_helper.fbdev) {
-               info = fbdev->psb_fb_helper.fbdev;
-
-               /* If this is our base framebuffer then kill any virtual map
-                  for the framebuffer layer and unpin it */
-               if (psbfb->vm_map) {
-                       vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
-                       psb_gtt_unpin(psbfb->gtt);
-               }
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
-       drm_fb_helper_fini(&fbdev->psb_fb_helper);
-       drm_framebuffer_cleanup(&psbfb->base);
-
-       if (psbfb->gtt)
-               drm_gem_object_unreference(&psbfb->gtt->gem);
-       return 0;
-}
-
-int psb_fbdev_init(struct drm_device *dev)
-{
-       struct psb_fbdev *fbdev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
-       if (!fbdev) {
-               dev_err(dev->dev, "no memory\n");
-               return -ENOMEM;
-       }
-
-       dev_priv->fbdev = fbdev;
-       fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
-
-       drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
-                                                       INTELFB_CONN_LIMIT);
-
-       drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
-       drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
-       return 0;
-}
-
-void psb_fbdev_fini(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (!dev_priv->fbdev)
-               return;
-
-       psb_fbdev_destroy(dev, dev_priv->fbdev);
-       kfree(dev_priv->fbdev);
-       dev_priv->fbdev = NULL;
-}
-
-static void psbfb_output_poll_changed(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
-       drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
-}
-
-/**
- *     psb_user_framebuffer_create_handle - add hamdle to a framebuffer
- *     @fb: framebuffer
- *     @file_priv: our DRM file
- *     @handle: returned handle
- *
- *     Our framebuffer object is a GTT range which also contains a GEM
- *     object. We need to turn it into a handle for userspace. GEM will do
- *     the work for us
- */
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-                                             struct drm_file *file_priv,
-                                             unsigned int *handle)
-{
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
-       struct gtt_range *r = psbfb->gtt;
-       return drm_gem_handle_create(file_priv, &r->gem, handle);
-}
-
-/**
- *     psb_user_framebuffer_destroy    -       destruct user created fb
- *     @fb: framebuffer
- *
- *     User framebuffers are backed by GEM objects so all we have to do is
- *     clean up a bit and drop the reference, GEM will handle the fallout
- */
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
-       struct gtt_range *r = psbfb->gtt;
-       struct drm_device *dev = fb->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_fbdev *fbdev = dev_priv->fbdev;
-       struct drm_crtc *crtc;
-       int reset = 0;
-
-       /* Should never get stolen memory for a user fb */
-       WARN_ON(r->stolen);
-
-       /* Check if we are erroneously live */
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-               if (crtc->fb == fb)
-                       reset = 1;
-
-       if (reset)
-               /*
-                * Now force a sane response before we permit the DRM CRTC
-                * layer to do stupid things like blank the display. Instead
-                * we reset this framebuffer as if the user had forced a reset.
-                * We must do this before the cleanup so that the DRM layer
-                * doesn't get a chance to stick its oar in where it isn't
-                * wanted.
-                */
-               drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
-
-       /* Let DRM do its clean up */
-       drm_framebuffer_cleanup(fb);
-       /*  We are no longer using the resource in GEM */
-       drm_gem_object_unreference_unlocked(&r->gem);
-       kfree(fb);
-}
-
-static const struct drm_mode_config_funcs psb_mode_funcs = {
-       .fb_create = psb_user_framebuffer_create,
-       .output_poll_changed = psbfb_output_poll_changed,
-};
-
-static int psb_create_backlight_property(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_property *backlight;
-
-       if (dev_priv->backlight_property)
-               return 0;
-
-       backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
-                                                       "backlight", 2);
-       backlight->values[0] = 0;
-       backlight->values[1] = 100;
-
-       dev_priv->backlight_property = backlight;
-
-       return 0;
-}
-
-static void psb_setup_outputs(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_connector *connector;
-
-       drm_mode_create_scaling_mode_property(dev);
-       psb_create_backlight_property(dev);
-
-       dev_priv->ops->output_init(dev);
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
-               struct psb_intel_output *psb_intel_output =
-                   to_psb_intel_output(connector);
-               struct drm_encoder *encoder = &psb_intel_output->enc;
-               int crtc_mask = 0, clone_mask = 0;
-
-               /* valid crtcs */
-               switch (psb_intel_output->type) {
-               case INTEL_OUTPUT_ANALOG:
-                       crtc_mask = (1 << 0);
-                       clone_mask = (1 << INTEL_OUTPUT_ANALOG);
-                       break;
-               case INTEL_OUTPUT_SDVO:
-                       crtc_mask = ((1 << 0) | (1 << 1));
-                       clone_mask = (1 << INTEL_OUTPUT_SDVO);
-                       break;
-               case INTEL_OUTPUT_LVDS:
-                       if (IS_MRST(dev))
-                               crtc_mask = (1 << 0);
-                       else
-                               crtc_mask = (1 << 1);
-                       clone_mask = (1 << INTEL_OUTPUT_LVDS);
-                       break;
-               case INTEL_OUTPUT_MIPI:
-                       crtc_mask = (1 << 0);
-                       clone_mask = (1 << INTEL_OUTPUT_MIPI);
-                       break;
-               case INTEL_OUTPUT_MIPI2:
-                       crtc_mask = (1 << 2);
-                       clone_mask = (1 << INTEL_OUTPUT_MIPI2);
-                       break;
-               case INTEL_OUTPUT_HDMI:
-                       /* HDMI on crtc 1 for SoC devices and crtc 0 for
-                           Cedarview. HDMI on Poulsbo is only via external
-                          logic */
-                       if (IS_MFLD(dev) || IS_MRST(dev))
-                               crtc_mask = (1 << 1);
-                       else
-                               crtc_mask = (1 << 0);   /* Cedarview */
-                       clone_mask = (1 << INTEL_OUTPUT_HDMI);
-                       break;
-               }
-               encoder->possible_crtcs = crtc_mask;
-               encoder->possible_clones =
-                   psb_intel_connector_clones(dev, clone_mask);
-       }
-}
-
-void psb_modeset_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-       struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
-       int i;
-
-       drm_mode_config_init(dev);
-
-       dev->mode_config.min_width = 0;
-       dev->mode_config.min_height = 0;
-
-       dev->mode_config.funcs = (void *) &psb_mode_funcs;
-
-       /* set memory base */
-       /* MRST and PSB should use BAR 2*/
-       pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
-                                       &(dev->mode_config.fb_base));
-
-       /* num pipes is 2 for PSB but 1 for Mrst */
-       for (i = 0; i < dev_priv->num_pipe; i++)
-               psb_intel_crtc_init(dev, i, mode_dev);
-
-       dev->mode_config.max_width = 2048;
-       dev->mode_config.max_height = 2048;
-
-       psb_setup_outputs(dev);
-}
-
-void psb_modeset_cleanup(struct drm_device *dev)
-{
-       mutex_lock(&dev->struct_mutex);
-
-       drm_kms_helper_poll_fini(dev);
-       psb_fbdev_fini(dev);
-       drm_mode_config_cleanup(dev);
-
-       mutex_unlock(&dev->struct_mutex);
-}
diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h
deleted file mode 100644 (file)
index d1b2289..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *      Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _FRAMEBUFFER_H_
-#define _FRAMEBUFFER_H_
-
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
-
-#include "psb_drv.h"
-
-struct psb_framebuffer {
-       struct drm_framebuffer base;
-       struct address_space *addr_space;
-       struct fb_info *fbdev;
-       struct gtt_range *gtt;
-       bool vm_map;            /* True if we must undo a vm_map_ram */
-};
-
-struct psb_fbdev {
-       struct drm_fb_helper psb_fb_helper;
-       struct psb_framebuffer pfb;
-};
-
-#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
-
-extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
-
-#endif
-
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
deleted file mode 100644 (file)
index f6433c0..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- *  psb GEM interface
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors: Alan Cox
- *
- * TODO:
- *     -       we need to work out if the MMU is relevant (eg for
- *             accelerated operations on a GEM object)
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-
-int psb_gem_init_object(struct drm_gem_object *obj)
-{
-       return -EINVAL;
-}
-
-void psb_gem_free_object(struct drm_gem_object *obj)
-{
-       struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
-       drm_gem_object_release_wrap(obj);
-       /* This must occur last as it frees up the memory of the GEM object */
-       psb_gtt_free_range(obj->dev, gtt);
-}
-
-int psb_gem_get_aperture(struct drm_device *dev, void *data,
-                               struct drm_file *file)
-{
-       return -EINVAL;
-}
-
-/**
- *     psb_gem_dumb_map_gtt    -       buffer mapping for dumb interface
- *     @file: our drm client file
- *     @dev: drm device
- *     @handle: GEM handle to the object (from dumb_create)
- *
- *     Do the necessary setup to allow the mapping of the frame buffer
- *     into user memory. We don't have to do much here at the moment.
- */
-int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
-                        uint32_t handle, uint64_t *offset)
-{
-       int ret = 0;
-       struct drm_gem_object *obj;
-
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
-       mutex_lock(&dev->struct_mutex);
-
-       /* GEM does all our handle to object mapping */
-       obj = drm_gem_object_lookup(dev, file, handle);
-       if (obj == NULL) {
-               ret = -ENOENT;
-               goto unlock;
-       }
-       /* What validation is needed here ? */
-
-       /* Make it mmapable */
-       if (!obj->map_list.map) {
-               ret = gem_create_mmap_offset(obj);
-               if (ret)
-                       goto out;
-       }
-       /* GEM should really work out the hash offsets for us */
-       *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
-out:
-       drm_gem_object_unreference(obj);
-unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-}
-
-/**
- *     psb_gem_create          -       create a mappable object
- *     @file: the DRM file of the client
- *     @dev: our device
- *     @size: the size requested
- *     @handlep: returned handle (opaque number)
- *
- *     Create a GEM object, fill in the boilerplate and attach a handle to
- *     it so that userspace can speak about it. This does the core work
- *     for the various methods that do/will create GEM objects for things
- */
-static int psb_gem_create(struct drm_file *file,
-       struct drm_device *dev, uint64_t size, uint32_t *handlep)
-{
-       struct gtt_range *r;
-       int ret;
-       u32 handle;
-
-       size = roundup(size, PAGE_SIZE);
-
-       /* Allocate our object - for now a direct gtt range which is not
-          stolen memory backed */
-       r = psb_gtt_alloc_range(dev, size, "gem", 0);
-       if (r == NULL) {
-               dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
-               return -ENOSPC;
-       }
-       /* Initialize the extra goodies GEM needs to do all the hard work */
-       if (drm_gem_object_init(dev, &r->gem, size) != 0) {
-               psb_gtt_free_range(dev, r);
-               /* GEM doesn't give an error code so use -ENOMEM */
-               dev_err(dev->dev, "GEM init failed for %lld\n", size);
-               return -ENOMEM;
-       }
-       /* Give the object a handle so we can carry it more easily */
-       ret = drm_gem_handle_create(file, &r->gem, &handle);
-       if (ret) {
-               dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
-                                                       &r->gem, size);
-               drm_gem_object_release(&r->gem);
-               psb_gtt_free_range(dev, r);
-               return ret;
-       }
-       /* We have the initial and handle reference but need only one now */
-       drm_gem_object_unreference(&r->gem);
-       *handlep = handle;
-       return 0;
-}
-
-/**
- *     psb_gem_dumb_create     -       create a dumb buffer
- *     @drm_file: our client file
- *     @dev: our device
- *     @args: the requested arguments copied from userspace
- *
- *     Allocate a buffer suitable for use for a frame buffer of the
- *     form described by user space. Give userspace a handle by which
- *     to reference it.
- */
-int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
-                       struct drm_mode_create_dumb *args)
-{
-       args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
-       args->size = args->pitch * args->height;
-       return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-/**
- *     psb_gem_dumb_destroy    -       destroy a dumb buffer
- *     @file: client file
- *     @dev: our DRM device
- *     @handle: the object handle
- *
- *     Destroy a handle that was created via psb_gem_dumb_create, at least
- *     we hope it was created that way. i915 seems to assume the caller
- *     does the checking but that might be worth review ! FIXME
- */
-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-                       uint32_t handle)
-{
-       /* No special work needed, drop the reference and see what falls out */
-       return drm_gem_handle_delete(file, handle);
-}
-
-/**
- *     psb_gem_fault           -       pagefault handler for GEM objects
- *     @vma: the VMA of the GEM object
- *     @vmf: fault detail
- *
- *     Invoked when a fault occurs on an mmap of a GEM managed area. GEM
- *     does most of the work for us including the actual map/unmap calls
- *     but we need to do the actual page work.
- *
- *     This code eventually needs to handle faulting objects in and out
- *     of the GTT and repacking it when we run out of space. We can put
- *     that off for now and for our simple uses
- *
- *     The VMA was set up by GEM. In doing so it also ensured that the
- *     vma->vm_private_data points to the GEM object that is backing this
- *     mapping.
- */
-int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct drm_gem_object *obj;
-       struct gtt_range *r;
-       int ret;
-       unsigned long pfn;
-       pgoff_t page_offset;
-       struct drm_device *dev;
-       struct drm_psb_private *dev_priv;
-
-       obj = vma->vm_private_data;     /* GEM object */
-       dev = obj->dev;
-       dev_priv = dev->dev_private;
-
-       r = container_of(obj, struct gtt_range, gem);   /* Get the gtt range */
-
-       /* Make sure we don't parallel update on a fault, nor move or remove
-          something from beneath our feet */
-       mutex_lock(&dev->struct_mutex);
-
-       /* For now the mmap pins the object and it stays pinned. As things
-          stand that will do us no harm */
-       if (r->mmapping == 0) {
-               ret = psb_gtt_pin(r);
-               if (ret < 0) {
-                       dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
-                       goto fail;
-               }
-               r->mmapping = 1;
-       }
-
-       /* Page relative to the VMA start - we must calculate this ourselves
-          because vmf->pgoff is the fake GEM offset */
-       page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
-                               >> PAGE_SHIFT;
-
-       /* CPU view of the page, don't go via the GART for CPU writes */
-       if (r->stolen)
-               pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
-       else
-               pfn = page_to_pfn(r->pages[page_offset]);
-       ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
-fail:
-       mutex_unlock(&dev->struct_mutex);
-       switch (ret) {
-       case 0:
-       case -ERESTARTSYS:
-       case -EINTR:
-               return VM_FAULT_NOPAGE;
-       case -ENOMEM:
-               return VM_FAULT_OOM;
-       default:
-               return VM_FAULT_SIGBUS;
-       }
-}
-
-static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
-                                               int size, u32 *handle)
-{
-       struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
-       if (gtt == NULL)
-               return -ENOMEM;
-       if (drm_gem_private_object_init(dev, &gtt->gem, size) != 0)
-               goto free_gtt;
-       if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
-               return 0;
-free_gtt:
-       psb_gtt_free_range(dev, gtt);
-       return -ENOMEM;
-}
-
-/*
- *     GEM interfaces for our specific client
- */
-int psb_gem_create_ioctl(struct drm_device *dev, void *data,
-                                       struct drm_file *file)
-{
-       struct drm_psb_gem_create *args = data;
-       int ret;
-       if (args->flags & PSB_GEM_CREATE_STOLEN) {
-               ret = psb_gem_create_stolen(file, dev, args->size,
-                                                       &args->handle);
-               if (ret == 0)
-                       return 0;
-               /* Fall throguh */
-               args->flags &= ~PSB_GEM_CREATE_STOLEN;
-       }
-       return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
-                                       struct drm_file *file)
-{
-       struct drm_psb_gem_mmap *args = data;
-       return dev->driver->dumb_map_offset(file, dev,
-                                               args->handle, &args->offset);
-}
-
diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
deleted file mode 100644 (file)
index daac121..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-
-void drm_gem_object_release_wrap(struct drm_gem_object *obj)
-{
-       /* Remove the list map if one is present */
-       if (obj->map_list.map) {
-               struct drm_gem_mm *mm = obj->dev->mm_private;
-               struct drm_map_list *list = &obj->map_list;
-               drm_ht_remove_item(&mm->offset_hash, &list->hash);
-               drm_mm_put_block(list->file_offset_node);
-               kfree(list->map);
-               list->map = NULL;
-       }
-       drm_gem_object_release(obj);
-}
-
-/**
- *     gem_create_mmap_offset          -       invent an mmap offset
- *     @obj: our object
- *
- *     Standard implementation of offset generation for mmap as is
- *     duplicated in several drivers. This belongs in GEM.
- */
-int gem_create_mmap_offset(struct drm_gem_object *obj)
-{
-       struct drm_device *dev = obj->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
-       struct drm_map_list *list;
-       struct drm_local_map *map;
-       int ret;
-
-       list = &obj->map_list;
-       list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-       if (list->map == NULL)
-               return -ENOMEM;
-       map = list->map;
-       map->type = _DRM_GEM;
-       map->size = obj->size;
-       map->handle = obj;
-
-       list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-                                       obj->size / PAGE_SIZE, 0, 0);
-       if (!list->file_offset_node) {
-               dev_err(dev->dev, "failed to allocate offset for bo %d\n",
-                                                               obj->name);
-               ret = -ENOSPC;
-               goto free_it;
-       }
-       list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-                                       obj->size / PAGE_SIZE, 0);
-       if (!list->file_offset_node) {
-               ret = -ENOMEM;
-               goto free_it;
-       }
-       list->hash.key = list->file_offset_node->start;
-       ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-       if (ret) {
-               dev_err(dev->dev, "failed to add to map hash\n");
-               goto free_mm;
-       }
-       return 0;
-
-free_mm:
-       drm_mm_put_block(list->file_offset_node);
-free_it:
-       kfree(list->map);
-       list->map = NULL;
-       return ret;
-}
diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h
deleted file mode 100644 (file)
index ce5ce30..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
-extern int gem_create_mmap_offset(struct drm_gem_object *obj);
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
deleted file mode 100644 (file)
index e770bd1..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
- *         Alan Cox <alan@linux.intel.com>
- */
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-
-
-/*
- *     GTT resource allocator - manage page mappings in GTT space
- */
-
-/**
- *     psb_gtt_mask_pte        -       generate GTT pte entry
- *     @pfn: page number to encode
- *     @type: type of memory in the GTT
- *
- *     Set the GTT entry for the appropriate memory type.
- */
-static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
-{
-       uint32_t mask = PSB_PTE_VALID;
-
-       if (type & PSB_MMU_CACHED_MEMORY)
-               mask |= PSB_PTE_CACHED;
-       if (type & PSB_MMU_RO_MEMORY)
-               mask |= PSB_PTE_RO;
-       if (type & PSB_MMU_WO_MEMORY)
-               mask |= PSB_PTE_WO;
-
-       return (pfn << PAGE_SHIFT) | mask;
-}
-
-/**
- *     psb_gtt_entry           -       find the GTT entries for a gtt_range
- *     @dev: our DRM device
- *     @r: our GTT range
- *
- *     Given a gtt_range object return the GTT offset of the page table
- *     entries for this gtt_range
- */
-u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long offset;
-
-       offset = r->resource.start - dev_priv->gtt_mem->start;
-
-       return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
-}
-
-/**
- *     psb_gtt_insert  -       put an object into the GTT
- *     @dev: our DRM device
- *     @r: our GTT range
- *
- *     Take our preallocated GTT range and insert the GEM object into
- *     the GTT. This is protected via the gtt mutex which the caller
- *     must hold.
- */
-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
-{
-       u32 *gtt_slot, pte;
-       struct page **pages;
-       int i;
-
-       if (r->pages == NULL) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       WARN_ON(r->stolen);     /* refcount these maybe ? */
-
-       gtt_slot = psb_gtt_entry(dev, r);
-       pages = r->pages;
-
-       /* Make sure changes are visible to the GPU */
-       set_pages_array_uc(pages, r->npage);
-
-       /* Write our page entries into the GTT itself */
-       for (i = r->roll; i < r->npage; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
-               iowrite32(pte, gtt_slot++);
-       }
-       for (i = 0; i < r->roll; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
-               iowrite32(pte, gtt_slot++);
-       }
-       /* Make sure all the entries are set before we return */
-       ioread32(gtt_slot - 1);
-
-       return 0;
-}
-
-/**
- *     psb_gtt_remove  -       remove an object from the GTT
- *     @dev: our DRM device
- *     @r: our GTT range
- *
- *     Remove a preallocated GTT range from the GTT. Overwrite all the
- *     page table entries with the dummy page. This is protected via the gtt
- *     mutex which the caller must hold.
- */
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 *gtt_slot, pte;
-       int i;
-
-       WARN_ON(r->stolen);
-
-       gtt_slot = psb_gtt_entry(dev, r);
-       pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
-
-       for (i = 0; i < r->npage; i++)
-               iowrite32(pte, gtt_slot++);
-       ioread32(gtt_slot - 1);
-       set_pages_array_wb(r->pages, r->npage);
-}
-
-/**
- *     psb_gtt_roll    -       set scrolling position
- *     @dev: our DRM device
- *     @r: the gtt mapping we are using
- *     @roll: roll offset
- *
- *     Roll an existing pinned mapping by moving the pages through the GTT.
- *     This allows us to implement hardware scrolling on the consoles without
- *     a 2D engine
- */
-void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
-{
-       u32 *gtt_slot, pte;
-       int i;
-
-       if (roll >= r->npage) {
-               WARN_ON(1);
-               return;
-       }
-
-       r->roll = roll;
-
-       /* Not currently in the GTT - no worry we will write the mapping at
-          the right position when it gets pinned */
-       if (!r->stolen && !r->in_gart)
-               return;
-
-       gtt_slot = psb_gtt_entry(dev, r);
-
-       for (i = r->roll; i < r->npage; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
-               iowrite32(pte, gtt_slot++);
-       }
-       for (i = 0; i < r->roll; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
-               iowrite32(pte, gtt_slot++);
-       }
-       ioread32(gtt_slot - 1);
-}
-
-/**
- *     psb_gtt_attach_pages    -       attach and pin GEM pages
- *     @gt: the gtt range
- *
- *     Pin and build an in kernel list of the pages that back our GEM object.
- *     While we hold this the pages cannot be swapped out. This is protected
- *     via the gtt mutex which the caller must hold.
- */
-static int psb_gtt_attach_pages(struct gtt_range *gt)
-{
-       struct inode *inode;
-       struct address_space *mapping;
-       int i;
-       struct page *p;
-       int pages = gt->gem.size / PAGE_SIZE;
-
-       WARN_ON(gt->pages);
-
-       /* This is the shared memory object that backs the GEM resource */
-       inode = gt->gem.filp->f_path.dentry->d_inode;
-       mapping = inode->i_mapping;
-
-       gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
-       if (gt->pages == NULL)
-               return -ENOMEM;
-       gt->npage = pages;
-
-       for (i = 0; i < pages; i++) {
-               /* FIXME: needs updating as per mail from Hugh Dickins */
-               p = read_cache_page_gfp(mapping, i,
-                                       __GFP_COLD | GFP_KERNEL);
-               if (IS_ERR(p))
-                       goto err;
-               gt->pages[i] = p;
-       }
-       return 0;
-
-err:
-       while (i--)
-               page_cache_release(gt->pages[i]);
-       kfree(gt->pages);
-       gt->pages = NULL;
-       return PTR_ERR(p);
-}
-
-/**
- *     psb_gtt_detach_pages    -       attach and pin GEM pages
- *     @gt: the gtt range
- *
- *     Undo the effect of psb_gtt_attach_pages. At this point the pages
- *     must have been removed from the GTT as they could now be paged out
- *     and move bus address. This is protected via the gtt mutex which the
- *     caller must hold.
- */
-static void psb_gtt_detach_pages(struct gtt_range *gt)
-{
-       int i;
-       for (i = 0; i < gt->npage; i++) {
-               /* FIXME: do we need to force dirty */
-               set_page_dirty(gt->pages[i]);
-               page_cache_release(gt->pages[i]);
-       }
-       kfree(gt->pages);
-       gt->pages = NULL;
-}
-
-/**
- *     psb_gtt_pin             -       pin pages into the GTT
- *     @gt: range to pin
- *
- *     Pin a set of pages into the GTT. The pins are refcounted so that
- *     multiple pins need multiple unpins to undo.
- *
- *     Non GEM backed objects treat this as a no-op as they are always GTT
- *     backed objects.
- */
-int psb_gtt_pin(struct gtt_range *gt)
-{
-       int ret = 0;
-       struct drm_device *dev = gt->gem.dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev_priv->gtt_mutex);
-
-       if (gt->in_gart == 0 && gt->stolen == 0) {
-               ret = psb_gtt_attach_pages(gt);
-               if (ret < 0)
-                       goto out;
-               ret = psb_gtt_insert(dev, gt);
-               if (ret < 0) {
-                       psb_gtt_detach_pages(gt);
-                       goto out;
-               }
-       }
-       gt->in_gart++;
-out:
-       mutex_unlock(&dev_priv->gtt_mutex);
-       return ret;
-}
-
-/**
- *     psb_gtt_unpin           -       Drop a GTT pin requirement
- *     @gt: range to pin
- *
- *     Undoes the effect of psb_gtt_pin. On the last drop the GEM object
- *     will be removed from the GTT which will also drop the page references
- *     and allow the VM to clean up or page stuff.
- *
- *     Non GEM backed objects treat this as a no-op as they are always GTT
- *     backed objects.
- */
-void psb_gtt_unpin(struct gtt_range *gt)
-{
-       struct drm_device *dev = gt->gem.dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev_priv->gtt_mutex);
-
-       WARN_ON(!gt->in_gart);
-
-       gt->in_gart--;
-       if (gt->in_gart == 0 && gt->stolen == 0) {
-               psb_gtt_remove(dev, gt);
-               psb_gtt_detach_pages(gt);
-       }
-       mutex_unlock(&dev_priv->gtt_mutex);
-}
-
-/*
- *     GTT resource allocator - allocate and manage GTT address space
- */
-
-/**
- *     psb_gtt_alloc_range     -       allocate GTT address space
- *     @dev: Our DRM device
- *     @len: length (bytes) of address space required
- *     @name: resource name
- *     @backed: resource should be backed by stolen pages
- *
- *     Ask the kernel core to find us a suitable range of addresses
- *     to use for a GTT mapping.
- *
- *     Returns a gtt_range structure describing the object, or NULL on
- *     error. On successful return the resource is both allocated and marked
- *     as in use.
- */
-struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-                                               const char *name, int backed)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct gtt_range *gt;
-       struct resource *r = dev_priv->gtt_mem;
-       int ret;
-       unsigned long start, end;
-
-       if (backed) {
-               /* The start of the GTT is the stolen pages */
-               start = r->start;
-               end = r->start + dev_priv->gtt.stolen_size - 1;
-       } else {
-               /* The rest we will use for GEM backed objects */
-               start = r->start + dev_priv->gtt.stolen_size;
-               end = r->end;
-       }
-
-       gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
-       if (gt == NULL)
-               return NULL;
-       gt->resource.name = name;
-       gt->stolen = backed;
-       gt->in_gart = backed;
-       gt->roll = 0;
-       /* Ensure this is set for non GEM objects */
-       gt->gem.dev = dev;
-       ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
-                               len, start, end, PAGE_SIZE, NULL, NULL);
-       if (ret == 0) {
-               gt->offset = gt->resource.start - r->start;
-               return gt;
-       }
-       kfree(gt);
-       return NULL;
-}
-
-/**
- *     psb_gtt_free_range      -       release GTT address space
- *     @dev: our DRM device
- *     @gt: a mapping created with psb_gtt_alloc_range
- *
- *     Release a resource that was allocated with psb_gtt_alloc_range. If the
- *     object has been pinned by mmap users we clean this up here currently.
- */
-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
-{
-       /* Undo the mmap pin if we are destroying the object */
-       if (gt->mmapping) {
-               psb_gtt_unpin(gt);
-               gt->mmapping = 0;
-       }
-       WARN_ON(gt->in_gart && !gt->stolen);
-       release_resource(&gt->resource);
-       kfree(gt);
-}
-
-void psb_gtt_alloc(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       init_rwsem(&dev_priv->gtt.sem);
-}
-
-void psb_gtt_takedown(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (dev_priv->gtt_map) {
-               iounmap(dev_priv->gtt_map);
-               dev_priv->gtt_map = NULL;
-       }
-       if (dev_priv->gtt_initialized) {
-               pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
-                                     dev_priv->gmch_ctrl);
-               PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
-               (void) PSB_RVDC32(PSB_PGETBL_CTL);
-       }
-       if (dev_priv->vram_addr)
-               iounmap(dev_priv->gtt_map);
-}
-
-int psb_gtt_init(struct drm_device *dev, int resume)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned gtt_pages;
-       unsigned long stolen_size, vram_stolen_size;
-       unsigned i, num_pages;
-       unsigned pfn_base;
-       uint32_t vram_pages;
-       uint32_t dvmt_mode = 0;
-       struct psb_gtt *pg;
-
-       int ret = 0;
-       uint32_t pte;
-
-       mutex_init(&dev_priv->gtt_mutex);
-
-       psb_gtt_alloc(dev);
-       pg = &dev_priv->gtt;
-
-       /* Enable the GTT */
-       pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
-       pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
-                             dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-
-       dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
-       PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
-       (void) PSB_RVDC32(PSB_PGETBL_CTL);
-
-       /* The root resource we allocate address space from */
-       dev_priv->gtt_initialized = 1;
-
-       pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
-
-       /*
-        *      The video mmu has a hw bug when accessing 0x0D0000000.
-        *      Make gatt start at 0x0e000,0000. This doesn't actually
-        *      matter for us but may do if the video acceleration ever
-        *      gets opened up.
-        */
-       pg->mmu_gatt_start = 0xE0000000;
-
-       pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
-       gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
-                                                               >> PAGE_SHIFT;
-       /* Some CDV firmware doesn't report this currently. In which case the
-          system has 64 gtt pages */
-       if (pg->gtt_start == 0 || gtt_pages == 0) {
-               dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
-               gtt_pages = 64;
-               pg->gtt_start = dev_priv->pge_ctl;
-       }
-
-       pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
-       pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
-                                                               >> PAGE_SHIFT;
-       dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
-
-       if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
-               static struct resource fudge;   /* Preferably peppermint */
-               /* This can occur on CDV SDV systems. Fudge it in this case.
-                  We really don't care what imaginary space is being allocated
-                  at this point */
-               dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
-               pg->gatt_start = 0x40000000;
-               pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
-               /* This is a little confusing but in fact the GTT is providing
-                  a view from the GPU into memory and not vice versa. As such
-                  this is really allocating space that is not the same as the
-                  CPU address space on CDV */
-               fudge.start = 0x40000000;
-               fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
-               fudge.name = "fudge";
-               fudge.flags = IORESOURCE_MEM;
-               dev_priv->gtt_mem = &fudge;
-       }
-
-       pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
-       vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
-                                                               - PAGE_SIZE;
-
-       stolen_size = vram_stolen_size;
-
-       printk(KERN_INFO "Stolen memory information\n");
-       printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
-       printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
-               vram_stolen_size/1024);
-       dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
-       printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
-               (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
-
-       if (resume && (gtt_pages != pg->gtt_pages) &&
-           (stolen_size != pg->stolen_size)) {
-               dev_err(dev->dev, "GTT resume error.\n");
-               ret = -EINVAL;
-               goto out_err;
-       }
-
-       pg->gtt_pages = gtt_pages;
-       pg->stolen_size = stolen_size;
-       dev_priv->vram_stolen_size = vram_stolen_size;
-
-       /*
-        *      Map the GTT and the stolen memory area
-        */
-       dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
-                                               gtt_pages << PAGE_SHIFT);
-       if (!dev_priv->gtt_map) {
-               dev_err(dev->dev, "Failure to map gtt.\n");
-               ret = -ENOMEM;
-               goto out_err;
-       }
-
-       dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
-       if (!dev_priv->vram_addr) {
-               dev_err(dev->dev, "Failure to map stolen base.\n");
-               ret = -ENOMEM;
-               goto out_err;
-       }
-
-       /*
-        * Insert vram stolen pages into the GTT
-        */
-
-       pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
-       vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
-       printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
-               num_pages, pfn_base << PAGE_SHIFT, 0);
-       for (i = 0; i < num_pages; ++i) {
-               pte = psb_gtt_mask_pte(pfn_base + i, 0);
-               iowrite32(pte, dev_priv->gtt_map + i);
-       }
-
-       /*
-        * Init rest of GTT to the scratch page to avoid accidents or scribbles
-        */
-
-       pfn_base = page_to_pfn(dev_priv->scratch_page);
-       pte = psb_gtt_mask_pte(pfn_base, 0);
-       for (; i < gtt_pages; ++i)
-               iowrite32(pte, dev_priv->gtt_map + i);
-
-       (void) ioread32(dev_priv->gtt_map + i - 1);
-       return 0;
-
-out_err:
-       psb_gtt_takedown(dev);
-       return ret;
-}
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h
deleted file mode 100644 (file)
index aa17423..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2008, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#ifndef _PSB_GTT_H_
-#define _PSB_GTT_H_
-
-#include <drm/drmP.h>
-
-/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
-struct psb_gtt {
-       uint32_t gatt_start;
-       uint32_t mmu_gatt_start;
-       uint32_t gtt_start;
-       uint32_t gtt_phys_start;
-       unsigned gtt_pages;
-       unsigned gatt_pages;
-       unsigned long stolen_size;
-       unsigned long vram_stolen_size;
-       struct rw_semaphore sem;
-};
-
-/* Exported functions */
-extern int psb_gtt_init(struct drm_device *dev, int resume);
-extern void psb_gtt_takedown(struct drm_device *dev);
-
-/* Each gtt_range describes an allocation in the GTT area */
-struct gtt_range {
-       struct resource resource;       /* Resource for our allocation */
-       u32 offset;                     /* GTT offset of our object */
-       struct drm_gem_object gem;      /* GEM high level stuff */
-       int in_gart;                    /* Currently in the GART (ref ct) */
-       bool stolen;                    /* Backed from stolen RAM */
-       bool mmapping;                  /* Is mmappable */
-       struct page **pages;            /* Backing pages if present */
-       int npage;                      /* Number of backing pages */
-       int roll;                       /* Roll applied to the GTT entries */
-};
-
-extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-                                               const char *name, int backed);
-extern void psb_gtt_kref_put(struct gtt_range *gt);
-extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
-extern int psb_gtt_pin(struct gtt_range *gt);
-extern void psb_gtt_unpin(struct gtt_range *gt);
-extern void psb_gtt_roll(struct drm_device *dev,
-                                       struct gtt_range *gt, int roll);
-
-#endif
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
deleted file mode 100644 (file)
index 096757f..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-
-
-static void *find_section(struct bdb_header *bdb, int section_id)
-{
-       u8 *base = (u8 *)bdb;
-       int index = 0;
-       u16 total, current_size;
-       u8 current_id;
-
-       /* skip to first section */
-       index += bdb->header_size;
-       total = bdb->bdb_size;
-
-       /* walk the sections looking for section_id */
-       while (index < total) {
-               current_id = *(base + index);
-               index++;
-               current_size = *((u16 *)(base + index));
-               index += 2;
-               if (current_id == section_id)
-                       return base + index;
-               index += current_size;
-       }
-
-       return NULL;
-}
-
-static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
-                       struct lvds_dvo_timing *dvo_timing)
-{
-       panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
-               dvo_timing->hactive_lo;
-       panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
-               ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
-       panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
-               dvo_timing->hsync_pulse_width;
-       panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
-               ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
-
-       panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
-               dvo_timing->vactive_lo;
-       panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
-               dvo_timing->vsync_off;
-       panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
-               dvo_timing->vsync_pulse_width;
-       panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
-               ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
-       panel_fixed_mode->clock = dvo_timing->clock * 10;
-       panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
-
-       /* Some VBTs have bogus h/vtotal values */
-       if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
-               panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
-       if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
-               panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
-
-       drm_mode_set_name(panel_fixed_mode);
-}
-
-static void parse_backlight_data(struct drm_psb_private *dev_priv,
-                               struct bdb_header *bdb)
-{
-       struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
-       struct bdb_lvds_backlight *lvds_bl;
-       u8 p_type = 0;
-       void *bl_start = NULL;
-       struct bdb_lvds_options *lvds_opts
-                               = find_section(bdb, BDB_LVDS_OPTIONS);
-
-       dev_priv->lvds_bl = NULL;
-
-       if (lvds_opts)
-               p_type = lvds_opts->panel_type;
-       else
-               return;
-
-       bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
-       vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
-
-       lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
-       if (!lvds_bl) {
-               dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
-               return;
-       }
-       memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
-       dev_priv->lvds_bl = lvds_bl;
-}
-
-/* Try to find integrated panel data */
-static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
-                           struct bdb_header *bdb)
-{
-       struct bdb_lvds_options *lvds_options;
-       struct bdb_lvds_lfp_data *lvds_lfp_data;
-       struct bdb_lvds_lfp_data_entry *entry;
-       struct lvds_dvo_timing *dvo_timing;
-       struct drm_display_mode *panel_fixed_mode;
-
-       /* Defaults if we can't find VBT info */
-       dev_priv->lvds_dither = 0;
-       dev_priv->lvds_vbt = 0;
-
-       lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
-       if (!lvds_options)
-               return;
-
-       dev_priv->lvds_dither = lvds_options->pixel_dither;
-       if (lvds_options->panel_type == 0xff)
-               return;
-
-       lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
-       if (!lvds_lfp_data)
-               return;
-
-
-       entry = &lvds_lfp_data->data[lvds_options->panel_type];
-       dvo_timing = &entry->dvo_timing;
-
-       panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
-                                     GFP_KERNEL);
-       if (panel_fixed_mode == NULL) {
-               dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n");
-               return;
-       }
-
-       dev_priv->lvds_vbt = 1;
-       fill_detail_timing_data(panel_fixed_mode, dvo_timing);
-
-       if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
-               dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
-               drm_mode_debug_printmodeline(panel_fixed_mode);
-       } else {
-               dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
-               dev_priv->lvds_vbt = 0;
-               kfree(panel_fixed_mode);
-       }
-       return;
-}
-
-/* Try to find sdvo panel data */
-static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
-                     struct bdb_header *bdb)
-{
-       struct bdb_sdvo_lvds_options *sdvo_lvds_options;
-       struct lvds_dvo_timing *dvo_timing;
-       struct drm_display_mode *panel_fixed_mode;
-
-       dev_priv->sdvo_lvds_vbt_mode = NULL;
-
-       sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
-       if (!sdvo_lvds_options)
-               return;
-
-       dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
-       if (!dvo_timing)
-               return;
-
-       panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
-
-       if (!panel_fixed_mode)
-               return;
-
-       fill_detail_timing_data(panel_fixed_mode,
-                       dvo_timing + sdvo_lvds_options->panel_type);
-
-       dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
-
-       return;
-}
-
-static void parse_general_features(struct drm_psb_private *dev_priv,
-                      struct bdb_header *bdb)
-{
-       struct bdb_general_features *general;
-
-       /* Set sensible defaults in case we can't find the general block */
-       dev_priv->int_tv_support = 1;
-       dev_priv->int_crt_support = 1;
-
-       general = find_section(bdb, BDB_GENERAL_FEATURES);
-       if (general) {
-               dev_priv->int_tv_support = general->int_tv_support;
-               dev_priv->int_crt_support = general->int_crt_support;
-               dev_priv->lvds_use_ssc = general->enable_ssc;
-
-               if (dev_priv->lvds_use_ssc) {
-                       dev_priv->lvds_ssc_freq
-                               = general->ssc_freq ? 100 : 96;
-               }
-       }
-}
-
-/**
- * psb_intel_init_bios - initialize VBIOS settings & find VBT
- * @dev: DRM device
- *
- * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
- * to appropriate values.
- *
- * VBT existence is a sanity check that is relied on by other i830_bios.c code.
- * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
- * feed an updated VBT back through that, compared to what we'll fetch using
- * this method of groping around in the BIOS data.
- *
- * Returns 0 on success, nonzero on failure.
- */
-bool psb_intel_init_bios(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct pci_dev *pdev = dev->pdev;
-       struct vbt_header *vbt = NULL;
-       struct bdb_header *bdb;
-       u8 __iomem *bios;
-       size_t size;
-       int i;
-
-       bios = pci_map_rom(pdev, &size);
-       if (!bios)
-               return -1;
-
-       /* Scour memory looking for the VBT signature */
-       for (i = 0; i + 4 < size; i++) {
-               if (!memcmp(bios + i, "$VBT", 4)) {
-                       vbt = (struct vbt_header *)(bios + i);
-                       break;
-               }
-       }
-
-       if (!vbt) {
-               dev_err(dev->dev, "VBT signature missing\n");
-               pci_unmap_rom(pdev, bios);
-               return -1;
-       }
-
-       bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
-
-       /* Grab useful general definitions */
-       parse_general_features(dev_priv, bdb);
-       parse_lfp_panel_data(dev_priv, bdb);
-       parse_sdvo_panel_data(dev_priv, bdb);
-       parse_backlight_data(dev_priv, bdb);
-
-       pci_unmap_rom(pdev, bios);
-
-       return 0;
-}
-
-/**
- * Destroy and free VBT data
- */
-void psb_intel_destroy_bios(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_display_mode *sdvo_lvds_vbt_mode =
-                               dev_priv->sdvo_lvds_vbt_mode;
-       struct drm_display_mode *lfp_lvds_vbt_mode =
-                               dev_priv->lfp_lvds_vbt_mode;
-       struct bdb_lvds_backlight *lvds_bl =
-                               dev_priv->lvds_bl;
-
-       /*free sdvo panel mode*/
-       if (sdvo_lvds_vbt_mode) {
-               dev_priv->sdvo_lvds_vbt_mode = NULL;
-               kfree(sdvo_lvds_vbt_mode);
-       }
-
-       if (lfp_lvds_vbt_mode) {
-               dev_priv->lfp_lvds_vbt_mode = NULL;
-               kfree(lfp_lvds_vbt_mode);
-       }
-
-       if (lvds_bl) {
-               dev_priv->lvds_bl = NULL;
-               kfree(lvds_bl);
-       }
-}
diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h
deleted file mode 100644 (file)
index 70f1bf0..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _I830_BIOS_H_
-#define _I830_BIOS_H_
-
-#include <drm/drmP.h>
-
-struct vbt_header {
-       u8 signature[20];               /**< Always starts with 'VBT$' */
-       u16 version;                    /**< decimal */
-       u16 header_size;                /**< in bytes */
-       u16 vbt_size;                   /**< in bytes */
-       u8 vbt_checksum;
-       u8 reserved0;
-       u32 bdb_offset;                 /**< from beginning of VBT */
-       u32 aim_offset[4];              /**< from beginning of VBT */
-} __attribute__((packed));
-
-
-struct bdb_header {
-       u8 signature[16];               /**< Always 'BIOS_DATA_BLOCK' */
-       u16 version;                    /**< decimal */
-       u16 header_size;                /**< in bytes */
-       u16 bdb_size;                   /**< in bytes */
-};
-
-/* strictly speaking, this is a "skip" block, but it has interesting info */
-struct vbios_data {
-       u8 type; /* 0 == desktop, 1 == mobile */
-       u8 relstage;
-       u8 chipset;
-       u8 lvds_present:1;
-       u8 tv_present:1;
-       u8 rsvd2:6; /* finish byte */
-       u8 rsvd3[4];
-       u8 signon[155];
-       u8 copyright[61];
-       u16 code_segment;
-       u8 dos_boot_mode;
-       u8 bandwidth_percent;
-       u8 rsvd4; /* popup memory size */
-       u8 resize_pci_bios;
-       u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
-
-/*
- * There are several types of BIOS data blocks (BDBs), each block has
- * an ID and size in the first 3 bytes (ID in first, size in next 2).
- * Known types are listed below.
- */
-#define BDB_GENERAL_FEATURES     1
-#define BDB_GENERAL_DEFINITIONS          2
-#define BDB_OLD_TOGGLE_LIST      3
-#define BDB_MODE_SUPPORT_LIST    4
-#define BDB_GENERIC_MODE_TABLE   5
-#define BDB_EXT_MMIO_REGS        6
-#define BDB_SWF_IO               7
-#define BDB_SWF_MMIO             8
-#define BDB_DOT_CLOCK_TABLE      9
-#define BDB_MODE_REMOVAL_TABLE  10
-#define BDB_CHILD_DEVICE_TABLE  11
-#define BDB_DRIVER_FEATURES     12
-#define BDB_DRIVER_PERSISTENCE  13
-#define BDB_EXT_TABLE_PTRS      14
-#define BDB_DOT_CLOCK_OVERRIDE  15
-#define BDB_DISPLAY_SELECT      16
-/* 17 rsvd */
-#define BDB_DRIVER_ROTATION     18
-#define BDB_DISPLAY_REMOVE      19
-#define BDB_OEM_CUSTOM          20
-#define BDB_EFP_LIST            21 /* workarounds for VGA hsync/vsync */
-#define BDB_SDVO_LVDS_OPTIONS   22
-#define BDB_SDVO_PANEL_DTDS     23
-#define BDB_SDVO_LVDS_PNP_IDS   24
-#define BDB_SDVO_LVDS_POWER_SEQ         25
-#define BDB_TV_OPTIONS          26
-#define BDB_LVDS_OPTIONS        40
-#define BDB_LVDS_LFP_DATA_PTRS  41
-#define BDB_LVDS_LFP_DATA       42
-#define BDB_LVDS_BACKLIGHT      43
-#define BDB_LVDS_POWER          44
-#define BDB_SKIP               254 /* VBIOS private block, ignore */
-
-struct bdb_general_features {
-       /* bits 1 */
-       u8 panel_fitting:2;
-       u8 flexaim:1;
-       u8 msg_enable:1;
-       u8 clear_screen:3;
-       u8 color_flip:1;
-
-       /* bits 2 */
-       u8 download_ext_vbt:1;
-       u8 enable_ssc:1;
-       u8 ssc_freq:1;
-       u8 enable_lfp_on_override:1;
-       u8 disable_ssc_ddt:1;
-       u8 rsvd8:3; /* finish byte */
-
-       /* bits 3 */
-       u8 disable_smooth_vision:1;
-       u8 single_dvi:1;
-       u8 rsvd9:6; /* finish byte */
-
-       /* bits 4 */
-       u8 legacy_monitor_detect;
-
-       /* bits 5 */
-       u8 int_crt_support:1;
-       u8 int_tv_support:1;
-       u8 rsvd11:6; /* finish byte */
-} __attribute__((packed));
-
-struct bdb_general_definitions {
-       /* DDC GPIO */
-       u8 crt_ddc_gmbus_pin;
-
-       /* DPMS bits */
-       u8 dpms_acpi:1;
-       u8 skip_boot_crt_detect:1;
-       u8 dpms_aim:1;
-       u8 rsvd1:5; /* finish byte */
-
-       /* boot device bits */
-       u8 boot_display[2];
-       u8 child_dev_size;
-
-       /* device info */
-       u8 tv_or_lvds_info[33];
-       u8 dev1[33];
-       u8 dev2[33];
-       u8 dev3[33];
-       u8 dev4[33];
-       /* may be another device block here on some platforms */
-};
-
-struct bdb_lvds_options {
-       u8 panel_type;
-       u8 rsvd1;
-       /* LVDS capabilities, stored in a dword */
-       u8 pfit_mode:2;
-       u8 pfit_text_mode_enhanced:1;
-       u8 pfit_gfx_mode_enhanced:1;
-       u8 pfit_ratio_auto:1;
-       u8 pixel_dither:1;
-       u8 lvds_edid:1;
-       u8 rsvd2:1;
-       u8 rsvd4;
-} __attribute__((packed));
-
-struct bdb_lvds_backlight {
-       u8 type:2;
-       u8 pol:1;
-       u8 gpio:3;
-       u8 gmbus:2;
-       u16 freq;
-       u8 minbrightness;
-       u8 i2caddr;
-       u8 brightnesscmd;
-       /*FIXME: more...*/
-} __attribute__((packed));
-
-/* LFP pointer table contains entries to the struct below */
-struct bdb_lvds_lfp_data_ptr {
-       u16 fp_timing_offset; /* offsets are from start of bdb */
-       u8 fp_table_size;
-       u16 dvo_timing_offset;
-       u8 dvo_table_size;
-       u16 panel_pnp_id_offset;
-       u8 pnp_table_size;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_ptrs {
-       u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
-       struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
-
-/* LFP data has 3 blocks per entry */
-struct lvds_fp_timing {
-       u16 x_res;
-       u16 y_res;
-       u32 lvds_reg;
-       u32 lvds_reg_val;
-       u32 pp_on_reg;
-       u32 pp_on_reg_val;
-       u32 pp_off_reg;
-       u32 pp_off_reg_val;
-       u32 pp_cycle_reg;
-       u32 pp_cycle_reg_val;
-       u32 pfit_reg;
-       u32 pfit_reg_val;
-       u16 terminator;
-} __attribute__((packed));
-
-struct lvds_dvo_timing {
-       u16 clock;              /**< In 10khz */
-       u8 hactive_lo;
-       u8 hblank_lo;
-       u8 hblank_hi:4;
-       u8 hactive_hi:4;
-       u8 vactive_lo;
-       u8 vblank_lo;
-       u8 vblank_hi:4;
-       u8 vactive_hi:4;
-       u8 hsync_off_lo;
-       u8 hsync_pulse_width;
-       u8 vsync_pulse_width:4;
-       u8 vsync_off:4;
-       u8 rsvd0:6;
-       u8 hsync_off_hi:2;
-       u8 h_image;
-       u8 v_image;
-       u8 max_hv;
-       u8 h_border;
-       u8 v_border;
-       u8 rsvd1:3;
-       u8 digital:2;
-       u8 vsync_positive:1;
-       u8 hsync_positive:1;
-       u8 rsvd2:1;
-} __attribute__((packed));
-
-struct lvds_pnp_id {
-       u16 mfg_name;
-       u16 product_code;
-       u32 serial;
-       u8 mfg_week;
-       u8 mfg_year;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_entry {
-       struct lvds_fp_timing fp_timing;
-       struct lvds_dvo_timing dvo_timing;
-       struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data {
-       struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
-
-struct aimdb_header {
-       char signature[16];
-       char oem_device[20];
-       u16 aimdb_version;
-       u16 aimdb_header_size;
-       u16 aimdb_size;
-} __attribute__((packed));
-
-struct aimdb_block {
-       u8 aimdb_id;
-       u16 aimdb_size;
-} __attribute__((packed));
-
-struct vch_panel_data {
-       u16 fp_timing_offset;
-       u8 fp_timing_size;
-       u16 dvo_timing_offset;
-       u8 dvo_timing_size;
-       u16 text_fitting_offset;
-       u8 text_fitting_size;
-       u16 graphics_fitting_offset;
-       u8 graphics_fitting_size;
-} __attribute__((packed));
-
-struct vch_bdb_22 {
-       struct aimdb_block aimdb_block;
-       struct vch_panel_data panels[16];
-} __attribute__((packed));
-
-struct bdb_sdvo_lvds_options {
-       u8 panel_backlight;
-       u8 h40_set_panel_type;
-       u8 panel_type;
-       u8 ssc_clk_freq;
-       u16 als_low_trip;
-       u16 als_high_trip;
-       u8 sclalarcoeff_tab_row_num;
-       u8 sclalarcoeff_tab_row_size;
-       u8 coefficient[8];
-       u8 panel_misc_bits_1;
-       u8 panel_misc_bits_2;
-       u8 panel_misc_bits_3;
-       u8 panel_misc_bits_4;
-} __attribute__((packed));
-
-
-extern bool psb_intel_init_bios(struct drm_device *dev);
-extern void psb_intel_destroy_bios(struct drm_device *dev);
-
-/*
- * Driver<->VBIOS interaction occurs through scratch bits in
- * GR18 & SWF*.
- */
-
-/* GR18 bits are set on display switch and hotkey events */
-#define GR18_DRIVER_SWITCH_EN  (1<<7) /* 0: VBIOS control, 1: driver control */
-#define GR18_HOTKEY_MASK       0x78 /* See also SWF4 15:0 */
-#define   GR18_HK_NONE         (0x0<<3)
-#define   GR18_HK_LFP_STRETCH  (0x1<<3)
-#define   GR18_HK_TOGGLE_DISP  (0x2<<3)
-#define   GR18_HK_DISP_SWITCH  (0x4<<3) /* see SWF14 15:0 for what to enable */
-#define   GR18_HK_POPUP_DISABLED (0x6<<3)
-#define   GR18_HK_POPUP_ENABLED        (0x7<<3)
-#define   GR18_HK_PFIT         (0x8<<3)
-#define   GR18_HK_APM_CHANGE   (0xa<<3)
-#define   GR18_HK_MULTIPLE     (0xc<<3)
-#define GR18_USER_INT_EN       (1<<2)
-#define GR18_A0000_FLUSH_EN    (1<<1)
-#define GR18_SMM_EN            (1<<0)
-
-/* Set by driver, cleared by VBIOS */
-#define SWF00_YRES_SHIFT       16
-#define SWF00_XRES_SHIFT       0
-#define SWF00_RES_MASK         0xffff
-
-/* Set by VBIOS at boot time and driver at runtime */
-#define SWF01_TV2_FORMAT_SHIFT 8
-#define SWF01_TV1_FORMAT_SHIFT 0
-#define SWF01_TV_FORMAT_MASK   0xffff
-
-#define SWF10_VBIOS_BLC_I2C_EN (1<<29)
-#define SWF10_GTT_OVERRIDE_EN  (1<<28)
-#define SWF10_LFP_DPMS_OVR     (1<<27) /* override DPMS on display switch */
-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
-#define   SWF10_OLD_TOGGLE     0x0
-#define   SWF10_TOGGLE_LIST_1  0x1
-#define   SWF10_TOGGLE_LIST_2  0x2
-#define   SWF10_TOGGLE_LIST_3  0x3
-#define   SWF10_TOGGLE_LIST_4  0x4
-#define SWF10_PANNING_EN       (1<<23)
-#define SWF10_DRIVER_LOADED    (1<<22)
-#define SWF10_EXTENDED_DESKTOP (1<<21)
-#define SWF10_EXCLUSIVE_MODE   (1<<20)
-#define SWF10_OVERLAY_EN       (1<<19)
-#define SWF10_PLANEB_HOLDOFF   (1<<18)
-#define SWF10_PLANEA_HOLDOFF   (1<<17)
-#define SWF10_VGA_HOLDOFF      (1<<16)
-#define SWF10_ACTIVE_DISP_MASK 0xffff
-#define   SWF10_PIPEB_LFP2     (1<<15)
-#define   SWF10_PIPEB_EFP2     (1<<14)
-#define   SWF10_PIPEB_TV2      (1<<13)
-#define   SWF10_PIPEB_CRT2     (1<<12)
-#define   SWF10_PIPEB_LFP      (1<<11)
-#define   SWF10_PIPEB_EFP      (1<<10)
-#define   SWF10_PIPEB_TV       (1<<9)
-#define   SWF10_PIPEB_CRT      (1<<8)
-#define   SWF10_PIPEA_LFP2     (1<<7)
-#define   SWF10_PIPEA_EFP2     (1<<6)
-#define   SWF10_PIPEA_TV2      (1<<5)
-#define   SWF10_PIPEA_CRT2     (1<<4)
-#define   SWF10_PIPEA_LFP      (1<<3)
-#define   SWF10_PIPEA_EFP      (1<<2)
-#define   SWF10_PIPEA_TV       (1<<1)
-#define   SWF10_PIPEA_CRT      (1<<0)
-
-#define SWF11_MEMORY_SIZE_SHIFT        16
-#define SWF11_SV_TEST_EN       (1<<15)
-#define SWF11_IS_AGP           (1<<14)
-#define SWF11_DISPLAY_HOLDOFF  (1<<13)
-#define SWF11_DPMS_REDUCED     (1<<12)
-#define SWF11_IS_VBE_MODE      (1<<11)
-#define SWF11_PIPEB_ACCESS     (1<<10) /* 0 here means pipe a */
-#define SWF11_DPMS_MASK                0x07
-#define   SWF11_DPMS_OFF       (1<<2)
-#define   SWF11_DPMS_SUSPEND   (1<<1)
-#define   SWF11_DPMS_STANDBY   (1<<0)
-#define   SWF11_DPMS_ON                0
-
-#define SWF14_GFX_PFIT_EN      (1<<31)
-#define SWF14_TEXT_PFIT_EN     (1<<30)
-#define SWF14_LID_STATUS_CLOSED        (1<<29) /* 0 here means open */
-#define SWF14_POPUP_EN         (1<<28)
-#define SWF14_DISPLAY_HOLDOFF  (1<<27)
-#define SWF14_DISP_DETECT_EN   (1<<26)
-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
-#define SWF14_DRIVER_STATUS    (1<<24)
-#define SWF14_OS_TYPE_WIN9X    (1<<23)
-#define SWF14_OS_TYPE_WINNT    (1<<22)
-/* 21:19 rsvd */
-#define SWF14_PM_TYPE_MASK     0x00070000
-#define   SWF14_PM_ACPI_VIDEO  (0x4 << 16)
-#define   SWF14_PM_ACPI                (0x3 << 16)
-#define   SWF14_PM_APM_12      (0x2 << 16)
-#define   SWF14_PM_APM_11      (0x1 << 16)
-#define SWF14_HK_REQUEST_MASK  0x0000ffff /* see GR18 6:3 for event type */
-         /* if GR18 indicates a display switch */
-#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
-#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
-#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
-#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
-#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
-#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
-#define   SWF14_DS_PIPEB_TV_EN  (1<<9)
-#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
-#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
-#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
-#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
-#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
-#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
-#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
-#define   SWF14_DS_PIPEA_TV_EN  (1<<1)
-#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
-         /* if GR18 indicates a panel fitting request */
-#define   SWF14_PFIT_EN                (1<<0) /* 0 means disable */
-         /* if GR18 indicates an APM change request */
-#define   SWF14_APM_HIBERNATE  0x4
-#define   SWF14_APM_SUSPEND    0x3
-#define   SWF14_APM_STANDBY    0x1
-#define   SWF14_APM_RESTORE    0x0
-
-#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c
deleted file mode 100644 (file)
index 51cbf65..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright Â© 2006-2007 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/export.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-
-/*
- * Intel GPIO access functions
- */
-
-#define I2C_RISEFALL_TIME 20
-
-static int get_clock(void *data)
-{
-       struct psb_intel_i2c_chan *chan = data;
-       struct drm_device *dev = chan->drm_dev;
-       u32 val;
-
-       val = REG_READ(chan->reg);
-       return (val & GPIO_CLOCK_VAL_IN) != 0;
-}
-
-static int get_data(void *data)
-{
-       struct psb_intel_i2c_chan *chan = data;
-       struct drm_device *dev = chan->drm_dev;
-       u32 val;
-
-       val = REG_READ(chan->reg);
-       return (val & GPIO_DATA_VAL_IN) != 0;
-}
-
-static void set_clock(void *data, int state_high)
-{
-       struct psb_intel_i2c_chan *chan = data;
-       struct drm_device *dev = chan->drm_dev;
-       u32 reserved = 0, clock_bits;
-
-       /* On most chips, these bits must be preserved in software. */
-       reserved =
-                   REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
-                                          GPIO_CLOCK_PULLUP_DISABLE);
-
-       if (state_high)
-               clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
-       else
-               clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
-                   GPIO_CLOCK_VAL_MASK;
-       REG_WRITE(chan->reg, reserved | clock_bits);
-       udelay(I2C_RISEFALL_TIME);      /* wait for the line to change state */
-}
-
-static void set_data(void *data, int state_high)
-{
-       struct psb_intel_i2c_chan *chan = data;
-       struct drm_device *dev = chan->drm_dev;
-       u32 reserved = 0, data_bits;
-
-       /* On most chips, these bits must be preserved in software. */
-       reserved =
-                   REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
-                                          GPIO_CLOCK_PULLUP_DISABLE);
-
-       if (state_high)
-               data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
-       else
-               data_bits =
-                   GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
-                   GPIO_DATA_VAL_MASK;
-
-       REG_WRITE(chan->reg, reserved | data_bits);
-       udelay(I2C_RISEFALL_TIME);      /* wait for the line to change state */
-}
-
-/**
- * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
- * @dev: DRM device
- * @output: driver specific output device
- * @reg: GPIO reg to use
- * @name: name for this bus
- *
- * Creates and registers a new i2c bus with the Linux i2c layer, for use
- * in output probing and control (e.g. DDC or SDVO control functions).
- *
- * Possible values for @reg include:
- *   %GPIOA
- *   %GPIOB
- *   %GPIOC
- *   %GPIOD
- *   %GPIOE
- *   %GPIOF
- *   %GPIOG
- *   %GPIOH
- * see PRM for details on how these different busses are used.
- */
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
-                                       const u32 reg, const char *name)
-{
-       struct psb_intel_i2c_chan *chan;
-
-       chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
-       if (!chan)
-               goto out_free;
-
-       chan->drm_dev = dev;
-       chan->reg = reg;
-       snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
-       chan->adapter.owner = THIS_MODULE;
-       chan->adapter.algo_data = &chan->algo;
-       chan->adapter.dev.parent = &dev->pdev->dev;
-       chan->algo.setsda = set_data;
-       chan->algo.setscl = set_clock;
-       chan->algo.getsda = get_data;
-       chan->algo.getscl = get_clock;
-       chan->algo.udelay = 20;
-       chan->algo.timeout = usecs_to_jiffies(2200);
-       chan->algo.data = chan;
-
-       i2c_set_adapdata(&chan->adapter, chan);
-
-       if (i2c_bit_add_bus(&chan->adapter))
-               goto out_free;
-
-       /* JJJ:  raise SCL and SDA? */
-       set_data(chan, 1);
-       set_clock(chan, 1);
-       udelay(20);
-
-       return chan;
-
-out_free:
-       kfree(chan);
-       return NULL;
-}
-
-/**
- * psb_intel_i2c_destroy - unregister and free i2c bus resources
- * @output: channel to free
- *
- * Unregister the adapter from the i2c layer, then free the structure.
- */
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
-{
-       if (!chan)
-               return;
-
-       i2c_del_adapter(&chan->adapter);
-       kfree(chan);
-}
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c
deleted file mode 100644 (file)
index d946bc1..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * FIXME: resolve with the i915 version
- */
-
-#include "psb_drv.h"
-
-struct opregion_header {
-       u8 signature[16];
-       u32 size;
-       u32 opregion_ver;
-       u8 bios_ver[32];
-       u8 vbios_ver[16];
-       u8 driver_ver[16];
-       u32 mboxes;
-       u8 reserved[164];
-} __packed;
-
-struct opregion_apci {
-       /*FIXME: add it later*/
-} __packed;
-
-struct opregion_swsci {
-       /*FIXME: add it later*/
-} __packed;
-
-struct opregion_acpi {
-       /*FIXME: add it later*/
-} __packed;
-
-int gma_intel_opregion_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 opregion_phy;
-       void *base;
-       u32 *lid_state;
-
-       dev_priv->lid_state = NULL;
-
-       pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
-       if (opregion_phy == 0)
-               return -ENOTSUPP;
-
-       base = ioremap(opregion_phy, 8*1024);
-       if (!base)
-               return -ENOMEM;
-
-       lid_state = base + 0x01ac;
-
-       dev_priv->lid_state = lid_state;
-       dev_priv->lid_last_state = readl(lid_state);
-       return 0;
-}
-
-int gma_intel_opregion_exit(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       if (dev_priv->lid_state)
-               iounmap(dev_priv->lid_state);
-       return 0;
-}
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
deleted file mode 100644 (file)
index f47aeb7..0000000
+++ /dev/null
@@ -1,714 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_output.h"
-#include "mid_bios.h"
-
-/*
- *     Provide the Medfield specific backlight management
- */
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-static int mdfld_brightness;
-struct backlight_device *mdfld_backlight_device;
-
-static int mfld_set_brightness(struct backlight_device *bd)
-{
-       struct drm_device *dev = bl_get_data(mdfld_backlight_device);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int level = bd->props.brightness;
-
-       /* Percentage 1-100% being valid */
-       if (level < 1)
-               level = 1;
-
-       if (gma_power_begin(dev, 0)) {
-               /* Calculate and set the brightness value */
-               u32 adjusted_level;
-
-               /* Adjust the backlight level with the percent in
-                * dev_priv->blc_adj2;
-                */
-               adjusted_level = level * dev_priv->blc_adj2;
-               adjusted_level = adjusted_level / 100;
-#if 0
-#ifndef CONFIG_MDFLD_DSI_DPU
-               if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && 
-                       (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
-                       mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
-                       dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
-               }
-#endif
-               mdfld_dsi_brightness_control(dev, 0, adjusted_level);
-
-               if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
-                       mdfld_dsi_brightness_control(dev, 2, adjusted_level);
-#endif
-               gma_power_end(dev);
-       }
-       mdfld_brightness = level;
-       return 0;
-}
-
-int psb_get_brightness(struct backlight_device *bd)
-{
-       /* return locally cached var instead of HW read (due to DPST etc.) */
-       /* FIXME: ideally return actual value in case firmware fiddled with
-          it */
-       return mdfld_brightness;
-}
-
-static const struct backlight_ops mfld_ops = {
-       .get_brightness = psb_get_brightness,
-       .update_status  = mfld_set_brightness,
-};
-
-static int mdfld_backlight_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct backlight_properties props;
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.max_brightness = 100;
-       props.type = BACKLIGHT_PLATFORM;
-
-       mdfld_backlight_device = backlight_device_register("mfld-bl",
-                                       NULL, (void *)dev, &mfld_ops, &props);
-                                       
-       if (IS_ERR(mdfld_backlight_device))
-               return PTR_ERR(mdfld_backlight_device);
-
-       dev_priv->blc_adj1 = 100;
-       dev_priv->blc_adj2 = 100;
-       mdfld_backlight_device->props.brightness = 100;
-       mdfld_backlight_device->props.max_brightness = 100;
-       backlight_update_status(mdfld_backlight_device);
-       dev_priv->backlight_device = mdfld_backlight_device;
-       return 0;
-}
-
-#endif
-
-/*
- *     Provide the Medfield specific chip logic and low level methods for
- *     power management.
- */
-
-static void mdfld_init_pm(struct drm_device *dev)
-{
-       /* No work needed here yet */
-}
-
-/**
- * mdfld_save_display_registers        -       save registers for pipe
- * @dev: our device
- * @pipe: pipe to save
- *
- * Save the pipe state of the device before we power it off. Keep everything
- * we need to put it back again
- */
-static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int i;
-
-       /* register */
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 fp_reg = MRST_FPA0;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 htot_reg = HTOTAL_A;
-       u32 hblank_reg = HBLANK_A;
-       u32 hsync_reg = HSYNC_A;
-       u32 vtot_reg = VTOTAL_A;
-       u32 vblank_reg = VBLANK_A;
-       u32 vsync_reg = VSYNC_A;
-       u32 pipesrc_reg = PIPEASRC;
-       u32 dspstride_reg = DSPASTRIDE;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dsptileoff_reg = DSPATILEOFF;
-       u32 dspsize_reg = DSPASIZE;
-       u32 dsppos_reg = DSPAPOS;
-       u32 dspsurf_reg = DSPASURF;
-       u32 mipi_reg = MIPI;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 dspstatus_reg = PIPEASTAT;
-       u32 palette_reg = PALETTE_A;
-
-       /* pointer to values */
-       u32 *dpll_val = &dev_priv->saveDPLL_A;
-       u32 *fp_val = &dev_priv->saveFPA0;
-       u32 *pipeconf_val = &dev_priv->savePIPEACONF;
-       u32 *htot_val = &dev_priv->saveHTOTAL_A;
-       u32 *hblank_val = &dev_priv->saveHBLANK_A;
-       u32 *hsync_val = &dev_priv->saveHSYNC_A;
-       u32 *vtot_val = &dev_priv->saveVTOTAL_A;
-       u32 *vblank_val = &dev_priv->saveVBLANK_A;
-       u32 *vsync_val = &dev_priv->saveVSYNC_A;
-       u32 *pipesrc_val = &dev_priv->savePIPEASRC;
-       u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
-       u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
-       u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
-       u32 *dspsize_val = &dev_priv->saveDSPASIZE;
-       u32 *dsppos_val = &dev_priv->saveDSPAPOS;
-       u32 *dspsurf_val = &dev_priv->saveDSPASURF;
-       u32 *mipi_val = &dev_priv->saveMIPI;
-       u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
-       u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
-       u32 *palette_val = dev_priv->save_palette_a;
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               /* register */
-               dpll_reg = MDFLD_DPLL_B;
-               fp_reg = MDFLD_DPLL_DIV0;
-               pipeconf_reg = PIPEBCONF;
-               htot_reg = HTOTAL_B;
-               hblank_reg = HBLANK_B;
-               hsync_reg = HSYNC_B;
-               vtot_reg = VTOTAL_B;
-               vblank_reg = VBLANK_B;
-               vsync_reg = VSYNC_B;
-               pipesrc_reg = PIPEBSRC;
-               dspstride_reg = DSPBSTRIDE;
-               dsplinoff_reg = DSPBLINOFF;
-               dsptileoff_reg = DSPBTILEOFF;
-               dspsize_reg = DSPBSIZE;
-               dsppos_reg = DSPBPOS;
-               dspsurf_reg = DSPBSURF;
-               dspcntr_reg = DSPBCNTR;
-               dspstatus_reg = PIPEBSTAT;
-               palette_reg = PALETTE_B;
-
-               /* values */
-               dpll_val = &dev_priv->saveDPLL_B;
-               fp_val = &dev_priv->saveFPB0;
-               pipeconf_val = &dev_priv->savePIPEBCONF;
-               htot_val = &dev_priv->saveHTOTAL_B;
-               hblank_val = &dev_priv->saveHBLANK_B;
-               hsync_val = &dev_priv->saveHSYNC_B;
-               vtot_val = &dev_priv->saveVTOTAL_B;
-               vblank_val = &dev_priv->saveVBLANK_B;
-               vsync_val = &dev_priv->saveVSYNC_B;
-               pipesrc_val = &dev_priv->savePIPEBSRC;
-               dspstride_val = &dev_priv->saveDSPBSTRIDE;
-               dsplinoff_val = &dev_priv->saveDSPBLINOFF;
-               dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
-               dspsize_val = &dev_priv->saveDSPBSIZE;
-               dsppos_val = &dev_priv->saveDSPBPOS;
-               dspsurf_val = &dev_priv->saveDSPBSURF;
-               dspcntr_val = &dev_priv->saveDSPBCNTR;
-               dspstatus_val = &dev_priv->saveDSPBSTATUS;
-               palette_val = dev_priv->save_palette_b;
-               break;
-       case 2:
-               /* register */
-               pipeconf_reg = PIPECCONF;
-               htot_reg = HTOTAL_C;
-               hblank_reg = HBLANK_C;
-               hsync_reg = HSYNC_C;
-               vtot_reg = VTOTAL_C;
-               vblank_reg = VBLANK_C;
-               vsync_reg = VSYNC_C;
-               pipesrc_reg = PIPECSRC;
-               dspstride_reg = DSPCSTRIDE;
-               dsplinoff_reg = DSPCLINOFF;
-               dsptileoff_reg = DSPCTILEOFF;
-               dspsize_reg = DSPCSIZE;
-               dsppos_reg = DSPCPOS;
-               dspsurf_reg = DSPCSURF;
-               mipi_reg = MIPI_C;
-               dspcntr_reg = DSPCCNTR;
-               dspstatus_reg = PIPECSTAT;
-               palette_reg = PALETTE_C;
-
-               /* pointer to values */
-               pipeconf_val = &dev_priv->savePIPECCONF;
-               htot_val = &dev_priv->saveHTOTAL_C;
-               hblank_val = &dev_priv->saveHBLANK_C;
-               hsync_val = &dev_priv->saveHSYNC_C;
-               vtot_val = &dev_priv->saveVTOTAL_C;
-               vblank_val = &dev_priv->saveVBLANK_C;
-               vsync_val = &dev_priv->saveVSYNC_C;
-               pipesrc_val = &dev_priv->savePIPECSRC;
-               dspstride_val = &dev_priv->saveDSPCSTRIDE;
-               dsplinoff_val = &dev_priv->saveDSPCLINOFF;
-               dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
-               dspsize_val = &dev_priv->saveDSPCSIZE;
-               dsppos_val = &dev_priv->saveDSPCPOS;
-               dspsurf_val = &dev_priv->saveDSPCSURF;
-               mipi_val = &dev_priv->saveMIPI_C;
-               dspcntr_val = &dev_priv->saveDSPCCNTR;
-               dspstatus_val = &dev_priv->saveDSPCSTATUS;
-               palette_val = dev_priv->save_palette_c;
-               break;
-       default:
-               DRM_ERROR("%s, invalid pipe number.\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Pipe & plane A info */
-       *dpll_val = PSB_RVDC32(dpll_reg);
-       *fp_val = PSB_RVDC32(fp_reg);
-       *pipeconf_val = PSB_RVDC32(pipeconf_reg);
-       *htot_val = PSB_RVDC32(htot_reg);
-       *hblank_val = PSB_RVDC32(hblank_reg);
-       *hsync_val = PSB_RVDC32(hsync_reg);
-       *vtot_val = PSB_RVDC32(vtot_reg);
-       *vblank_val = PSB_RVDC32(vblank_reg);
-       *vsync_val = PSB_RVDC32(vsync_reg);
-       *pipesrc_val = PSB_RVDC32(pipesrc_reg);
-       *dspstride_val = PSB_RVDC32(dspstride_reg);
-       *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
-       *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
-       *dspsize_val = PSB_RVDC32(dspsize_reg);
-       *dsppos_val = PSB_RVDC32(dsppos_reg);
-       *dspsurf_val = PSB_RVDC32(dspsurf_reg);
-       *dspcntr_val = PSB_RVDC32(dspcntr_reg);
-       *dspstatus_val = PSB_RVDC32(dspstatus_reg);
-
-       /*save palette (gamma) */
-       for (i = 0; i < 256; i++)
-               palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
-
-       if (pipe == 1) {
-               dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
-               dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
-               dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
-               dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
-               return 0;
-       }
-       *mipi_val = PSB_RVDC32(mipi_reg);
-       return 0;
-}
-
-/**
- * mdfld_save_cursor_overlay_registers -       save cursor overlay info
- * @dev: our device
- *
- * Save the cursor and overlay register state
- */
-static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       /* Save cursor regs */
-       dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
-       dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
-       dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
-
-       dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
-       dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
-       dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
-
-       dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
-       dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
-       dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
-
-       /* HW overlay */
-       dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
-       dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
-       dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
-       dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
-       dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
-       dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
-       dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-
-       dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
-       dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
-       dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
-       dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
-       dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
-       dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
-       dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
-
-       return 0;
-}
-/*
- * mdfld_restore_display_registers     -       restore the state of a pipe
- * @dev: our device
- * @pipe: the pipe to restore
- *
- * Restore the state of a pipe to that which was saved by the register save
- * functions.
- */
-static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
-{
-       /* To get  panel out of ULPS mode */
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dsi_config *dsi_config = NULL;
-       u32 i = 0;
-       u32 dpll = 0;
-       u32 timeout = 0;
-       u32 reg_offset = 0;
-
-       /* register */
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 fp_reg = MRST_FPA0;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 htot_reg = HTOTAL_A;
-       u32 hblank_reg = HBLANK_A;
-       u32 hsync_reg = HSYNC_A;
-       u32 vtot_reg = VTOTAL_A;
-       u32 vblank_reg = VBLANK_A;
-       u32 vsync_reg = VSYNC_A;
-       u32 pipesrc_reg = PIPEASRC;
-       u32 dspstride_reg = DSPASTRIDE;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dsptileoff_reg = DSPATILEOFF;
-       u32 dspsize_reg = DSPASIZE;
-       u32 dsppos_reg = DSPAPOS;
-       u32 dspsurf_reg = DSPASURF;
-       u32 dspstatus_reg = PIPEASTAT;
-       u32 mipi_reg = MIPI;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 palette_reg = PALETTE_A;
-
-       /* values */
-       u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
-       u32 fp_val = dev_priv->saveFPA0;
-       u32 pipeconf_val = dev_priv->savePIPEACONF;
-       u32 htot_val = dev_priv->saveHTOTAL_A;
-       u32 hblank_val = dev_priv->saveHBLANK_A;
-       u32 hsync_val = dev_priv->saveHSYNC_A;
-       u32 vtot_val = dev_priv->saveVTOTAL_A;
-       u32 vblank_val = dev_priv->saveVBLANK_A;
-       u32 vsync_val = dev_priv->saveVSYNC_A;
-       u32 pipesrc_val = dev_priv->savePIPEASRC;
-       u32 dspstride_val = dev_priv->saveDSPASTRIDE;
-       u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
-       u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
-       u32 dspsize_val = dev_priv->saveDSPASIZE;
-       u32 dsppos_val = dev_priv->saveDSPAPOS;
-       u32 dspsurf_val = dev_priv->saveDSPASURF;
-       u32 dspstatus_val = dev_priv->saveDSPASTATUS;
-       u32 mipi_val = dev_priv->saveMIPI;
-       u32 dspcntr_val = dev_priv->saveDSPACNTR;
-       u32 *palette_val = dev_priv->save_palette_a;
-
-       switch (pipe) {
-       case 0:
-               dsi_config = dev_priv->dsi_configs[0];
-               break;
-       case 1:
-               /* register */
-               dpll_reg = MDFLD_DPLL_B;
-               fp_reg = MDFLD_DPLL_DIV0;
-               pipeconf_reg = PIPEBCONF;
-               htot_reg = HTOTAL_B;
-               hblank_reg = HBLANK_B;
-               hsync_reg = HSYNC_B;
-               vtot_reg = VTOTAL_B;
-               vblank_reg = VBLANK_B;
-               vsync_reg = VSYNC_B;
-               pipesrc_reg = PIPEBSRC;
-               dspstride_reg = DSPBSTRIDE;
-               dsplinoff_reg = DSPBLINOFF;
-               dsptileoff_reg = DSPBTILEOFF;
-               dspsize_reg = DSPBSIZE;
-               dsppos_reg = DSPBPOS;
-               dspsurf_reg = DSPBSURF;
-               dspcntr_reg = DSPBCNTR;
-               palette_reg = PALETTE_B;
-               dspstatus_reg = PIPEBSTAT;
-
-               /* values */
-               dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
-               fp_val = dev_priv->saveFPB0;
-               pipeconf_val = dev_priv->savePIPEBCONF;
-               htot_val = dev_priv->saveHTOTAL_B;
-               hblank_val = dev_priv->saveHBLANK_B;
-               hsync_val = dev_priv->saveHSYNC_B;
-               vtot_val = dev_priv->saveVTOTAL_B;
-               vblank_val = dev_priv->saveVBLANK_B;
-               vsync_val = dev_priv->saveVSYNC_B;
-               pipesrc_val = dev_priv->savePIPEBSRC;
-               dspstride_val = dev_priv->saveDSPBSTRIDE;
-               dsplinoff_val = dev_priv->saveDSPBLINOFF;
-               dsptileoff_val = dev_priv->saveDSPBTILEOFF;
-               dspsize_val = dev_priv->saveDSPBSIZE;
-               dsppos_val = dev_priv->saveDSPBPOS;
-               dspsurf_val = dev_priv->saveDSPBSURF;
-               dspcntr_val = dev_priv->saveDSPBCNTR;
-               dspstatus_val = dev_priv->saveDSPBSTATUS;
-               palette_val = dev_priv->save_palette_b;
-               break;
-       case 2:
-               reg_offset = MIPIC_REG_OFFSET;
-
-               /* register */
-               pipeconf_reg = PIPECCONF;
-               htot_reg = HTOTAL_C;
-               hblank_reg = HBLANK_C;
-               hsync_reg = HSYNC_C;
-               vtot_reg = VTOTAL_C;
-               vblank_reg = VBLANK_C;
-               vsync_reg = VSYNC_C;
-               pipesrc_reg = PIPECSRC;
-               dspstride_reg = DSPCSTRIDE;
-               dsplinoff_reg = DSPCLINOFF;
-               dsptileoff_reg = DSPCTILEOFF;
-               dspsize_reg = DSPCSIZE;
-               dsppos_reg = DSPCPOS;
-               dspsurf_reg = DSPCSURF;
-               mipi_reg = MIPI_C;
-               dspcntr_reg = DSPCCNTR;
-               palette_reg = PALETTE_C;
-               dspstatus_reg = PIPECSTAT;
-
-               /* values */
-               pipeconf_val = dev_priv->savePIPECCONF;
-               htot_val = dev_priv->saveHTOTAL_C;
-               hblank_val = dev_priv->saveHBLANK_C;
-               hsync_val = dev_priv->saveHSYNC_C;
-               vtot_val = dev_priv->saveVTOTAL_C;
-               vblank_val = dev_priv->saveVBLANK_C;
-               vsync_val = dev_priv->saveVSYNC_C;
-               pipesrc_val = dev_priv->savePIPECSRC;
-               dspstride_val = dev_priv->saveDSPCSTRIDE;
-               dsplinoff_val = dev_priv->saveDSPCLINOFF;
-               dsptileoff_val = dev_priv->saveDSPCTILEOFF;
-               dspsize_val = dev_priv->saveDSPCSIZE;
-               dsppos_val = dev_priv->saveDSPCPOS;
-               dspsurf_val = dev_priv->saveDSPCSURF;
-               dspstatus_val = dev_priv->saveDSPCSTATUS;
-               mipi_val = dev_priv->saveMIPI_C;
-               dspcntr_val = dev_priv->saveDSPCCNTR;
-               palette_val = dev_priv->save_palette_c;
-
-               dsi_config = dev_priv->dsi_configs[1];
-               break;
-       default:
-               DRM_ERROR("%s, invalid pipe number.\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Make sure VGA plane is off. it initializes to on after reset!*/
-       PSB_WVDC32(0x80000000, VGACNTRL);
-       if (pipe == 1) {
-               PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
-               PSB_RVDC32(dpll_reg);
-
-               PSB_WVDC32(fp_val, fp_reg);
-       } else {
-               dpll = PSB_RVDC32(dpll_reg);
-
-               if (!(dpll & DPLL_VCO_ENABLE)) {
-
-                       /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
-                       if (dpll & MDFLD_PWR_GATE_EN) {
-                               dpll &= ~MDFLD_PWR_GATE_EN;
-                               PSB_WVDC32(dpll, dpll_reg);
-                               udelay(500);    /* FIXME: 1 ? */
-                       }
-
-                       PSB_WVDC32(fp_val, fp_reg);
-                       PSB_WVDC32(dpll_val, dpll_reg);
-                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                       udelay(500);
-
-                       dpll_val |= DPLL_VCO_ENABLE;
-                       PSB_WVDC32(dpll_val, dpll_reg);
-                       PSB_RVDC32(dpll_reg);
-
-                       /* wait for DSI PLL to lock */
-                       while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
-                               udelay(150);
-                               timeout++;
-                       }
-
-                       if (timeout == 20000) {
-                               DRM_ERROR("%s, can't lock DSIPLL.\n",
-                                                       __func__);
-                               return -EINVAL;
-                       }
-               }
-       }
-       /* Restore mode */
-       PSB_WVDC32(htot_val, htot_reg);
-       PSB_WVDC32(hblank_val, hblank_reg);
-       PSB_WVDC32(hsync_val, hsync_reg);
-       PSB_WVDC32(vtot_val, vtot_reg);
-       PSB_WVDC32(vblank_val, vblank_reg);
-       PSB_WVDC32(vsync_val, vsync_reg);
-       PSB_WVDC32(pipesrc_val, pipesrc_reg);
-       PSB_WVDC32(dspstatus_val, dspstatus_reg);
-
-       /* Set up the plane */
-       PSB_WVDC32(dspstride_val, dspstride_reg);
-       PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
-       PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
-       PSB_WVDC32(dspsize_val, dspsize_reg);
-       PSB_WVDC32(dsppos_val, dsppos_reg);
-       PSB_WVDC32(dspsurf_val, dspsurf_reg);
-
-       if (pipe == 1) {
-               PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
-               PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
-               PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
-               PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
-
-       } else {
-               /* Set up pipe related registers */
-               PSB_WVDC32(mipi_val, mipi_reg);
-               /* Setup MIPI adapter + MIPI IP registers */
-               mdfld_dsi_controller_init(dsi_config, pipe);
-               msleep(20);
-       }
-       /* Enable the plane */
-       PSB_WVDC32(dspcntr_val, dspcntr_reg);
-       msleep(20);
-       /* Enable the pipe */
-       PSB_WVDC32(pipeconf_val, pipeconf_reg);
-
-       for (i = 0; i < 256; i++)
-               PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
-       if (pipe == 1)
-               return 0;
-       if (!mdfld_panel_dpi(dev))
-               mdfld_enable_te(dev, pipe);
-       return 0;
-}
-
-/**
- * mdfld_restore_cursor_overlay_registers      -       restore cursor
- * @dev: our device
- *
- * Restore the cursor and overlay state that was saved earlier
- */
-static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       /* Enable Cursor A */
-       PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
-       PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
-       PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
-
-       PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
-       PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
-       PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
-
-       PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
-       PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
-       PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
-
-       /* Restore HW overlay */
-       PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
-
-       PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
-
-       return 0;
-}
-
-/**
- *     mdfld_save_display_registers    -       save registers lost on suspend
- *     @dev: our DRM device
- *
- *     Save the state we need in order to be able to restore the interface
- *     upon resume from suspend
- */
-static int mdfld_save_registers(struct drm_device *dev)
-{
-       /* FIXME: We need to shut down panels here if using them
-          and once the right bits are merged */
-       mdfld_save_cursor_overlay_registers(dev);
-       mdfld_save_display_registers(dev, 0);
-       mdfld_save_display_registers(dev, 0);
-       mdfld_save_display_registers(dev, 2);
-       mdfld_save_display_registers(dev, 1);
-       mdfld_disable_crtc(dev, 0);
-       mdfld_disable_crtc(dev, 2);
-       mdfld_disable_crtc(dev, 1);
-       return 0;
-}
-
-/**
- *     mdfld_restore_display_registers -       restore lost register state
- *     @dev: our DRM device
- *
- *     Restore register state that was lost during suspend and resume.
- */
-static int mdfld_restore_registers(struct drm_device *dev)
-{
-       mdfld_restore_display_registers(dev, 1);
-       mdfld_restore_display_registers(dev, 0);
-       mdfld_restore_display_registers(dev, 2);
-       mdfld_restore_cursor_overlay_registers(dev);
-       return 0;
-}
-
-static int mdfld_power_down(struct drm_device *dev)
-{
-       /* FIXME */
-       return 0;
-}
-
-static int mdfld_power_up(struct drm_device *dev)
-{
-       /* FIXME */
-       return 0;
-}
-
-const struct psb_ops mdfld_chip_ops = {
-       .name = "Medfield",
-       .accel_2d = 0,
-       .pipes = 3,
-       .crtcs = 2,
-       .sgx_offset = MRST_SGX_OFFSET,
-
-       .chip_setup = mid_chip_setup,
-
-       .crtc_helper = &mdfld_helper_funcs,
-       .crtc_funcs = &mdfld_intel_crtc_funcs,
-
-       .output_init = mdfld_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       .backlight_init = mdfld_backlight_init,
-#endif
-
-       .init_pm = mdfld_init_pm,
-       .save_regs = mdfld_save_registers,
-       .restore_regs = mdfld_restore_registers,
-       .power_down = mdfld_power_down,
-       .power_up = mdfld_power_up,
-};
-
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
deleted file mode 100644 (file)
index fd211f3..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *  jim liu <jim.liu@intel.com>
- *  Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-int enable_gfx_rtpm;
-
-extern struct drm_device *gpDrmDevice;
-extern int gfxrtdelay;
-int enter_dsr;
-struct mdfld_dsi_dbi_output *gdbi_output;
-extern bool gbgfxsuspended;
-extern int enable_gfx_rtpm;
-extern int gfxrtdelay;
-
-#define MDFLD_DSR_MAX_IDLE_COUNT       2
-
-/*
- * set refreshing area
- */
-int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
-                               u16 x1, u16 y1, u16 x2, u16 y2)
-{
-       struct mdfld_dsi_pkg_sender *sender =
-               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
-       u8 param[4];
-       u8 cmd;
-       int err;
-
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       /* Set column */
-       cmd = DCS_SET_COLUMN_ADDRESS;
-       param[0] = x1 >> 8;
-       param[1] = x1;
-       param[2] = x2 >> 8;
-       param[3] = x2;
-
-       err = mdfld_dsi_send_dcs(sender,
-                                cmd,
-                                param,
-                                4,
-                                CMD_DATA_SRC_SYSTEM_MEM,
-                                MDFLD_DSI_QUEUE_PACKAGE);
-       if (err) {
-               dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
-               goto err_out;
-       }
-
-       /* Set page */
-       cmd = DCS_SET_PAGE_ADDRESS;
-       param[0] = y1 >> 8;
-       param[1] = y1;
-       param[2] = y2 >> 8;
-       param[3] = y2;
-
-       err = mdfld_dsi_send_dcs(sender,
-                                cmd,
-                                param,
-                                4,
-                                CMD_DATA_SRC_SYSTEM_MEM,
-                                MDFLD_DSI_QUEUE_PACKAGE);
-       if (err) {
-               dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
-               goto err_out;
-       }
-
-       /*update screen*/
-       err = mdfld_dsi_send_dcs(sender,
-                                write_mem_start,
-                                NULL,
-                                0,
-                                CMD_DATA_SRC_PIPE,
-                                MDFLD_DSI_QUEUE_PACKAGE);
-       if (err) {
-               dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
-               goto err_out;
-       }
-       mdfld_dsi_cmds_kick_out(sender);
-err_out:
-       return err;
-}
-
-/*
- * set panel's power state
- */
-int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
-                                                               int mode)
-{
-       struct drm_device *dev = dbi_output->dev;
-       struct mdfld_dsi_pkg_sender *sender =
-               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
-       u8 param = 0;
-       u32 err = 0;
-
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       if (mode == DRM_MODE_DPMS_ON) {
-               /* Exit sleep mode */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_EXIT_SLEEP_MODE,
-                                        NULL,
-                                        0,
-                                        CMD_DATA_SRC_SYSTEM_MEM,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                               DCS_EXIT_SLEEP_MODE);
-                       goto power_err;
-               }
-
-               /* Set display on */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_SET_DISPLAY_ON,
-                                        NULL,
-                                        0,
-                                        CMD_DATA_SRC_SYSTEM_MEM,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                                       DCS_SET_DISPLAY_ON);
-                       goto power_err;
-               }
-
-               /* set tear effect on */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_SET_TEAR_ON,
-                                        &param,
-                                        1,
-                                        CMD_DATA_SRC_SYSTEM_MEM,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                                       set_tear_on);
-                       goto power_err;
-               }
-
-               /**
-                * FIXME: remove this later
-                */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_WRITE_MEM_START,
-                                        NULL,
-                                        0,
-                                        CMD_DATA_SRC_PIPE,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                               DCS_WRITE_MEM_START);
-                       goto power_err;
-               }
-       } else {
-               /* Set tear effect off */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_SET_TEAR_OFF,
-                                        NULL,
-                                        0,
-                                        CMD_DATA_SRC_SYSTEM_MEM,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                                       DCS_SET_TEAR_OFF);
-                       goto power_err;
-               }
-
-               /* Turn display off */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_SET_DISPLAY_OFF,
-                                        NULL,
-                                        0,
-                                        CMD_DATA_SRC_SYSTEM_MEM,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                               DCS_SET_DISPLAY_OFF);
-                       goto power_err;
-               }
-
-               /* Now enter sleep mode */
-               err = mdfld_dsi_send_dcs(sender,
-                                        DCS_ENTER_SLEEP_MODE,
-                                        NULL,
-                                        0,
-                                        CMD_DATA_SRC_SYSTEM_MEM,
-                                        MDFLD_DSI_QUEUE_PACKAGE);
-               if (err) {
-                       dev_err(dev->dev, "DCS 0x%x sent failed\n",
-                                                       DCS_ENTER_SLEEP_MODE);
-                       goto power_err;
-               }
-       }
-       mdfld_dsi_cmds_kick_out(sender);
-power_err:
-       return err;
-}
-
-/*
- * send a generic DCS command with a parameter list
- */
-int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
-                       u8 dcs,  u8 *param, u32 num, u8 data_src)
-{
-       struct mdfld_dsi_pkg_sender *sender =
-               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
-       int ret;
-
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       ret = mdfld_dsi_send_dcs(sender,
-                                dcs,
-                                param,
-                                num,
-                                data_src,
-                                MDFLD_DSI_SEND_PACKAGE);
-
-       return ret;
-}
-
-/*
- * Enter DSR
- */
-void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
-{
-       u32 reg_val;
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dbi_output->base.base.crtc;
-       struct psb_intel_crtc *psb_crtc = (crtc) ?
-                                       to_psb_intel_crtc(crtc) : NULL;
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dspcntr_reg = DSPACNTR;
-
-       if (!dbi_output)
-               return;
-
-       /* FIXME check if can go */
-       dev_priv->is_in_idle = true;
-
-       gdbi_output = dbi_output;
-       if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
-               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
-               return;
-
-       if (pipe == 2) {
-               dpll_reg = MRST_DPLL_A;
-               pipeconf_reg = PIPECCONF;
-               dspcntr_reg = DSPCCNTR;
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-       /* Disable te interrupts */
-       mdfld_disable_te(dev, pipe);
-
-       /* Disable plane */
-       reg_val = REG_READ(dspcntr_reg);
-       if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
-               REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
-               REG_READ(dspcntr_reg);
-       }
-
-       /* Disable pipe */
-       reg_val = REG_READ(pipeconf_reg);
-       if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
-               reg_val &= ~DISPLAY_PLANE_ENABLE;
-               reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
-               REG_WRITE(pipeconf_reg, reg_val);
-               REG_READ(pipeconf_reg);
-               mdfldWaitForPipeDisable(dev, pipe);
-       }
-
-       /* Disable DPLL */
-       reg_val = REG_READ(dpll_reg);
-       if (!(reg_val & DPLL_VCO_ENABLE)) {
-               reg_val &= ~DPLL_VCO_ENABLE;
-               REG_WRITE(dpll_reg, reg_val);
-               REG_READ(dpll_reg);
-               udelay(500);
-       }
-
-       gma_power_end(dev);
-       dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
-       if (pipe == 2) {
-               enter_dsr = 1;
-               /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
-       }
-}
-
-static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
-                       int pipe)
-{
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_crtc *crtc = dbi_output->base.base.crtc;
-       struct psb_intel_crtc *psb_crtc = (crtc) ?
-                                       to_psb_intel_crtc(crtc) : NULL;
-       u32 reg_val;
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 reg_offset = 0;
-
-       /*if mode setting on-going, back off*/
-       if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
-               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
-               return;
-
-       if (pipe == 2) {
-               dpll_reg = MRST_DPLL_A;
-               pipeconf_reg = PIPECCONF;
-               dspcntr_reg = DSPCCNTR;
-               reg_offset = MIPIC_REG_OFFSET;
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-       /* Enable DPLL */
-       reg_val = REG_READ(dpll_reg);
-       if (!(reg_val & DPLL_VCO_ENABLE)) {
-               if (reg_val & MDFLD_PWR_GATE_EN) {
-                       reg_val &= ~MDFLD_PWR_GATE_EN;
-                       REG_WRITE(dpll_reg, reg_val);
-                       REG_READ(dpll_reg);
-                       udelay(500);
-               }
-
-               reg_val |= DPLL_VCO_ENABLE;
-               REG_WRITE(dpll_reg, reg_val);
-               REG_READ(dpll_reg);
-               udelay(500);
-
-               /* Add timeout */
-               while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
-                       cpu_relax();
-       }
-
-       /* Enable pipe */
-       reg_val = REG_READ(pipeconf_reg);
-       if (!(reg_val & PIPEACONF_ENABLE)) {
-               reg_val |= PIPEACONF_ENABLE;
-               REG_WRITE(pipeconf_reg, reg_val);
-               REG_READ(pipeconf_reg);
-               udelay(500);
-               mdfldWaitForPipeEnable(dev, pipe);
-       }
-
-       /* Enable plane */
-       reg_val = REG_READ(dspcntr_reg);
-       if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
-               reg_val |= DISPLAY_PLANE_ENABLE;
-               REG_WRITE(dspcntr_reg, reg_val);
-               REG_READ(dspcntr_reg);
-               udelay(500);
-       }
-
-       /* Enable TE interrupt on this pipe */
-       mdfld_enable_te(dev, pipe);
-       gma_power_end(dev);
-
-       /*clean IN_DSR flag*/
-       dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
-}
-
-/*
- * Exit from DSR
- */
-void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
-       struct mdfld_dsi_dbi_output **dbi_output;
-       int i;
-       int pipe;
-
-       /* FIXME can go ? */
-       dev_priv->is_in_idle = false;
-       dbi_output = dsr_info->dbi_outputs;
-
-#ifdef CONFIG_PM_RUNTIME
-        if (!enable_gfx_rtpm) {
-/*                pm_runtime_allow(&gpDrmDevice->pdev->dev); */
-/*             schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */
-       }
-#endif
-
-       /* For each output, exit dsr */
-       for (i = 0; i < dsr_info->dbi_output_num; i++) {
-               /* If panel has been turned off, skip */
-               if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
-                       continue;
-               pipe = dbi_output[i]->channel_num ? 2 : 0;
-               enter_dsr = 0;
-               mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
-       }
-       dev_priv->dsr_fb_update |= update_src;
-}
-
-static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
-{
-       if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
-               return false;
-       if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
-          (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
-               return false;
-       if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
-          (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
-               return false;
-
-       return true;
-}
-
-/* Periodically update dbi panel */
-void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
-       struct mdfld_dsi_dbi_output **dbi_outputs;
-       struct mdfld_dsi_dbi_output *dbi_output;
-       int i;
-       int can_enter_dsr = 0;
-       u32 damage_mask;
-
-       dbi_outputs = dsr_info->dbi_outputs;
-       dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
-
-       if (!dbi_output)
-               return;
-
-       if (pipe == 0)
-               damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
-       else if (pipe == 2)
-               damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
-       else
-               return;
-
-       /* If FB is damaged and panel is on update on-panel FB */
-       if (damage_mask && dbi_output->dbi_panel_on) {
-               dbi_output->dsr_fb_update_done = false;
-
-               if (dbi_output->p_funcs->update_fb)
-                       dbi_output->p_funcs->update_fb(dbi_output, pipe);
-
-               if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done)
-                       dev_priv->dsr_fb_update &= ~damage_mask;
-
-               /*clean IN_DSR flag*/
-               dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
-
-               dbi_output->dsr_idle_count = 0;
-       } else {
-               dbi_output->dsr_idle_count++;
-       }
-
-       switch (dsr_info->dbi_output_num) {
-       case 1:
-               if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
-                       can_enter_dsr = 1;
-               break;
-       case 2:
-               if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
-                  && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
-                       can_enter_dsr = 1;
-               break;
-       default:
-               DRM_ERROR("Wrong DBI output number\n");
-       }
-
-       /* Try to enter DSR */
-       if (can_enter_dsr) {
-               for (i = 0; i < dsr_info->dbi_output_num; i++) {
-                       if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
-                          !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
-                               mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
-                                       dbi_outputs[i]->channel_num ? 2 : 0);
-#if 0
-                               enter_dsr = 1;
-                               pr_err("%s: enter_dsr = 1\n", __func__);
-#endif
-                       }
-               }
-       /*schedule rpm suspend after gfxrtdelay*/
-#ifdef CONFIG_GFX_RTPM
-               if (!dev_priv->rpm_enabled
-                       || !enter_dsr
-       /*              || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */
-                       || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
-                       dev_warn(dev->dev,
-                               "Runtime PM schedule suspend failed, rpm %d\n",
-                                       dev_priv->rpm_enabled);
-#endif
-       }
-}
-
-int mdfld_dbi_dsr_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
-
-       if (!dsr_info || IS_ERR(dsr_info)) {
-               dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info),
-                                                               GFP_KERNEL);
-               if (!dsr_info) {
-                       dev_err(dev->dev, "No memory\n");
-                       return -ENOMEM;
-               }
-               dev_priv->dbi_dsr_info = dsr_info;
-       }
-       return 0;
-}
-
-void mdfld_dbi_dsr_exit(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
-
-       if (dsr_info) {
-               kfree(dsr_info);
-               dev_priv->dbi_dsr_info = NULL;
-       }
-}
-
-void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
-                                                               int pipe)
-{
-       struct drm_device *dev = dsi_config->dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int lane_count = dsi_config->lane_count;
-       u32 val = 0;
-
-       dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
-
-       /* Un-ready device */
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
-       /* Init dsi adapter before kicking off */
-       REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
-       /* TODO: figure out how to setup these registers */
-       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-       REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
-                                                       0x000a0014);
-       REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
-       REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
-       REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
-
-       /* Enable all interrupts */
-       REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-       /* Max value: 20 clock cycles of txclkesc */
-       REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
-       /* Min 21 txclkesc, max: ffffh */
-       REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
-       /* Min: 7d0 max: 4e20 */
-       REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
-
-       /* Set up func_prg */
-       val |= lane_count;
-       val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
-       val |= DSI_DBI_COLOR_FORMAT_OPTION2;
-       REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
-       REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
-       REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
-
-       /* De-assert dbi_stall when half of DBI FIFO is empty */
-       /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
-
-       REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-       REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
-       REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-#if 0
-/*DBI encoder helper funcs*/
-static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
-       .dpms = mdfld_dsi_dbi_dpms,
-       .mode_fixup = mdfld_dsi_dbi_mode_fixup,
-       .prepare = mdfld_dsi_dbi_prepare,
-       .mode_set = mdfld_dsi_dbi_mode_set,
-       .commit = mdfld_dsi_dbi_commit,
-};
-
-/*DBI encoder funcs*/
-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-#endif
-
-/*
- * Init DSI DBI encoder.
- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
- * return pointer of newly allocated DBI encoder, NULL on error
- */
-struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
-                               struct mdfld_dsi_connector *dsi_connector,
-                               struct panel_funcs *p_funcs)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dsi_dbi_output *dbi_output = NULL;
-       struct mdfld_dsi_config *dsi_config;
-       struct drm_connector *connector = NULL;
-       struct drm_encoder *encoder = NULL;
-       struct drm_display_mode *fixed_mode = NULL;
-       struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
-       struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
-       u32 data = 0;
-       int pipe;
-       int ret;
-
-       if (!pg || !dsi_connector || !p_funcs) {
-               WARN_ON(1);
-               return NULL;
-       }
-
-       dsi_config = mdfld_dsi_get_config(dsi_connector);
-       pipe = dsi_connector->pipe;
-
-       /*panel hard-reset*/
-       if (p_funcs->reset) {
-               ret = p_funcs->reset(pipe);
-               if (ret) {
-                       DRM_ERROR("Panel %d hard-reset failed\n", pipe);
-                       return NULL;
-               }
-       }
-       /* Panel drvIC init */
-       if (p_funcs->drv_ic_init)
-               p_funcs->drv_ic_init(dsi_config, pipe);
-
-       /* Panel power mode detect */
-       ret = mdfld_dsi_get_power_mode(dsi_config,
-                                      &data,
-                                      MDFLD_DSI_HS_TRANSMISSION);
-       if (ret) {
-               DRM_ERROR("Panel %d get power mode failed\n", pipe);
-               dsi_connector->status = connector_status_disconnected;
-       } else {
-               DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
-               dsi_connector->status = connector_status_connected;
-       }
-
-       /*TODO: get panel info from DDB*/
-
-       dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
-       if (!dbi_output) {
-               dev_err(dev->dev, "No memory\n");
-               return NULL;
-       }
-
-       if (dsi_connector->pipe == 0) {
-               dbi_output->channel_num = 0;
-               dev_priv->dbi_output = dbi_output;
-       } else if (dsi_connector->pipe == 2) {
-               dbi_output->channel_num = 1;
-               dev_priv->dbi_output2 = dbi_output;
-       } else {
-               dev_err(dev->dev, "only support 2 DSI outputs\n");
-               goto out_err1;
-       }
-
-       dbi_output->dev = dev;
-       dbi_output->p_funcs = p_funcs;
-       fixed_mode = dsi_config->fixed_mode;
-       dbi_output->panel_fixed_mode = fixed_mode;
-
-       /* Create drm encoder object */
-       connector = &dsi_connector->base.base;
-       encoder = &dbi_output->base.base;
-       /* Review this if we ever get MIPI-HDMI bridges or similar */
-       drm_encoder_init(dev,
-                       encoder,
-                       p_funcs->encoder_funcs,
-                       DRM_MODE_ENCODER_LVDS);
-       drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
-
-       /* Attach to given connector */
-       drm_mode_connector_attach_encoder(connector, encoder);
-
-       /* Set possible CRTCs and clones */
-       if (dsi_connector->pipe) {
-               encoder->possible_crtcs = (1 << 2);
-               encoder->possible_clones = (1 << 1);
-       } else {
-               encoder->possible_crtcs = (1 << 0);
-               encoder->possible_clones = (1 << 0);
-       }
-
-       dev_priv->dsr_fb_update = 0;
-       dev_priv->dsr_enable = false;
-       dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
-
-       dbi_output->first_boot = true;
-       dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
-
-       /* Add this output to dpu_info if in DPU mode */
-       if (dpu_info && dsi_connector->status == connector_status_connected) {
-               if (dsi_connector->pipe == 0)
-                       dpu_info->dbi_outputs[0] = dbi_output;
-               else
-                       dpu_info->dbi_outputs[1] = dbi_output;
-
-               dpu_info->dbi_output_num++;
-       } else if (dsi_connector->status == connector_status_connected) {
-               /* Add this output to dsr_info if not */
-               if (dsi_connector->pipe == 0)
-                       dsr_info->dbi_outputs[0] = dbi_output;
-               else
-                       dsr_info->dbi_outputs[1] = dbi_output;
-
-               dsr_info->dbi_output_num++;
-       }
-       return &dbi_output->base;
-out_err1:
-       kfree(dbi_output);
-       return NULL;
-}
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h
deleted file mode 100644 (file)
index f0fa986..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DBI_H__
-#define __MDFLD_DSI_DBI_H__
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-/*
- * DBI encoder which inherits from mdfld_dsi_encoder
- */
-struct mdfld_dsi_dbi_output {
-       struct mdfld_dsi_encoder base;
-       struct drm_display_mode *panel_fixed_mode;
-       u8 last_cmd;
-       u8 lane_count;
-       u8 channel_num;
-       struct drm_device *dev;
-
-       /* Backlight operations */
-
-       /* DSR timer */
-       u32 dsr_idle_count;
-       bool dsr_fb_update_done;
-
-       /* Mode setting flags */
-       u32 mode_flags;
-
-       /* Panel status */
-       bool dbi_panel_on;
-       bool first_boot;
-       struct panel_funcs *p_funcs;
-
-       /* DPU */
-       u32 *dbi_cb_addr;
-       u32 dbi_cb_phy;
-       spinlock_t cb_lock;
-       u32 cb_write;
-};
-
-#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \
-       container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base)
-
-struct mdfld_dbi_dsr_info {
-       int dbi_output_num;
-       struct mdfld_dsi_dbi_output *dbi_outputs[2];
-
-       u32 dsr_idle_count;
-};
-
-#define DBI_CB_TIMEOUT_COUNT   0xffff
-
-/* Offsets */
-#define CMD_MEM_ADDR_OFFSET    0
-
-#define CMD_DATA_SRC_SYSTEM_MEM        0
-#define CMD_DATA_SRC_PIPE      1
-
-static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output)
-{
-       struct drm_device *dev = dbi_output->dev;
-       u32 retry = DBI_CB_TIMEOUT_COUNT;
-       int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
-       int ret = 0;
-
-       /* Query the dbi fifo status*/
-       while (retry--) {
-               if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27))
-                       break;
-       }
-
-       if (!retry) {
-               DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
-               ret = -EAGAIN;
-       }
-       return ret;
-}
-
-static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output)
-{
-       struct drm_device *dev = dbi_output->dev;
-       u32 retry = DBI_CB_TIMEOUT_COUNT;
-       int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
-       int ret = 0;
-
-       /* Query the command execution status */
-       while (retry--)
-               if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0)))
-                       break;
-
-       if (!retry) {
-               DRM_ERROR("Timeout waiting for DBI command status\n");
-               ret = -EAGAIN;
-       }
-
-       return ret;
-}
-
-static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output)
-{
-       int ret = 0;
-
-       /* Query the command execution status*/
-       ret = mdfld_dsi_dbi_cmd_sent(dbi_output);
-       if (ret) {
-               DRM_ERROR("Peripheral is busy\n");
-               ret = -EAGAIN;
-       }
-       /* Query the dbi fifo status*/
-       ret = mdfld_dsi_dbi_fifo_ready(dbi_output);
-       if (ret) {
-               DRM_ERROR("DBI FIFO is not empty\n");
-               ret = -EAGAIN;
-       }
-       return ret;
-}
-
-extern void mdfld_dsi_dbi_output_init(struct drm_device *dev,
-                       struct psb_intel_mode_device *mode_dev, int pipe);
-extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src);
-extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output,
-                       int pipe);
-extern int mdfld_dbi_dsr_init(struct drm_device *dev);
-extern void mdfld_dbi_dsr_exit(struct drm_device *dev);
-extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
-                       struct mdfld_dsi_connector *dsi_connector,
-                       struct panel_funcs *p_funcs);
-extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
-                       u8 dcs, u8 *param, u32 num, u8 data_src);
-extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
-                       u16 x1, u16 y1, u16 x2, u16 y2);
-extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
-                       int mode);
-extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
-                       int pipe);
-
-#endif /*__MDFLD_DSI_DBI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
deleted file mode 100644 (file)
index a4e2ff4..0000000
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- * Copyright Â© 2010-2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jim Liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_dbi.h"
-
-/*
- * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
- */
-
-static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info,
-                          mdfld_plane_t plane,
-                          struct psb_drm_dpu_rect *damaged_rect)
-{
-       int x, y;
-       int new_x, new_y;
-       struct psb_drm_dpu_rect *rect;
-       struct psb_drm_dpu_rect *pipe_rect;
-       int cursor_size;
-       struct mdfld_cursor_info *cursor;
-       mdfld_plane_t fb_plane;
-
-       if (plane == MDFLD_CURSORA) {
-               cursor = &dpu_info->cursors[0];
-               x = dpu_info->cursors[0].x;
-               y = dpu_info->cursors[0].y;
-               cursor_size = dpu_info->cursors[0].size;
-               pipe_rect = &dpu_info->damage_pipea;
-               fb_plane = MDFLD_PLANEA;
-       } else {
-               cursor = &dpu_info->cursors[1];
-               x = dpu_info->cursors[1].x;
-               y = dpu_info->cursors[1].y;
-               cursor_size = dpu_info->cursors[1].size;
-               pipe_rect = &dpu_info->damage_pipec;
-               fb_plane = MDFLD_PLANEC;
-       }
-       new_x = damaged_rect->x;
-       new_y = damaged_rect->y;
-
-       if (x == new_x && y == new_y)
-               return 0;
-
-       rect = &dpu_info->damaged_rects[plane];
-       /* Move to right */
-       if (new_x >= x) {
-               if (new_y > y) {
-                       rect->x = x;
-                       rect->y = y;
-                       rect->width = (new_x + cursor_size) - x;
-                       rect->height = (new_y + cursor_size) - y;
-                       goto cursor_out;
-               } else {
-                       rect->x = x;
-                       rect->y = new_y;
-                       rect->width = (new_x + cursor_size) - x;
-                       rect->height = (y - new_y);
-                       goto cursor_out;
-               }
-       } else {
-               if (new_y > y) {
-                       rect->x = new_x;
-                       rect->y = y;
-                       rect->width = (x + cursor_size) - new_x;
-                       rect->height = new_y - y;
-                       goto cursor_out;
-               } else {
-                       rect->x = new_x;
-                       rect->y = new_y;
-                       rect->width = (x + cursor_size) - new_x;
-                       rect->height = (y + cursor_size) - new_y;
-               }
-       }
-cursor_out:
-       if (new_x < 0)
-               cursor->x = 0;
-       else if (new_x > 864)
-               cursor->x = 864;
-       else
-               cursor->x = new_x;
-
-       if (new_y < 0)
-               cursor->y = 0;
-       else if (new_y > 480)
-               cursor->y = 480;
-       else
-               cursor->y = new_y;
-
-       /*
-        * FIXME: this is a workaround for cursor plane update,
-        * remove it later!
-        */
-       rect->x = 0;
-       rect->y = 0;
-       rect->width = 864;
-       rect->height = 480;
-
-       mdfld_check_boundary(dpu_info, rect);
-       mdfld_dpu_region_extent(pipe_rect, rect);
-
-       /* Update pending status of dpu_info */
-       dpu_info->pending |= (1 << plane);
-       /* Update fb panel as well */
-       dpu_info->pending |= (1 << fb_plane);
-       return 0;
-}
-
-static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info,
-                                  mdfld_plane_t plane,
-                                  struct psb_drm_dpu_rect *damaged_rect)
-{
-       struct psb_drm_dpu_rect *rect;
-
-       if (plane == MDFLD_PLANEA)
-               rect = &dpu_info->damage_pipea;
-       else
-               rect = &dpu_info->damage_pipec;
-
-       mdfld_check_boundary(dpu_info, damaged_rect);
-
-       /* Add fb damage area to this pipe */
-       mdfld_dpu_region_extent(rect, damaged_rect);
-
-       /* Update pending status of dpu_info */
-       dpu_info->pending |= (1 << plane);
-       return 0;
-}
-
-/* Do nothing here, right now */
-static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info,
-                               mdfld_plane_t plane,
-                               struct psb_drm_dpu_rect *damaged_rect)
-{
-       return 0;
-}
-
-int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
-                               mdfld_plane_t plane,
-                               struct psb_drm_dpu_rect *rect)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-       int ret = 0;
-
-       /* DPU not in use, no damage reporting needed */
-       if (dpu_info == NULL)
-               return 0;
-
-       spin_lock(&dpu_info->dpu_update_lock);
-
-       switch (plane) {
-       case MDFLD_PLANEA:
-       case MDFLD_PLANEC:
-               mdfld_fb_damage(dpu_info, plane, rect);
-               break;
-       case MDFLD_CURSORA:
-       case MDFLD_CURSORC:
-               mdfld_cursor_damage(dpu_info, plane, rect);
-               break;
-       case MDFLD_OVERLAYA:
-       case MDFLD_OVERLAYC:
-               mdfld_overlay_damage(dpu_info, plane, rect);
-               break;
-       default:
-               DRM_ERROR("Invalid plane type %d\n", plane);
-               ret = -EINVAL;
-       }
-       spin_unlock(&dpu_info->dpu_update_lock);
-       return ret;
-}
-
-int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv;
-       struct mdfld_dbi_dpu_info *dpu_info;
-       struct mdfld_dsi_config  *dsi_config;
-       struct psb_drm_dpu_rect rect;
-       int i;
-
-       if (!dev) {
-               DRM_ERROR("Invalid parameter\n");
-               return -EINVAL;
-       }
-
-       dev_priv = dev->dev_private;
-       dpu_info = dev_priv->dbi_dpu_info;
-
-       /* This is fine - we may be in non DPU mode */
-       if (!dpu_info)
-               return -EINVAL;
-
-       for (i = 0; i < dpu_info->dbi_output_num; i++) {
-               dsi_config = dev_priv->dsi_configs[i];
-               if (dsi_config) {
-                       rect.x = rect.y = 0;
-                       rect.width = dsi_config->fixed_mode->hdisplay;
-                       rect.height = dsi_config->fixed_mode->vdisplay;
-                       mdfld_dbi_dpu_report_damage(dev,
-                                   i ? (MDFLD_PLANEC) : (MDFLD_PLANEA),
-                                   &rect);
-               }
-       }
-       /* Exit DSR state */
-       mdfld_dpu_exit_dsr(dev);
-       return 0;
-}
-
-int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
-                                       struct psb_drm_dpu_rect *rect)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
-       mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect);
-
-       /* If dual display mode */
-       if (dpu_info->dbi_output_num == 2)
-               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect);
-
-       /* Force dsi to exit DSR mode */
-       mdfld_dpu_exit_dsr(dev);
-       return 0;
-}
-
-static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
-                                                mdfld_plane_t plane)
-{
-       struct drm_device *dev = dpu_info->dev;
-       u32 curpos_reg = CURAPOS;
-       u32 curbase_reg = CURABASE;
-       u32 curcntr_reg = CURACNTR;
-       struct mdfld_cursor_info *cursor = &dpu_info->cursors[0];
-
-       if (plane == MDFLD_CURSORC) {
-               curpos_reg = CURCPOS;
-               curbase_reg = CURCBASE;
-               curcntr_reg = CURCCNTR;
-               cursor = &dpu_info->cursors[1];
-       }
-
-       REG_WRITE(curcntr_reg, REG_READ(curcntr_reg));
-       REG_WRITE(curpos_reg,
-               (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
-               ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT)));
-       REG_WRITE(curbase_reg, REG_READ(curbase_reg));
-}
-
-static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
-                                                mdfld_plane_t plane)
-{
-       u32 pipesrc_reg = PIPEASRC;
-       u32 dspsize_reg = DSPASIZE;
-       u32 dspoff_reg = DSPALINOFF;
-       u32 dspsurf_reg = DSPASURF;
-       u32 dspstride_reg = DSPASTRIDE;
-       u32 stride;
-       struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea;
-       struct drm_device *dev = dpu_info->dev;
-
-       if (plane == MDFLD_PLANEC) {
-               pipesrc_reg = PIPECSRC;
-               dspsize_reg = DSPCSIZE;
-               dspoff_reg = DSPCLINOFF;
-               dspsurf_reg = DSPCSURF;
-               dspstride_reg = DSPCSTRIDE;
-               rect = &dpu_info->damage_pipec;
-       }
-
-       stride = REG_READ(dspstride_reg);
-       /* FIXME: should I do the pipe src update here? */
-       REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1));
-       /* Flush plane */
-       REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1));
-       REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride)));
-       REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
-
-       /*
-        * TODO: wait for flip finished and restore the pipesrc reg,
-        * or cursor will be show at a wrong position
-        */
-}
-
-static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
-                                                 mdfld_plane_t plane)
-{
-}
-
-/*
- * TODO: we are still in dbi normal mode now, we will try to use partial
- * mode later.
- */
-static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output,
-                               struct mdfld_dbi_dpu_info *dpu_info, int pipe)
-{
-       u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr;
-       u32 *index;
-       struct psb_drm_dpu_rect *rect = pipe ?
-               (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea);
-
-       /* FIXME: lock command buffer, this may lead to a deadlock,
-          as we already hold the dpu_update_lock */
-       if (!spin_trylock(&dbi_output->cb_lock)) {
-               DRM_ERROR("lock command buffer failed, try again\n");
-               return -EAGAIN;
-       }
-
-       index = &dbi_output->cb_write;
-
-       if (*index) {
-               DRM_ERROR("DBI command buffer unclean\n");
-               return -EAGAIN;
-       }
-
-       /* Column address */
-       *(cb_addr + ((*index)++)) = set_column_address;
-       *(cb_addr + ((*index)++)) = rect->x >> 8;
-       *(cb_addr + ((*index)++)) = rect->x;
-       *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8;
-       *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1);
-
-       *index = 8;
-
-       /* Page address */
-       *(cb_addr + ((*index)++)) = set_page_addr;
-       *(cb_addr + ((*index)++)) = rect->y >> 8;
-       *(cb_addr + ((*index)++)) = rect->y;
-       *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8;
-       *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1);
-
-       *index = 16;
-
-       /*write memory*/
-       *(cb_addr + ((*index)++)) = write_mem_start;
-
-       return 0;
-}
-
-static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
-{
-       u32 cmd_phy = dbi_output->dbi_cb_phy;
-       u32 *index = &dbi_output->cb_write;
-       int reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       struct drm_device *dev = dbi_output->dev;
-
-       if (*index == 0 || !dbi_output)
-               return 0;
-
-       REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505);
-       REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3);
-
-       *index = 0;
-
-       /* FIXME: unlock command buffer */
-       spin_unlock(&dbi_output->cb_lock);
-       return 0;
-}
-
-static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output,
-                                struct mdfld_dbi_dpu_info *dpu_info, int pipe)
-{
-       struct drm_device *dev =  dbi_output->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       mdfld_plane_t cursor_plane = MDFLD_CURSORA;
-       mdfld_plane_t fb_plane = MDFLD_PLANEA;
-       mdfld_plane_t overlay_plane = MDFLD_OVERLAYA;
-       int ret = 0;
-       u32 plane_mask = MDFLD_PIPEA_PLANE_MASK;
-
-       /* Damaged rects on this pipe */
-       if (pipe) {
-               cursor_plane = MDFLD_CURSORC;
-               fb_plane = MDFLD_PLANEC;
-               overlay_plane = MDFLD_OVERLAYC;
-               plane_mask = MDFLD_PIPEC_PLANE_MASK;
-       }
-
-       /*update cursor which assigned to @pipe*/
-       if (dpu_info->pending & (1 << cursor_plane))
-               mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane);
-
-       /*update fb which assigned to @pipe*/
-       if (dpu_info->pending & (1 << fb_plane))
-               mdfld_dpu_fb_plane_flush(dpu_info, fb_plane);
-
-       /* TODO: update overlay */
-       if (dpu_info->pending & (1 << overlay_plane))
-               mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane);
-
-       /* Flush damage area to panel fb */
-       if (dpu_info->pending & plane_mask) {
-               ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe);
-               /*
-                * TODO: remove b_dsr_enable later,
-                * added it so that text console could boot smoothly
-                */
-               /* Clean pending flags on this pipe */
-               if (!ret && dev_priv->dsr_enable) {
-                       dpu_info->pending &= ~plane_mask;
-                       /* Reset overlay pipe damage rect */
-                       mdfld_dpu_init_damage(dpu_info, pipe);
-               }
-       }
-       return ret;
-}
-
-static int mdfld_dpu_update_fb(struct drm_device *dev)
-{
-       struct drm_crtc *crtc;
-       struct psb_intel_crtc *psb_crtc;
-       struct mdfld_dsi_dbi_output **dbi_output;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-       bool pipe_updated[2];
-       unsigned long irq_flags;
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dspsurf_reg = DSPASURF;
-       u32 mipi_state_reg = MIPIA_INTR_STAT_REG;
-       u32 reg_offset = 0;
-       int pipe;
-       int i;
-       int ret;
-
-       dbi_output = dpu_info->dbi_outputs;
-       pipe_updated[0] = pipe_updated[1] = false;
-
-       if (!gma_power_begin(dev, true))
-               return -EAGAIN;
-
-       /* Try to prevent any new damage reports */
-       if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags))
-               return -EAGAIN;
-
-       for (i = 0; i < dpu_info->dbi_output_num; i++) {
-               crtc = dbi_output[i]->base.base.crtc;
-               psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
-
-               pipe = dbi_output[i]->channel_num ? 2 : 0;
-
-               if (pipe == 2) {
-                       dspcntr_reg = DSPCCNTR;
-                       pipeconf_reg = PIPECCONF;
-                       dsplinoff_reg = DSPCLINOFF;
-                       dspsurf_reg = DSPCSURF;
-                       reg_offset = MIPIC_REG_OFFSET;
-               }
-
-               if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset))
-                                                       & (1 << 27)) ||
-                       !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
-                       !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
-                       !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
-                       dev_err(dev->dev,
-                               "DBI FIFO is busy, DSI %d state %x\n",
-                               pipe,
-                               REG_READ(mipi_state_reg + reg_offset));
-                       continue;
-               }
-
-               /*
-                *      If DBI output is in a exclusive state then the pipe
-                *      change won't be updated
-                */
-               if (dbi_output[i]->dbi_panel_on &&
-                  !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
-                  !(psb_crtc &&
-                       psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
-                  !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
-                       ret = mdfld_dpu_update_pipe(dbi_output[i],
-                               dpu_info, dbi_output[i]->channel_num ? 2 : 0);
-                       if (!ret)
-                               pipe_updated[i] = true;
-               }
-       }
-
-       for (i = 0; i < dpu_info->dbi_output_num; i++)
-               if (pipe_updated[i])
-                       mdfld_dbi_flush_cb(dbi_output[i],
-                               dbi_output[i]->channel_num ? 2 : 0);
-
-       spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
-       gma_power_end(dev);
-       return 0;
-}
-
-static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
-                                                               int pipe)
-{
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_crtc *crtc = dbi_output->base.base.crtc;
-       struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc)
-                                                               : NULL;
-       u32 reg_val;
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 dspbase_reg = DSPABASE;
-       u32 dspsurf_reg = DSPASURF;
-       u32 reg_offset = 0;
-
-       if (!dbi_output)
-               return 0;
-
-       /* If mode setting on-going, back off */
-       if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
-               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
-               return -EAGAIN;
-
-       if (pipe == 2) {
-               dpll_reg = MRST_DPLL_A;
-               pipeconf_reg = PIPECCONF;
-               dspcntr_reg = DSPCCNTR;
-               dspbase_reg = MDFLD_DSPCBASE;
-               dspsurf_reg = DSPCSURF;
-
-               reg_offset = MIPIC_REG_OFFSET;
-       }
-
-       if (!gma_power_begin(dev, true))
-               return -EAGAIN;
-
-       /* Enable DPLL */
-       reg_val = REG_READ(dpll_reg);
-       if (!(reg_val & DPLL_VCO_ENABLE)) {
-
-               if (reg_val & MDFLD_PWR_GATE_EN) {
-                       reg_val &= ~MDFLD_PWR_GATE_EN;
-                       REG_WRITE(dpll_reg, reg_val);
-                       REG_READ(dpll_reg);
-                       udelay(500);
-               }
-
-               reg_val |= DPLL_VCO_ENABLE;
-               REG_WRITE(dpll_reg, reg_val);
-               REG_READ(dpll_reg);
-               udelay(500);
-
-               /* FIXME: add timeout */
-               while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
-                       cpu_relax();
-       }
-
-       /* Enable pipe */
-       reg_val = REG_READ(pipeconf_reg);
-       if (!(reg_val & PIPEACONF_ENABLE)) {
-               reg_val |= PIPEACONF_ENABLE;
-               REG_WRITE(pipeconf_reg, reg_val);
-               REG_READ(pipeconf_reg);
-               udelay(500);
-               mdfldWaitForPipeEnable(dev, pipe);
-       }
-
-       /* Enable plane */
-       reg_val = REG_READ(dspcntr_reg);
-       if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
-               reg_val |= DISPLAY_PLANE_ENABLE;
-               REG_WRITE(dspcntr_reg, reg_val);
-               REG_READ(dspcntr_reg);
-               udelay(500);
-       }
-
-       gma_power_end(dev);
-
-       /* Clean IN_DSR flag */
-       dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
-
-       return 0;
-}
-
-int mdfld_dpu_exit_dsr(struct drm_device *dev)
-{
-       struct mdfld_dsi_dbi_output **dbi_output;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-       int i;
-       int pipe;
-
-       dbi_output = dpu_info->dbi_outputs;
-
-       for (i = 0; i < dpu_info->dbi_output_num; i++) {
-               /* If this output is not in DSR mode, don't call exit dsr */
-               if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)
-                       __mdfld_dbi_exit_dsr(dbi_output[i],
-                                       dbi_output[i]->channel_num ? 2 : 0);
-       }
-
-       /* Enable TE interrupt */
-       for (i = 0; i < dpu_info->dbi_output_num; i++) {
-               /* If this output is not in DSR mode, don't call exit dsr */
-               pipe = dbi_output[i]->channel_num ? 2 : 0;
-               if (dbi_output[i]->dbi_panel_on && pipe) {
-                       mdfld_disable_te(dev, 0);
-                       mdfld_enable_te(dev, 2);
-               } else if (dbi_output[i]->dbi_panel_on && !pipe) {
-                       mdfld_disable_te(dev, 2);
-                       mdfld_enable_te(dev, 0);
-               }
-       }
-       return 0;
-}
-
-static int mdfld_dpu_enter_dsr(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-       struct mdfld_dsi_dbi_output **dbi_output;
-       int i;
-
-       dbi_output = dpu_info->dbi_outputs;
-
-       for (i = 0; i < dpu_info->dbi_output_num; i++) {
-               /* If output is off or already in DSR state, don't re-enter */
-               if (dbi_output[i]->dbi_panel_on &&
-                  !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
-                       mdfld_dsi_dbi_enter_dsr(dbi_output[i],
-                               dbi_output[i]->channel_num ? 2 : 0);
-               }
-       }
-
-       return 0;
-}
-
-static void mdfld_dbi_dpu_timer_func(unsigned long data)
-{
-       struct drm_device *dev = (struct drm_device *)data;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-       struct timer_list *dpu_timer = &dpu_info->dpu_timer;
-       unsigned long flags;
-
-       if (dpu_info->pending) {
-               dpu_info->idle_count = 0;
-               /* Update panel fb with damaged area */
-               mdfld_dpu_update_fb(dev);
-       } else {
-               dpu_info->idle_count++;
-       }
-
-       if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
-               mdfld_dpu_enter_dsr(dev);
-               /* Stop timer by return */
-               return;
-       }
-
-       spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
-       if (!timer_pending(dpu_timer)) {
-               dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
-               add_timer(dpu_timer);
-       }
-       spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
-}
-
-void mdfld_dpu_update_panel(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
-       if (dpu_info->pending) {
-               dpu_info->idle_count = 0;
-
-               /*update panel fb with damaged area*/
-               mdfld_dpu_update_fb(dev);
-       } else {
-               dpu_info->idle_count++;
-       }
-
-       if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
-               /*enter dsr*/
-               mdfld_dpu_enter_dsr(dev);
-       }
-}
-
-static int mdfld_dbi_dpu_timer_init(struct drm_device *dev,
-                               struct mdfld_dbi_dpu_info *dpu_info)
-{
-       struct timer_list *dpu_timer = &dpu_info->dpu_timer;
-       unsigned long flags;
-
-       spin_lock_init(&dpu_info->dpu_timer_lock);
-       spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
-
-       init_timer(dpu_timer);
-
-       dpu_timer->data = (unsigned long)dev;
-       dpu_timer->function = mdfld_dbi_dpu_timer_func;
-       dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
-
-       spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
-
-       return 0;
-}
-
-void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info)
-{
-       struct timer_list *dpu_timer = &dpu_info->dpu_timer;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
-       if (!timer_pending(dpu_timer)) {
-               dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
-               add_timer(dpu_timer);
-       }
-       spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
-}
-
-int mdfld_dbi_dpu_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
-       if (!dpu_info || IS_ERR(dpu_info)) {
-               dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info),
-                                                               GFP_KERNEL);
-               if (!dpu_info) {
-                       DRM_ERROR("No memory\n");
-                       return -ENOMEM;
-               }
-               dev_priv->dbi_dpu_info = dpu_info;
-       }
-
-       dpu_info->dev = dev;
-
-       dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE;
-       dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE;
-
-       /*init dpu_update_lock*/
-       spin_lock_init(&dpu_info->dpu_update_lock);
-
-       /*init dpu refresh timer*/
-       mdfld_dbi_dpu_timer_init(dev, dpu_info);
-
-       /*init pipe damage area*/
-       mdfld_dpu_init_damage(dpu_info, 0);
-       mdfld_dpu_init_damage(dpu_info, 2);
-
-       return 0;
-}
-
-void mdfld_dbi_dpu_exit(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
-       if (!dpu_info)
-               return;
-
-       del_timer_sync(&dpu_info->dpu_timer);
-       kfree(dpu_info);
-       dev_priv->dbi_dpu_info = NULL;
-}
-
-
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
deleted file mode 100644 (file)
index 42367ed..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DBI_DPU_H__
-#define __MDFLD_DSI_DBI_DPU_H__
-
-#include "mdfld_dsi_dbi.h"
-
-typedef enum {
-       MDFLD_PLANEA,
-       MDFLD_PLANEC,
-       MDFLD_CURSORA,
-       MDFLD_CURSORC,
-       MDFLD_OVERLAYA,
-       MDFLD_OVERLAYC,
-       MDFLD_PLANE_NUM,
-} mdfld_plane_t;
-
-#define MDFLD_PIPEA_PLANE_MASK 0x15
-#define MDFLD_PIPEC_PLANE_MASK 0x2A
-
-struct mdfld_cursor_info {
-       int x, y;
-       int size;
-};
-
-#define MDFLD_CURSOR_SIZE      64
-
-/*
- * enter DSR mode if screen has no update for 2 frames.
- */
-#define MDFLD_MAX_IDLE_COUNT   2
-
-struct mdfld_dbi_dpu_info {
-       struct drm_device *dev;
-       /* Lock */
-       spinlock_t dpu_update_lock;
-
-       /* Cursor postion */
-       struct mdfld_cursor_info cursors[2];
-
-       /* Damaged area for each plane */
-       struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM];
-
-       /* Final damaged area */
-       struct psb_drm_dpu_rect damage_pipea;
-       struct psb_drm_dpu_rect damage_pipec;
-
-       /* Pending */
-       u32 pending;
-
-       /* DPU timer */
-       struct timer_list dpu_timer;
-       spinlock_t dpu_timer_lock;
-
-       /* DPU idle count */
-       u32 idle_count;
-
-       /* DSI outputs */
-       struct mdfld_dsi_dbi_output *dbi_outputs[2];
-       int dbi_output_num;
-};
-
-static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin,
-                        struct psb_drm_dpu_rect *rect)
-{
-       int x1, y1, x2, y2;
-
-       x1 = origin->x + origin->width;
-       y1 = origin->y + origin->height;
-
-       x2 = rect->x + rect->width;
-       y2 = rect->y + rect->height;
-
-       origin->x = min(origin->x, rect->x);
-       origin->y = min(origin->y, rect->y);
-       origin->width = max(x1, x2) - origin->x;
-       origin->height = max(y1, y2) - origin->y;
-
-       return 0;
-}
-
-static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info,
-                               struct psb_drm_dpu_rect *rect)
-{
-       if (rect->x < 0)
-               rect->x = 0;
-       if (rect->y < 0)
-               rect->y = 0;
-
-       if (rect->x + rect->width > 864)
-               rect->width = 864 - rect->x;
-       if (rect->y + rect->height > 480)
-               rect->height = 480 - rect->height;
-
-       if (!rect->width)
-               rect->width = 1;
-       if (!rect->height)
-               rect->height = 1;
-}
-
-static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info,
-                               int pipe)
-{
-       struct psb_drm_dpu_rect *rect;
-
-       if (pipe == 0)
-               rect = &dpu_info->damage_pipea;
-       else
-               rect = &dpu_info->damage_pipec;
-
-       rect->x = 864;
-       rect->y = 480;
-       rect->width = -864;
-       rect->height = -480;
-}
-
-extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
-                               struct psb_drm_dpu_rect *rect);
-extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
-                               mdfld_plane_t plane,
-                               struct psb_drm_dpu_rect *rect);
-extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev);
-extern int mdfld_dpu_exit_dsr(struct drm_device *dev);
-extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info);
-extern int mdfld_dbi_dpu_init(struct drm_device *dev);
-extern void mdfld_dbi_dpu_exit(struct drm_device *dev);
-extern void mdfld_dpu_update_panel(struct drm_device *dev);
-
-#endif /*__MDFLD_DSI_DBI_DPU_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c
deleted file mode 100644 (file)
index e685f12..0000000
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-
-static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
-{
-       u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
-       int timeout = 0;
-
-       if (pipe == 2)
-               gen_fifo_stat_reg += MIPIC_REG_OFFSET;
-
-       udelay(500);
-
-       /* This will time out after approximately 2+ seconds */
-       while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
-               udelay(100);
-               timeout++;
-       }
-
-       if (timeout == 20000)
-               dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
-{
-       u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
-       int timeout = 0;
-
-       if (pipe == 2)
-               gen_fifo_stat_reg += MIPIC_REG_OFFSET;
-
-       udelay(500);
-
-       /* This will time out after approximately 2+ seconds */
-       while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) {
-               udelay(100);
-               timeout++;
-       }
-       if (timeout == 20000)
-               dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
-{
-       u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
-        int timeout = 0;
-
-       if (pipe == 2)
-               gen_fifo_stat_reg += MIPIC_REG_OFFSET;
-
-        udelay(500);
-
-        /* This will time out after approximately 2+ seconds */
-        while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
-                                                        != DPI_FIFO_EMPTY)) {
-                udelay(100);
-                timeout++;
-        }
-
-        if (timeout == 20000)
-                dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
-{
-       u32 intr_stat_reg = MIPIA_INTR_STAT_REG;
-       int timeout = 0;
-
-       if (pipe == 2)
-               intr_stat_reg += MIPIC_REG_OFFSET;
-
-        udelay(500);
-
-        /* This will time out after approximately 2+ seconds */
-        while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) {
-                udelay(100);
-                timeout++;
-        }
-
-        if (timeout == 20000)
-                dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
-}
-
-
-/* ************************************************************************* *\
- * FUNCTION: mdfld_dsi_tpo_ic_init
- *
- * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
- *               restore_display_registers.  since this function does not
- *               acquire the mutex, it is important that the calling function
- *               does!
-\* ************************************************************************* */
-void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
-{
-       struct drm_device *dev = dsi_config->dev;
-       u32 dcsChannelNumber = dsi_config->channel_num;
-       u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG; 
-       u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
-       u32 gen_ctrl_val = GEN_LONG_WRITE;
-
-       if (pipe == 2) {
-               gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET; 
-               gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
-       }
-
-       gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
-
-       /* Flip page order */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00008036);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
-
-       /* 0xF0 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x005a5af0);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
-       /* Write protection key */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x005a5af1);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
-       /* 0xFC */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x005a5afc);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
-       /* 0xB7 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x770000b7);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00000044);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
-
-       /* 0xB6 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x000a0ab6);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
-       /* 0xF2 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x081010f2);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x4a070708);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x000000c5);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
-       /* 0xF8 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x024003f8);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x01030a04);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x0e020220);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00000004);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
-
-       /* 0xE2 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x398fc3e2);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x0000916f);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
-
-       /* 0xB0 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x000000b0);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
-
-       /* 0xF4 */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x240242f4);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x78ee2002);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x2a071050);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x507fee10);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x10300710);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
-
-       /* 0xBA */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x19fe07ba);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x101c0a31);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00000010);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
-       /* 0xBB */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x28ff07bb);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x24280a31);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00000034);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
-       /* 0xFB */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x535d05fb);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x1b1a2130);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x221e180e);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x131d2120);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x535d0508);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x1c1a2131);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x231f160d);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x111b2220);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x535c2008);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x1f1d2433);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x2c251a10);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x2c34372d);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00000023);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
-
-       /* 0xFA */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x525c0bfa);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x1c1c232f);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x2623190e);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x18212625);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x545d0d0e);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x1e1d2333);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x26231a10);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x1a222725);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x545d280f);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x21202635);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x31292013);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x31393d33);
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x00000029);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
-
-       /* Set DM */
-       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
-       REG_WRITE(gen_data_reg, 0x000100f7);
-       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
-       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-}
-
-static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,
-                                               int num_lane, int bpp)
-{
-       return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); 
-}
-
-/*
- * Calculate the dpi time basing on a given drm mode @mode
- * return 0 on success.
- * FIXME: I was using proposed mode value for calculation, may need to 
- * use crtc mode values later 
- */
-int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, 
-                       struct mdfld_dsi_dpi_timing *dpi_timing,
-                       int num_lane, int bpp)
-{
-       int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
-       int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
-       
-       if(!mode || !dpi_timing) {
-               DRM_ERROR("Invalid parameter\n");
-               return -EINVAL;
-       }
-       
-       pclk_hactive = mode->hdisplay;
-       pclk_hfp = mode->hsync_start - mode->hdisplay;
-       pclk_hsync = mode->hsync_end - mode->hsync_start;
-       pclk_hbp = mode->htotal - mode->hsync_end;
-       
-       pclk_vactive = mode->vdisplay;
-       pclk_vfp = mode->vsync_start - mode->vdisplay;
-       pclk_vsync = mode->vsync_end - mode->vsync_start;
-       pclk_vbp = mode->vtotal - mode->vsync_end;
-
-       /*
-        * byte clock counts were calculated by following formula
-        * bclock_count = pclk_count * bpp / num_lane / 8
-        */
-       dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp);
-       dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
-       dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
-       dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
-       dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
-       dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
-       dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
-
-       return 0; 
-}
-
-void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
-       struct drm_device *dev = dsi_config->dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int lane_count = dsi_config->lane_count;
-       struct mdfld_dsi_dpi_timing dpi_timing;
-       struct drm_display_mode *mode = dsi_config->mode;
-       u32 val = 0;
-       
-       /*un-ready device*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-       
-       /*init dsi adapter before kicking off*/
-       REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-       
-       /*enable all interrupts*/
-       REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-       
-
-       /*set up func_prg*/
-       val |= lane_count;
-       val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
-               
-       switch(dsi_config->bpp) {
-       case 16:
-               val |= DSI_DPI_COLOR_FORMAT_RGB565;
-               break;
-       case 18:
-               val |= DSI_DPI_COLOR_FORMAT_RGB666;
-               break;
-       case 24:
-               val |= DSI_DPI_COLOR_FORMAT_RGB888;
-               break;
-       default:
-               DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
-       }
-       REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-       
-       REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 
-                       (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
-       REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
-       
-       /*max value: 20 clock cycles of txclkesc*/
-       REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
-       
-       /*min 21 txclkesc, max: ffffh*/
-       REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
-
-       REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
-       
-       /*set DPI timing registers*/
-       mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
-       
-       REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
-       
-       REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-       
-       /*min: 7d0 max: 4e20*/
-       REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
-       
-       /*set up video mode*/
-       val = 0;
-       val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
-       REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
-       
-       REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
-       
-       REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-       
-       /*TODO: figure out how to setup these registers*/
-       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-       
-       REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
-       /*set device ready*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
-{
-       struct drm_device *dev = output->dev;
-       u32 reg_offset = 0;
-       
-       if(output->panel_on) 
-               return;
-               
-       if(pipe) 
-               reg_offset = MIPIC_REG_OFFSET;
-
-       /* clear special packet sent bit */
-       if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
-               REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
-       }
-               
-       /*send turn on package*/
-       REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
-       
-       /*wait for SPL_PKG_SENT interrupt*/
-       mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
-       
-       if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
-               REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
-       }
-
-       output->panel_on = 1;
-
-       /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
-       /* if(pipe == 2) */
-       /*      dev_priv->dpi_panel_on2 = true; */
-       /* else if (pipe == 0) */
-       /*      dev_priv->dpi_panel_on = true; */
-}
-
-static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe)
-{
-       struct drm_device *dev = output->dev;
-       u32 reg_offset = 0;
-       
-       /*if output is on, or mode setting didn't happen, ignore this*/
-       if((!output->panel_on) || output->first_boot) {
-               output->first_boot = 0; 
-               return;
-       }
-       
-       if(pipe)
-               reg_offset = MIPIC_REG_OFFSET;
-
-       /* Wait for dpi fifo to empty */
-       mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
-
-       /* Clear the special packet interrupt bit if set */
-       if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
-               REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
-       }
-       
-       if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) {
-               dev_warn(dev->dev, "try to send the same package again, abort!");
-               goto shutdown_out;
-       }
-       
-       REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
-
-shutdown_out:
-       output->panel_on = 0;
-       output->first_boot = 0;
-
-       /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
-       /* if(pipe == 2) */
-       /*      dev_priv->dpi_panel_on2 = false; */
-       /* else if (pipe == 0) */
-       /*      dev_priv->dpi_panel_on = false;  */
-       /* #ifdef CONFIG_PM_RUNTIME*/ 
-       /*      if (drm_psb_ospm && !enable_gfx_rtpm) { */
-       /*              pm_runtime_allow(&gpDrmDevice->pdev->dev); */
-       /*      schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */
-       /* } */
-       /*if (enable_gfx_rtpm) */
-       /*              pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
-       /* #endif */
-}
-
-void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
-       struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
-       int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
-       struct drm_device *dev = dsi_config->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 mipi_reg = MIPI;
-       u32 pipeconf_reg = PIPEACONF;
-       
-       if(pipe) {
-               mipi_reg = MIPI_C;
-               pipeconf_reg = PIPECCONF;
-       }
-       
-       /* Start up display island if it was shutdown */
-       if (!gma_power_begin(dev, true))
-               return;
-
-       if(on) {
-               if (mdfld_get_panel_type(dev, pipe) == TMD_VID){
-                       mdfld_dsi_dpi_turn_on(dpi_output, pipe);
-               } else {
-                       /* Enable mipi port */
-                       REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31)));
-                       REG_READ(mipi_reg);
-
-                       mdfld_dsi_dpi_turn_on(dpi_output, pipe);
-                       mdfld_dsi_tpo_ic_init(dsi_config, pipe);
-               }
-
-               if(pipe == 2) {
-                       dev_priv->dpi_panel_on2 = true;
-               }
-               else {
-                       dev_priv->dpi_panel_on  = true;
-               }
-
-       } else {
-               if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
-                       mdfld_dsi_dpi_shut_down(dpi_output, pipe);
-               } else {
-                       mdfld_dsi_dpi_shut_down(dpi_output, pipe);
-                       /* Disable mipi port */
-                       REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31)));
-                       REG_READ(mipi_reg);
-               }
-
-               if(pipe == 2)
-                       dev_priv->dpi_panel_on2 = false;
-               else
-                       dev_priv->dpi_panel_on  = false;
-       }
-       gma_power_end(dev);
-}
-
-void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
-{
-       dev_dbg(encoder->dev->dev, "DPMS %s\n",
-                       (mode == DRM_MODE_DPMS_ON ? "on":"off"));
-
-       if (mode == DRM_MODE_DPMS_ON)
-               mdfld_dsi_dpi_set_power(encoder, true);
-       else {
-               mdfld_dsi_dpi_set_power(encoder, false);
-#if 0 /* FIXME */
-#ifdef CONFIG_PM_RUNTIME
-               if (enable_gfx_rtpm)
-                       pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay);
-#endif
-#endif
-       }
-}
-
-bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
-                                    struct drm_display_mode *mode,
-                                    struct drm_display_mode *adjusted_mode)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
-       struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
-
-       if(fixed_mode) {
-               adjusted_mode->hdisplay = fixed_mode->hdisplay;
-               adjusted_mode->hsync_start = fixed_mode->hsync_start;
-               adjusted_mode->hsync_end = fixed_mode->hsync_end;
-               adjusted_mode->htotal = fixed_mode->htotal;
-               adjusted_mode->vdisplay = fixed_mode->vdisplay;
-               adjusted_mode->vsync_start = fixed_mode->vsync_start;
-               adjusted_mode->vsync_end = fixed_mode->vsync_end;
-               adjusted_mode->vtotal = fixed_mode->vtotal;
-               adjusted_mode->clock = fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-       }
-       
-       return true;
-}
-
-void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) 
-{
-       mdfld_dsi_dpi_set_power(encoder, false);
-}
-
-void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) 
-{
-       mdfld_dsi_dpi_set_power(encoder, true);
-}
-
-void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
-                                  struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted_mode)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
-       struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
-       struct drm_device *dev = dsi_config->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
-       
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 mipi_reg = MIPI;
-       u32 reg_offset = 0;
-       
-       u32 pipeconf = dev_priv->pipeconf;
-       u32 dspcntr = dev_priv->dspcntr;
-       u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
-       
-       dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n",
-                               mode->hdisplay, mode->vdisplay, pipe);
-
-       if(pipe) {
-               pipeconf_reg = PIPECCONF;
-               dspcntr_reg = DSPCCNTR;
-               mipi_reg = MIPI_C;
-               reg_offset = MIPIC_REG_OFFSET;
-       } else {
-               mipi |= 2;
-       }
-       
-       if (!gma_power_begin(dev, true))
-               return;
-
-       /* Set up mipi port FIXME: do at init time */
-       REG_WRITE(mipi_reg, mipi);
-       REG_READ(mipi_reg);
-
-       /* Set up DSI controller DPI interface */
-       mdfld_dsi_dpi_controller_init(dsi_config, pipe);
-
-       if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
-               /* Turn on DPI interface */
-               mdfld_dsi_dpi_turn_on(dpi_output, pipe);
-       }
-       
-       /* Set up pipe */
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
-       
-       /* Set up display plane */
-       REG_WRITE(dspcntr_reg, dspcntr);
-       REG_READ(dspcntr_reg);
-       
-       msleep(20); /* FIXME: this should wait for vblank */
-       
-       dev_dbg(dev->dev, "State %x, power %d\n",
-               REG_READ(MIPIA_INTR_STAT_REG + reg_offset),
-               dpi_output->panel_on);
-
-       if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
-               /* Init driver ic */
-               mdfld_dsi_tpo_ic_init(dsi_config, pipe);
-               /* Init backlight */
-               mdfld_dsi_brightness_init(dsi_config, pipe);
-       }
-       gma_power_end(dev);
-}
-
-
-/*
- * Init DSI DPI encoder. 
- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
- * return pointer of newly allocated DPI encoder, NULL on error
- */ 
-struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, 
-                               struct mdfld_dsi_connector *dsi_connector,
-                               struct panel_funcs *p_funcs)
-{
-       struct mdfld_dsi_dpi_output *dpi_output = NULL;
-       struct mdfld_dsi_config *dsi_config;
-       struct drm_connector *connector = NULL;
-       struct drm_encoder *encoder = NULL;
-       struct drm_display_mode *fixed_mode = NULL;
-       int pipe;
-       u32 data;
-       int ret;
-
-       if (!dsi_connector || !p_funcs) {
-               WARN_ON(1);
-               return NULL;
-       }
-
-       dsi_config = mdfld_dsi_get_config(dsi_connector);
-       pipe = dsi_connector->pipe;
-
-       /* Panel hard-reset */
-       if (p_funcs->reset) {
-               ret = p_funcs->reset(pipe);
-               if (ret) {
-                       DRM_ERROR("Panel %d hard-reset failed\n", pipe);
-                       return NULL;
-               }
-       }
-
-       /* Panel drvIC init */
-       if (p_funcs->drv_ic_init)
-               p_funcs->drv_ic_init(dsi_config, pipe);
-
-       /* Panel power mode detect */
-       ret = mdfld_dsi_get_power_mode(dsi_config,
-                                       &data,
-                                       MDFLD_DSI_LP_TRANSMISSION);
-       if (ret) {
-               DRM_ERROR("Panel %d get power mode failed\n", pipe);
-               dsi_connector->status = connector_status_disconnected;
-       } else {
-               DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
-               dsi_connector->status = connector_status_connected;
-       }
-
-       dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
-       if(!dpi_output) {
-               dev_err(dev->dev, "No memory for dsi_dpi_output\n");
-               return NULL;
-       }
-
-       if(dsi_connector->pipe) 
-               dpi_output->panel_on = 0;
-       else
-               dpi_output->panel_on = 0;
-       
-       dpi_output->dev = dev;
-       dpi_output->p_funcs = p_funcs;
-       dpi_output->first_boot = 1;
-       
-       /* Get fixed mode */
-       dsi_config = mdfld_dsi_get_config(dsi_connector);
-       fixed_mode = dsi_config->fixed_mode;
-       
-       /* Create drm encoder object */
-       connector = &dsi_connector->base.base;
-       encoder = &dpi_output->base.base;
-       /*
-        * On existing hardware this will be a panel of some form,
-        * if future devices also have HDMI bridges this will need
-        * revisiting
-        */
-       drm_encoder_init(dev,
-                       encoder,
-                       p_funcs->encoder_funcs,
-                       DRM_MODE_ENCODER_LVDS);
-       drm_encoder_helper_add(encoder,
-                               p_funcs->encoder_helper_funcs);
-       
-       /* Attach to given connector */
-       drm_mode_connector_attach_encoder(connector, encoder);
-       
-       /* Set possible crtcs and clones */
-       if(dsi_connector->pipe) {
-               encoder->possible_crtcs = (1 << 2);
-               encoder->possible_clones = (1 << 1);
-       } else {
-               encoder->possible_crtcs = (1 << 0);
-               encoder->possible_clones = (1 << 0);
-       }
-       return &dpi_output->base;
-}
-
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h
deleted file mode 100644 (file)
index ed92d45..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DPI_H__
-#define __MDFLD_DSI_DPI_H__
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-struct mdfld_dsi_dpi_timing {
-       u16 hsync_count;
-       u16 hbp_count;
-       u16 hfp_count;
-       u16 hactive_count;
-       u16 vsync_count;
-       u16 vbp_count;
-       u16 vfp_count;
-};
-
-struct mdfld_dsi_dpi_output {
-       struct mdfld_dsi_encoder base;
-       struct drm_device *dev;
-
-       int panel_on;
-       int first_boot;
-
-       struct panel_funcs *p_funcs;
-};
-
-#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \
-       container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
-
-extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
-                       struct mdfld_dsi_dpi_timing *dpi_timing,
-                       int num_lane, int bpp);
-extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
-                       struct mdfld_dsi_connector *dsi_connector,
-                       struct panel_funcs *p_funcs);
-
-/* Medfield DPI helper functions */
-extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
-extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode);
-extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
-extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
-extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode);
-extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
-                       int pipe);
-extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config,
-                       int pipe);
-#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
deleted file mode 100644 (file)
index 3f979db..0000000
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include <asm/intel_scu_ipc.h>
-#include "mdfld_dsi_pkg_sender.h"
-#include <linux/pm_runtime.h>
-#include <linux/moduleparam.h>
-
-#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
-
-static int CABC_control = 1;
-static int LABC_control = 1;
-
-module_param (CABC_control, int, 0644);
-module_param (LABC_control, int, 0644);
-
-/**
- * make these MCS command global 
- * we don't need 'movl' everytime we send them.
- * FIXME: these datas were provided by OEM, we should get them from GCT.
- **/
-static u32 mdfld_dbi_mcs_hysteresis[] = {
-       0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
-       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-       0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
-       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-       0x000000ff,
-};
-
-static u32 mdfld_dbi_mcs_display_profile[] = {
-       0x50281450, 0x0000c882, 0x00000000, 0x00000000,
-       0x00000000,
-};
-
-static u32 mdfld_dbi_mcs_kbbc_profile[] = {
-       0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
-}; 
-       
-static u32 mdfld_dbi_mcs_gamma_profile[] = {
-       0x81111158, 0x88888888, 0x88888888,
-}; 
-
-/*
- * write hysteresis values.
- */
-static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
-                                                                int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       if(!sender) {
-               WARN_ON(1);
-               return;
-       }
-       mdfld_dsi_send_mcs_long_hs(sender,
-                                  mdfld_dbi_mcs_hysteresis,
-                                  17,
-                                  MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * write display profile values.
- */
-static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       if(!sender) {
-               WARN_ON(1);
-               return;
-        }
-       mdfld_dsi_send_mcs_long_hs(sender,
-                                  mdfld_dbi_mcs_display_profile,
-                                  5,
-                                  MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * write KBBC profile values.
- */
-static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       if(!sender) {
-               WARN_ON(1);
-               return;
-        }
-       mdfld_dsi_send_mcs_long_hs(sender,
-                                  mdfld_dbi_mcs_kbbc_profile,
-                                  4,
-                                  MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * write gamma setting.
- */
-static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       if(!sender) {
-               WARN_ON(1);
-               return;
-       }
-       mdfld_dsi_send_mcs_long_hs(sender,
-                                  mdfld_dbi_mcs_gamma_profile,
-                                  3,
-                                  MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * Check and see if the generic control or data buffer is empty and ready.
- */
-void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
-{
-       u32 GEN_BF_time_out_count = 0;
-       
-       /* Check MIPI Adatper command registers */
-       for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
-       {
-               if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
-                       break;
-               udelay (100);
-       }
-
-       if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
-               dev_err(dev->dev,
-        "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
-                                                gen_fifo_stat_reg);
-}
-
-/*
- * Manage the DSI MIPI keyboard and display brightness.
- * FIXME: this is exported to OSPM code. should work out an specific 
- * display interface to OSPM. 
- */
-void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-       struct drm_device *dev = sender->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 gen_ctrl_val;
-       
-       if(!sender) {
-               WARN_ON(1);
-               return;
-       }
-       /* Set default display backlight value to 85% (0xd8)*/
-       mdfld_dsi_send_mcs_short_hs(sender,
-                                   write_display_brightness,
-                                   0xd8,
-                                   1,
-                                   MDFLD_DSI_SEND_PACKAGE);
-
-       /* Set minimum brightness setting of CABC function to 20% (0x33)*/
-       mdfld_dsi_send_mcs_short_hs(sender,
-                                   write_cabc_min_bright,
-                                   0x33,
-                                   1,
-                                   MDFLD_DSI_SEND_PACKAGE);
-
-       mdfld_dsi_write_hysteresis(dsi_config, pipe);
-       mdfld_dsi_write_display_profile (dsi_config, pipe);
-       mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
-       mdfld_dsi_write_gamma_setting (dsi_config, pipe);
-
-       /* Enable backlight or/and LABC */
-       gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
-       if (LABC_control == 1 || CABC_control == 1)
-               gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
-
-       if (LABC_control == 1)
-               gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
-
-       dev_priv->mipi_ctrl_display = gen_ctrl_val;
-
-       mdfld_dsi_send_mcs_short_hs(sender,
-                                   write_ctrl_display,
-                                   (u8)gen_ctrl_val,
-                                   1,
-                                   MDFLD_DSI_SEND_PACKAGE);
-
-       if (CABC_control == 0)
-               return;
-       mdfld_dsi_send_mcs_short_hs(sender,
-                                   write_ctrl_cabc,
-                                   UI_IMAGE,
-                                   1,
-                                   MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * Manage the mipi display brightness.
- * TODO: refine this interface later
- */
-void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
-{
-       struct mdfld_dsi_pkg_sender *sender;
-       struct drm_psb_private *dev_priv;
-       struct mdfld_dsi_config *dsi_config;
-       u32 gen_ctrl_val;
-       int p_type;     
-       
-       if (!dev || (pipe != 0 && pipe != 2)) {
-               dev_err(dev->dev, "Invalid parameter\n");
-               return;
-       }
-
-       p_type = mdfld_get_panel_type(dev, 0);
-
-       dev_priv = dev->dev_private;
-
-       if(pipe)
-               dsi_config = dev_priv->dsi_configs[1];
-       else
-               dsi_config = dev_priv->dsi_configs[0];
-
-       sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       if(!sender) {
-               WARN_ON(1);
-               return;
-       }
-
-       gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
-
-       dev_dbg(dev->dev,
-                "pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val);
-       
-       if(p_type == TMD_VID || p_type == TMD_CMD){
-               /* Set display backlight value */
-               mdfld_dsi_send_mcs_short_hs(sender, 
-                                       tmd_write_display_brightness, 
-                                       (u8)gen_ctrl_val, 
-                                        1, 
-                                       MDFLD_DSI_SEND_PACKAGE);                
-       } else {                        
-               /* Set display backlight value */
-               mdfld_dsi_send_mcs_short_hs(sender,
-                                   write_display_brightness,
-                                   (u8)gen_ctrl_val,
-                                    1,
-                                    MDFLD_DSI_SEND_PACKAGE);
-
-
-               /* Enable backlight control */
-               if (level == 0)
-                       gen_ctrl_val = 0;
-               else 
-                       gen_ctrl_val = dev_priv->mipi_ctrl_display;
-
-               mdfld_dsi_send_mcs_short_hs(sender,
-                                    write_ctrl_display,
-                                   (u8)gen_ctrl_val,
-                                   1,
-                                   MDFLD_DSI_SEND_PACKAGE);
-       }
-}
-
-/*
- * shut down DSI controller
- */ 
-void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       struct drm_device * dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int retry = 100;
-       
-       if (!dsi_config) {
-               WARN_ON(1);
-               return;
-       }
-       
-       dev = dsi_config->dev;
-       
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-               
-       if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) &  DSI_DEVICE_READY)) 
-               goto shutdown_out;
-       
-       /* Send shut down package, clean packet send bit first */
-       if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
-               REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), 
-                               (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
-       }
-       
-       /*send shut down package in HS*/
-       REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
-       
-       
-       /*
-        * make sure shut down is sent.
-        * FIXME: add max retry counter
-        */
-       while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
-               retry--;
-               
-               if(!retry) {
-                       dev_err(dev->dev, "timeout\n");
-                       break;
-               }
-       }
-       
-       /*sleep 1 ms to ensure shutdown finished*/
-       msleep(100);
-       
-       /*un-ready device*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
-                          (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));
-
-shutdown_out:                     
-       gma_power_end(dev);
-}
-
-void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       struct drm_device * dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int retry = 100;
-       
-       
-       if (!dsi_config) {
-               WARN_ON(1);
-               return;
-       }
-       
-       dev = dsi_config->dev;
-       dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
-       
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-       
-       if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) 
-               goto startup_out;
-       
-       /*if config DPI, turn on DPI interface*/
-       if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
-               if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
-                       REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
-               }
-               
-               REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
-               
-               /*
-                * make sure shut down is sent.
-                * FIXME: add max retry counter
-                */
-               while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
-                       retry--;
-                       if(!retry) {
-                               dev_err(dev->dev, "timeout\n");
-                               break;
-                       }
-               }
-               
-               msleep(100);
-       }
-       
-       /*set device ready*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
-                          (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));
-
-startup_out:   
-       gma_power_end(dev);
-}
-
-
-static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
-                                       u8 dcs,
-                                       u32 *data,
-                                       u8 transmission)
-{
-       struct mdfld_dsi_pkg_sender *sender
-               = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       if (!sender || !data) {
-               DRM_ERROR("Invalid parameter\n");
-               return -EINVAL;
-       }
-
-       if (transmission == MDFLD_DSI_HS_TRANSMISSION)
-               return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
-       else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
-               return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
-       else
-               return -EINVAL;
-}
-
-int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
-                               u32 *mode,
-                               u8 transmission)
-{
-       if (!dsi_config || !mode) {
-               DRM_ERROR("Invalid parameter\n");
-               return -EINVAL;
-       }
-
-       return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
-}
-
-int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
-                                       u32 *result,
-                                       u8 transmission)
-{
-       if (!dsi_config || !result) {
-               DRM_ERROR("Invalid parameter\n");
-               return -EINVAL;
-       }
-
-       return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
-                                         transmission);
-}
-
-/*
- * NOTE: this function was used by OSPM.
- * TODO: will be removed later, should work out display interfaces for OSPM
- */
-void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
-               WARN_ON(1);
-               return;
-       }
-
-       if(dsi_config->type)
-               mdfld_dsi_dpi_controller_init(dsi_config, pipe);
-       else
-               mdfld_dsi_controller_dbi_init(dsi_config, pipe);
-}
-
-static void mdfld_dsi_connector_save(struct drm_connector * connector)
-{
-}
-
-static void mdfld_dsi_connector_restore(struct drm_connector * connector)
-{
-}
-
-static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
-{
-       struct psb_intel_output *psb_output
-                                       = to_psb_intel_output(connector);
-       struct mdfld_dsi_connector *dsi_connector
-                                       = MDFLD_DSI_CONNECTOR(psb_output);
-       return dsi_connector->status;
-}
-
-static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
-                                       struct drm_property *property,
-                                       uint64_t value)
-{
-       struct drm_encoder *encoder = connector->encoder;
-
-       if (!strcmp(property->name, "scaling mode") && encoder) {
-               struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
-               bool bTransitionFromToCentered;
-               uint64_t curValue;
-
-               if (!psb_crtc)
-                       goto set_prop_error;
-
-               switch (value) {
-               case DRM_MODE_SCALE_FULLSCREEN:
-                       break;
-               case DRM_MODE_SCALE_NO_SCALE:
-                       break;
-               case DRM_MODE_SCALE_ASPECT:
-                       break;
-               default:
-                       goto set_prop_error;
-               }
-
-               if (drm_connector_property_get_value(connector, property, &curValue))
-                       goto set_prop_error;
-
-               if (curValue == value)
-                       goto set_prop_done;
-
-               if (drm_connector_property_set_value(connector, property, value))
-                       goto set_prop_error;
-
-               bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
-                       (value == DRM_MODE_SCALE_NO_SCALE);
-
-               if (psb_crtc->saved_mode.hdisplay != 0 &&
-                   psb_crtc->saved_mode.vdisplay != 0) {
-                       if (bTransitionFromToCentered) {
-                               if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
-                                           encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
-                                       goto set_prop_error;
-                       } else {
-                               struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private;
-                               pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
-                                                    &psb_crtc->saved_adjusted_mode);
-                       }
-               }
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       } else if (!strcmp(property->name, "backlight") && encoder) {
-               struct drm_psb_private *dev_priv = encoder->dev->dev_private;
-               struct backlight_device *psb_bd = dev_priv->backlight_device;
-               dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
-               if (drm_connector_property_set_value(connector, property, value))
-                       goto set_prop_error;
-               else {
-                       dev_dbg(encoder->dev->dev,
-                                       "set brightness to %d", (int)value);
-                       if (psb_bd) {
-                               psb_bd->props.brightness = value;
-                               backlight_update_status(psb_bd);
-                       }
-               }
-#endif
-       }
-set_prop_done:
-    return 0;
-set_prop_error:
-    return -1;
-}
-
-static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
-{
-       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
-       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
-       struct mdfld_dsi_pkg_sender * sender;
-       
-       if(!dsi_connector)
-               return;
-       
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-       
-       sender = dsi_connector->pkg_sender;
-
-       mdfld_dsi_pkg_sender_destroy(sender);
-
-       kfree(dsi_connector);
-}
-
-static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
-{
-       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
-       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
-       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
-       struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
-       struct drm_display_mode * dup_mode = NULL;
-       struct drm_device * dev = connector->dev;
-       
-       connector->display_info.min_vfreq = 0;
-       connector->display_info.max_vfreq = 200;
-       connector->display_info.min_hfreq = 0;
-       connector->display_info.max_hfreq = 200;
-
-       if(fixed_mode) {
-               dev_dbg(dev->dev, "fixed_mode %dx%d\n",
-                       fixed_mode->hdisplay, fixed_mode->vdisplay);
-               
-               dup_mode = drm_mode_duplicate(dev, fixed_mode);
-               drm_mode_probed_add(connector, dup_mode);
-               return 1;
-       }
-       dev_err(dev->dev, "Didn't get any modes!\n");
-       return 0;
-}
-
-static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
-{
-       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
-       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
-       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
-       struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
-
-       dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
-                                                       mode, fixed_mode);
-
-       if(mode->flags & DRM_MODE_FLAG_DBLSCAN) 
-               return MODE_NO_DBLESCAN;
-
-       if(mode->flags & DRM_MODE_FLAG_INTERLACE)
-               return MODE_NO_INTERLACE;
-
-       /**
-        * FIXME: current DC has no fitting unit, reject any mode setting request
-        * will figure out a way to do up-scaling(pannel fitting) later.  
-        **/
-       if(fixed_mode) {
-               if(mode->hdisplay != fixed_mode->hdisplay)
-                       return MODE_PANEL;
-
-               if(mode->vdisplay != fixed_mode->vdisplay)
-                       return MODE_PANEL;
-       }
-       dev_dbg(connector->dev->dev, "mode ok\n");
-
-       return MODE_OK;
-}
-
-static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
-{
-#ifdef CONFIG_PM_RUNTIME
-       struct drm_device * dev = connector->dev;
-       struct drm_psb_private * dev_priv = dev->dev_private;
-       bool panel_on, panel_on2;
-#endif
-       /* First, execute DPMS */
-       drm_helper_connector_dpms(connector, mode);
-
-#ifdef CONFIG_PM_RUNTIME
-       if(mdfld_panel_dpi(dev)) {
-               /* DPI panel */
-               panel_on = dev_priv->dpi_panel_on;
-               panel_on2 = dev_priv->dpi_panel_on2;
-       } else {
-               /* DBI panel */
-               panel_on = dev_priv->dbi_panel_on;
-               panel_on2 = dev_priv->dbi_panel_on2;
-       }
-
-       /* Then check all display panels + monitors status */
-       /* Make sure that the Display (B) sub-system status isn't i3 when
-        * R/W the DC register, otherwise "Fabric error" issue would occur
-        * during S0i3 state. */
-       if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
-                                               & HDMIB_PORT_EN)) {
-               /* Request rpm idle */
-               if(dev_priv->rpm_enabled)
-                       pm_request_idle(&dev->pdev->dev);
-       }
-       /*
-        * if rpm wasn't enabled yet, try to allow it
-        * FIXME: won't enable rpm for DPI since DPI
-        * CRTC setting is a little messy now.
-        * Enable it later!
-        */
-#if 0
-       if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
-               ospm_runtime_pm_allow(dev);
-#endif
-#endif
-}
-
-static struct drm_encoder *mdfld_dsi_connector_best_encoder(
-                                        struct drm_connector *connector) 
-{
-       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
-       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
-       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
-       struct mdfld_dsi_encoder * encoder = NULL;
-       
-       if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) 
-               encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
-       else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) 
-               encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
-       
-       dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
-       
-       if(!encoder) {
-               dev_err(connector->dev->dev,
-                        "Invalid encoder for type %d\n", dsi_config->type);
-               return NULL;
-       }
-       dsi_config->encoder = encoder;  
-       return &encoder->base;  
-}
-
-/* DSI connector funcs */
-static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
-       .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
-       .save = mdfld_dsi_connector_save,
-       .restore = mdfld_dsi_connector_restore,
-       .detect = mdfld_dsi_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .set_property = mdfld_dsi_connector_set_property,
-       .destroy = mdfld_dsi_connector_destroy,
-};
-
-/* DSI connector helper funcs */
-static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
-       .get_modes = mdfld_dsi_connector_get_modes,
-       .mode_valid = mdfld_dsi_connector_mode_valid,
-       .best_encoder = mdfld_dsi_connector_best_encoder,
-};
-
-static int mdfld_dsi_get_default_config(struct drm_device * dev, 
-                                                                               struct mdfld_dsi_config * config, int pipe)
-{
-       if(!dev || !config) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       
-       config->bpp = 24;
-       config->type = mdfld_panel_dpi(dev);
-       config->lane_count = 2;
-       config->channel_num = 0;
-       /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
-       if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
-               config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
-       } else {
-               config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
-       }
-       
-       return 0;
-}
-
-/*
- * Returns the panel fixed mode from configuration. 
- */
-struct drm_display_mode *
-mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       struct drm_device *dev = dsi_config->dev;
-       struct drm_display_mode *mode;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
-       bool use_gct = false;
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode) {
-               dev_err(dev->dev, "Out of memory for mode\n");
-               return NULL;
-        }
-       if (use_gct) {
-               dev_dbg(dev->dev, "gct find MIPI panel.\n");
-
-               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
-               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
-               mode->hsync_start = mode->hdisplay + \
-                               ((ti->hsync_offset_hi << 8) | \
-                               ti->hsync_offset_lo);
-               mode->hsync_end = mode->hsync_start + \
-                               ((ti->hsync_pulse_width_hi << 8) | \
-                               ti->hsync_pulse_width_lo);
-               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
-                                                               ti->hblank_lo);
-               mode->vsync_start = \
-                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
-                                               ti->vsync_offset_lo);
-               mode->vsync_end = \
-                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
-                                               ti->vsync_pulse_width_lo);
-               mode->vtotal = mode->vdisplay + \
-                               ((ti->vblank_hi << 8) | ti->vblank_lo);
-               mode->clock = ti->pixel_clock * 10;
-       } else {
-               if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { 
-                       if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
-                               mode->hdisplay = 480;
-                               mode->vdisplay = 854;
-                               mode->hsync_start = 487;
-                               mode->hsync_end = 490;
-                               mode->htotal = 499;
-                               mode->vsync_start = 861;
-                               mode->vsync_end = 865;
-                               mode->vtotal = 873;
-                               mode->clock = 33264;
-                       } else {
-                               mode->hdisplay = 864;
-                               mode->vdisplay = 480;
-                               mode->hsync_start = 873;
-                               mode->hsync_end = 876;
-                               mode->htotal = 887;
-                               mode->vsync_start = 487;
-                               mode->vsync_end = 490;
-                               mode->vtotal = 499;
-                               mode->clock = 33264;
-                       }
-               } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
-                       mode->hdisplay = 864;
-                       mode->vdisplay = 480;
-                       mode->hsync_start = 872;
-                       mode->hsync_end = 876;
-                       mode->htotal = 884;
-                       mode->vsync_start = 482;
-                       mode->vsync_end = 494;
-                       mode->vtotal = 486;
-                       mode->clock = 25777;
-                       
-               }
-       }
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-       
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-
-       return mode;
-}
-
-int mdfld_dsi_panel_reset(int pipe)
-{
-       unsigned gpio;
-       int ret = 0;
-
-       switch (pipe) {
-       case 0:
-               gpio = 128;
-               break;
-       case 2:
-               gpio = 34;
-               break;
-       default:
-               DRM_ERROR("Invalid output\n");
-               return -EINVAL;
-       }
-
-       ret = gpio_request(gpio, "gfx");
-       if (ret) {
-               DRM_ERROR("gpio_rqueset failed\n");
-               return ret;
-       }
-
-       ret = gpio_direction_output(gpio, 1);
-       if (ret) {
-               DRM_ERROR("gpio_direction_output failed\n");
-               goto gpio_error;
-       }
-
-       gpio_get_value(128);
-
-gpio_error:
-       if (gpio_is_valid(gpio))
-               gpio_free(gpio);
-
-       return ret;
-}
-
-/*
- * MIPI output init
- * @dev drm device
- * @pipe pipe number. 0 or 2
- * @config 
- * 
- * Do the initialization of a MIPI output, including create DRM mode objects
- * initialization of DSI output on @pipe 
- */
-void mdfld_dsi_output_init(struct drm_device *dev,
-                          int pipe, 
-                          struct mdfld_dsi_config *config,
-                          struct panel_funcs* p_cmd_funcs,
-                          struct panel_funcs* p_vid_funcs)
-{
-       struct mdfld_dsi_config * dsi_config;
-       struct mdfld_dsi_connector * dsi_connector;
-       struct psb_intel_output * psb_output;
-       struct drm_connector * connector;
-       struct mdfld_dsi_encoder * encoder;
-       struct drm_psb_private * dev_priv = dev->dev_private;
-       struct panel_info dsi_panel_info;
-       u32 width_mm, height_mm;
-
-       dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
-       
-       if(!dev || ((pipe != 0) && (pipe != 2))) {
-               WARN_ON(1);
-               return;
-       }
-       
-       /*create a new connetor*/
-       dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
-       if(!dsi_connector) {
-               DRM_ERROR("No memory");
-               return;
-       }
-       
-       dsi_connector->pipe =  pipe;
-       
-       /*set DSI config*/
-       if(config) { 
-               dsi_config = config;
-       } else {
-               dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
-               if(!dsi_config) {
-                       dev_err(dev->dev,
-                               "cannot allocate memory for DSI config\n");
-                       goto dsi_init_err0;
-               }
-               
-               mdfld_dsi_get_default_config(dev, dsi_config, pipe);
-       }
-       
-       dsi_connector->private = dsi_config;
-       
-       dsi_config->changed = 1;
-       dsi_config->dev = dev;
-       
-       /* Init fixed mode basing on DSI config type */
-       if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
-               dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
-               if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
-                       goto dsi_init_err0;
-       } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
-               dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
-               if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
-                       goto dsi_init_err0;
-       }
-
-       width_mm = dsi_panel_info.width_mm;
-       height_mm = dsi_panel_info.height_mm;
-
-       dsi_config->mode = dsi_config->fixed_mode;
-       dsi_config->connector = dsi_connector;
-       
-       if(!dsi_config->fixed_mode) {
-               dev_err(dev->dev, "No pannel fixed mode was found\n");
-               goto dsi_init_err0;
-       }
-       
-       if(pipe && dev_priv->dsi_configs[0]) {
-               dsi_config->dvr_ic_inited = 0;
-               dev_priv->dsi_configs[1] = dsi_config;
-       } else if(pipe == 0) {
-               dsi_config->dvr_ic_inited = 1;
-               dev_priv->dsi_configs[0] = dsi_config;
-       } else {
-               dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
-               goto dsi_init_err0;
-       }
-
-       /*init drm connector object*/
-       psb_output = &dsi_connector->base;
-       
-       psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
-
-       connector = &psb_output->base;
-       /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
-       drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
-                                               DRM_MODE_CONNECTOR_LVDS);
-       drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
-       
-       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-       connector->display_info.width_mm = width_mm;
-       connector->display_info.height_mm = height_mm;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-       
-       /* Attach properties */
-       drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
-       drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
-
-       /* Init DSI package sender on this output */
-       if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
-               DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
-               goto dsi_init_err0;
-       }
-
-       /* Init DBI & DPI encoders */
-       if (p_cmd_funcs) {
-               encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
-               if(!encoder) {
-                       dev_err(dev->dev, "Create DBI encoder failed\n");
-                       goto dsi_init_err1;
-               }
-               encoder->private = dsi_config;
-               dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
-       }
-       
-       if(p_vid_funcs) {
-               encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
-               if(!encoder) {
-                       dev_err(dev->dev, "Create DPI encoder failed\n");
-                       goto dsi_init_err1;
-               }
-               encoder->private = dsi_config;
-               dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
-       }
-       
-       drm_sysfs_connector_add(connector);
-       return;
-       
-       /*TODO: add code to destroy outputs on error*/
-dsi_init_err1:
-       /*destroy sender*/
-       mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
-
-       drm_connector_cleanup(connector);
-       kfree(dsi_config->fixed_mode);
-       kfree(dsi_config);
-dsi_init_err0:
-       kfree(dsi_connector);
-}
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
deleted file mode 100644 (file)
index 4699267..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_OUTPUT_H__
-#define __MDFLD_DSI_OUTPUT_H__
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include "mdfld_output.h"
-
-#include <asm/mrst.h>
-
-
-static inline struct mdfld_dsi_config *
-       mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
-{
-       if (!connector)
-               return NULL;
-       return (struct mdfld_dsi_config *)connector->private;
-}
-
-static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
-{
-       struct mdfld_dsi_connector *dsi_connector;
-
-       if (!config)
-               return NULL;
-
-       dsi_connector = config->connector;
-
-       if (!dsi_connector)
-               return NULL;
-
-       return dsi_connector->pkg_sender;
-}
-
-static inline struct mdfld_dsi_config *
-       mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
-{
-       if (!encoder)
-               return NULL;
-       return (struct mdfld_dsi_config *)encoder->private;
-}
-
-static inline struct mdfld_dsi_connector *
-       mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
-{
-       struct mdfld_dsi_config *config;
-
-       if (!encoder)
-               return NULL;
-
-       config = mdfld_dsi_encoder_get_config(encoder);
-       if (!config)
-               return NULL;
-
-       return config->connector;
-}
-
-static inline void *mdfld_dsi_encoder_get_pkg_sender(
-       struct mdfld_dsi_encoder *encoder)
-{
-       struct mdfld_dsi_config *dsi_config;
-
-       dsi_config = mdfld_dsi_encoder_get_config(encoder);
-       if (!dsi_config)
-               return NULL;
-
-       return mdfld_dsi_get_pkg_sender(dsi_config);
-}
-
-static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
-{
-       struct mdfld_dsi_connector *connector;
-
-       if (!encoder)
-               return -1;
-
-       connector = mdfld_dsi_encoder_get_connector(encoder);
-       if (!connector)
-               return -1;
-
-       return connector->pipe;
-}
-
-extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
-                               u32 gen_fifo_stat_reg, u32 fifo_stat);
-extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
-                               int pipe);
-extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
-                               int level);
-extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe,
-                               struct mdfld_dsi_config *config,
-                               struct panel_funcs *p_cmd_funcs,
-                               struct panel_funcs *p_vid_funcs);
-extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
-                               int pipe);
-extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
-                               u32 *mode,
-                               u8 transmission);
-extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
-                               u32 *result,
-                               u8 transmission);
-extern int mdfld_dsi_panel_reset(int pipe);
-
-#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
deleted file mode 100644 (file)
index 9b96a5c..0000000
+++ /dev/null
@@ -1,1484 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include <linux/freezer.h>
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-
-#define MDFLD_DSI_DBI_FIFO_TIMEOUT             100
-#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE       512
-#define MDFLD_DSI_READ_MAX_COUNT               5000
-
-static const char * const dsi_errors[] = {
-       "RX SOT Error",
-       "RX SOT Sync Error",
-       "RX EOT Sync Error",
-       "RX Escape Mode Entry Error",
-       "RX LP TX Sync Error",
-       "RX HS Receive Timeout Error",
-       "RX False Control Error",
-       "RX ECC Single Bit Error",
-       "RX ECC Multibit Error",
-       "RX Checksum Error",
-       "RX DSI Data Type Not Recognised",
-       "RX DSI VC ID Invalid",
-       "TX False Control Error",
-       "TX ECC Single Bit Error",
-       "TX ECC Multibit Error",
-       "TX Checksum Error",
-       "TX DSI Data Type Not Recognised",
-       "TX DSI VC ID invalid",
-       "High Contention",
-       "Low contention",
-       "DPI FIFO Under run",
-       "HS TX Timeout",
-       "LP RX Timeout",
-       "Turn Around ACK Timeout",
-       "ACK With No Error",
-       "RX Invalid TX Length",
-       "RX Prot Violation",
-       "HS Generic Write FIFO Full",
-       "LP Generic Write FIFO Full",
-       "Generic Read Data Avail",
-       "Special Packet Sent",
-       "Tearing Effect",
-};
-
-static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
-                                                               u32 mask)
-{
-       struct drm_device *dev = sender->dev;
-       u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
-       int retry = 0xffff;
-
-       while (retry--) {
-               if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
-                       return 0;
-               udelay(100);
-       }
-       dev_err(dev->dev, "fifo is NOT empty 0x%08x\n",
-                                       REG_READ(gen_fifo_stat_reg));
-       return -EIO;
-}
-
-static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
-       return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18)
-               | (1 << 26) | (1 << 27) | (1 << 28));
-}
-
-static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
-       return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26));
-}
-
-static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
-       return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18));
-}
-
-static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender)
-{
-       return wait_for_gen_fifo_empty(sender, (1 << 27));
-}
-
-static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
-{
-       u32 intr_stat_reg = sender->mipi_intr_stat_reg;
-       struct drm_device *dev = sender->dev;
-
-       switch (mask) {
-       case (1 << 0):
-       case (1 << 1):
-       case (1 << 2):
-       case (1 << 3):
-       case (1 << 4):
-       case (1 << 5):
-       case (1 << 6):
-       case (1 << 7):
-       case (1 << 8):
-       case (1 << 9):
-       case (1 << 10):
-       case (1 << 11):
-       case (1 << 12):
-       case (1 << 13):
-               break;
-       case (1 << 14):
-               /*wait for all fifo empty*/
-               /*wait_for_all_fifos_empty(sender)*/;
-               break;
-       case (1 << 15):
-               break;
-       case (1 << 16):
-               break;
-       case (1 << 17):
-               break;
-       case (1 << 18):
-       case (1 << 19):
-               /*wait for contention recovery time*/
-               /*mdelay(10);*/
-               /*wait for all fifo empty*/
-               if (0)
-                       wait_for_all_fifos_empty(sender);
-               break;
-       case (1 << 20):
-               break;
-       case (1 << 21):
-               /*wait for all fifo empty*/
-               /*wait_for_all_fifos_empty(sender);*/
-               break;
-       case (1 << 22):
-               break;
-       case (1 << 23):
-       case (1 << 24):
-       case (1 << 25):
-       case (1 << 26):
-       case (1 << 27):
-               /* HS Gen fifo full */
-               REG_WRITE(intr_stat_reg, mask);
-               wait_for_hs_fifos_empty(sender);
-               break;
-       case (1 << 28):
-               /* LP Gen fifo full\n */
-               REG_WRITE(intr_stat_reg, mask);
-               wait_for_lp_fifos_empty(sender);
-               break;
-       case (1 << 29):
-       case (1 << 30):
-       case (1 << 31):
-               break;
-       }
-
-       if (mask & REG_READ(intr_stat_reg))
-               dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask);
-
-       return 0;
-}
-
-static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
-{
-       struct drm_device *dev = sender->dev;
-       u32 intr_stat_reg = sender->mipi_intr_stat_reg;
-       u32 mask;
-       u32 intr_stat;
-       int i;
-       int err = 0;
-
-       intr_stat = REG_READ(intr_stat_reg);
-
-       for (i = 0; i < 32; i++) {
-               mask = (0x00000001UL) << i;
-               if (intr_stat & mask) {
-                       dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]);
-                       err = handle_dsi_error(sender, mask);
-                       if (err)
-                               dev_err(dev->dev, "Cannot handle error\n");
-               }
-       }
-       return err;
-}
-
-static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender)
-{
-       struct drm_device *dev = sender->dev;
-       u32 retry = 0xffff;
-       u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
-
-       /* Query the command execution status */
-       while (retry--) {
-               if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0)))
-                       break;
-       }
-
-       if (!retry) {
-               dev_err(dev->dev, "Timeout waiting for DBI Command status\n");
-               return -EAGAIN;
-       }
-       return 0;
-}
-
-/*
- * NOTE: this interface is abandoned expect for write_mem_start DCS
- * other DCS are sent via generic pkg interfaces
- */
-static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender,
-                       struct mdfld_dsi_pkg *pkg)
-{
-       struct drm_device *dev = sender->dev;
-       struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg;
-       u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg;
-       u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
-       u32 cb_phy = sender->dbi_cb_phy;
-       u32 index = 0;
-       u8 *cb = (u8 *)sender->dbi_cb_addr;
-       int i;
-       int ret;
-
-       if (!sender->dbi_pkg_support) {
-               dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n");
-               return -ENOTSUPP;
-       }
-
-       /*wait for DBI fifo empty*/
-       wait_for_dbi_fifo_empty(sender);
-
-       *(cb + (index++)) = dcs_pkg->cmd;
-       if (dcs_pkg->param_num) {
-               for (i = 0; i < dcs_pkg->param_num; i++)
-                       *(cb + (index++)) = *(dcs_pkg->param + i);
-       }
-
-       REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num));
-       REG_WRITE(dbi_cmd_addr_reg,
-               (cb_phy << CMD_MEM_ADDR_OFFSET)
-               | (1 << 0)
-               | ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0));
-
-       ret = dbi_cmd_sent(sender);
-       if (ret) {
-               dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd);
-               return -EAGAIN;
-       }
-       return 0;
-}
-
-static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       struct drm_device *dev = sender->dev;
-       u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
-       u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
-       u32 gen_ctrl_val = 0;
-       struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg;
-
-       gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS;
-       gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
-       gen_ctrl_val |= pkg->pkg_type;
-       gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS;
-
-       if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
-               /* wait for hs fifo empty */
-               /* wait_for_hs_fifos_empty(sender); */
-               /* Send pkg */
-               REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
-       } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
-               /* wait_for_lp_fifos_empty(sender); */
-               /* Send pkg*/
-               REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
-       } else {
-               dev_err(dev->dev, "Unknown transmission type %d\n",
-                                                       pkg->transmission_type);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       struct drm_device *dev = sender->dev;
-       u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
-       u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg;
-       u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
-       u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg;
-       u32 gen_ctrl_val = 0;
-       u32 *dp;
-       int i;
-       struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg;
-
-       dp = long_pkg->data;
-
-       /*
-        * Set up word count for long pkg
-        * FIXME: double check word count field.
-        * currently, using the byte counts of the payload as the word count.
-        * ------------------------------------------------------------
-        * | DI |   WC   | ECC|         PAYLOAD              |CHECKSUM|
-        * ------------------------------------------------------------
-        */
-       gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS;
-       gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
-       gen_ctrl_val |= pkg->pkg_type;
-
-       if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
-               /* Wait for hs ctrl and data fifos to be empty */
-               /* wait_for_hs_fifos_empty(sender); */
-               for (i = 0; i < long_pkg->len; i++)
-                       REG_WRITE(hs_gen_data_reg, *(dp + i));
-               REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
-       } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
-               /* wait_for_lp_fifos_empty(sender); */
-               for (i = 0; i < long_pkg->len; i++)
-                       REG_WRITE(lp_gen_data_reg, *(dp + i));
-               REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
-       } else {
-               dev_err(dev->dev, "Unknown transmission type %d\n",
-                                               pkg->transmission_type);
-               return -EINVAL;
-       }
-
-       return 0;
-
-}
-
-static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       return __send_short_pkg(sender, pkg);
-}
-
-static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       return __send_long_pkg(sender, pkg);
-}
-
-static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       return __send_short_pkg(sender, pkg);
-}
-
-static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       return __send_long_pkg(sender, pkg);
-}
-
-static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       u8 cmd;
-       u8 *data;
-
-       switch (pkg->pkg_type) {
-       case MDFLD_DSI_PKG_DCS:
-               cmd = pkg->pkg.dcs_pkg.cmd;
-               break;
-       case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
-       case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
-               cmd = pkg->pkg.short_pkg.cmd;
-               break;
-       case MDFLD_DSI_PKG_MCS_LONG_WRITE:
-               data = (u8 *)pkg->pkg.long_pkg.data;
-               cmd = *data;
-               break;
-       default:
-               return 0;
-       }
-
-       /* This prevents other package sending while doing msleep */
-       sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
-
-       /* Check panel mode v.s. sending command */
-       if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) &&
-               cmd != exit_sleep_mode) {
-               dev_err(sender->dev->dev,
-                               "sending 0x%x when panel sleep in\n", cmd);
-               sender->status = MDFLD_DSI_PKG_SENDER_FREE;
-               return -EINVAL;
-       }
-
-       /* Wait for 120 milliseconds in case exit_sleep_mode just be sent */
-       if (cmd == DCS_ENTER_SLEEP_MODE) {
-               /*TODO: replace it with msleep later*/
-               mdelay(120);
-       }
-       return 0;
-}
-
-static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg)
-{
-       u8 cmd;
-       u8 *data;
-
-       switch (pkg->pkg_type) {
-       case MDFLD_DSI_PKG_DCS:
-               cmd = pkg->pkg.dcs_pkg.cmd;
-               break;
-       case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
-       case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
-               cmd = pkg->pkg.short_pkg.cmd;
-               break;
-       case MDFLD_DSI_PKG_MCS_LONG_WRITE:
-               data = (u8 *)pkg->pkg.long_pkg.data;
-               cmd = *data;
-               break;
-       default:
-               return 0;
-       }
-
-       /* Update panel status */
-       if (cmd == DCS_ENTER_SLEEP_MODE) {
-               sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
-               /*TODO: replace it with msleep later*/
-               mdelay(120);
-       } else if (cmd == DCS_EXIT_SLEEP_MODE) {
-               sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
-               /*TODO: replace it with msleep later*/
-               mdelay(120);
-       } else if (unlikely(cmd == DCS_SOFT_RESET)) {
-               /*TODO: replace it with msleep later*/
-               mdelay(5);
-       }
-       sender->status = MDFLD_DSI_PKG_SENDER_FREE;
-       return 0;
-
-}
-
-static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender,
-                       struct mdfld_dsi_pkg *pkg)
-{
-       int ret;
-
-       if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
-               dev_err(sender->dev->dev, "sender is busy\n");
-               return -EAGAIN;
-       }
-
-       ret = send_pkg_prepare(sender, pkg);
-       if (ret) {
-               dev_err(sender->dev->dev, "send_pkg_prepare error\n");
-               return ret;
-       }
-
-       switch (pkg->pkg_type) {
-       case MDFLD_DSI_PKG_DCS:
-               ret = send_dcs_pkg(sender, pkg);
-               break;
-       case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0:
-       case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1:
-       case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2:
-       case MDFLD_DSI_PKG_GEN_READ_0:
-       case MDFLD_DSI_PKG_GEN_READ_1:
-       case MDFLD_DSI_PKG_GEN_READ_2:
-               ret = send_gen_short_pkg(sender, pkg);
-               break;
-       case MDFLD_DSI_PKG_GEN_LONG_WRITE:
-               ret = send_gen_long_pkg(sender, pkg);
-               break;
-       case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
-       case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
-       case MDFLD_DSI_PKG_MCS_READ:
-               ret = send_mcs_short_pkg(sender, pkg);
-               break;
-       case MDFLD_DSI_PKG_MCS_LONG_WRITE:
-               ret = send_mcs_long_pkg(sender, pkg);
-               break;
-       default:
-               dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n",
-                                                       pkg->pkg_type);
-               ret = -EINVAL;
-       }
-       send_pkg_done(sender, pkg);
-       return ret;
-}
-
-static int send_pkg(struct mdfld_dsi_pkg_sender *sender,
-                       struct mdfld_dsi_pkg *pkg)
-{
-       int err ;
-
-       /* Handle DSI error */
-       err = dsi_error_handler(sender);
-       if (err) {
-               dev_err(sender->dev->dev, "Error handling failed\n");
-               err = -EAGAIN;
-               goto send_pkg_err;
-       }
-
-       /* Send pkg */
-       err = do_send_pkg(sender, pkg);
-       if (err) {
-               dev_err(sender->dev->dev, "sent pkg failed\n");
-               err = -EAGAIN;
-               goto send_pkg_err;
-       }
-
-       /* FIXME: should I query complete and fifo empty here? */
-send_pkg_err:
-       return err;
-}
-
-static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked(
-                                       struct mdfld_dsi_pkg_sender *sender)
-{
-       struct mdfld_dsi_pkg *pkg;
-
-       if (list_empty(&sender->free_list)) {
-               dev_err(sender->dev->dev, "No free pkg left\n");
-               return NULL;
-       }
-       pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry);
-       /* Detach from free list */
-       list_del_init(&pkg->entry);
-       return pkg;
-}
-
-static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender,
-                                       struct mdfld_dsi_pkg *pkg)
-{
-       memset(pkg, 0, sizeof(struct mdfld_dsi_pkg));
-       INIT_LIST_HEAD(&pkg->entry);
-       list_add_tail(&pkg->entry, &sender->free_list);
-}
-
-static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender,
-                                       struct psb_gtt *pg, int pipe)
-{
-       unsigned long phys;
-       void *virt_addr = NULL;
-
-       switch (pipe) {
-       case 0:
-               /* FIXME: Doesn't this collide with stolen space ? */
-               phys = pg->gtt_phys_start - 0x1000;
-               break;
-       case 2:
-               phys = pg->gtt_phys_start - 0x800;
-               break;
-       default:
-               dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe);
-               return -EINVAL;
-       }
-
-       virt_addr = ioremap_nocache(phys, 0x800);
-       if (!virt_addr) {
-               dev_err(sender->dev->dev, "Map DBI command buffer error\n");
-               return -ENOMEM;
-       }
-       sender->dbi_cb_phy = phys;
-       sender->dbi_cb_addr = virt_addr;
-       return 0;
-}
-
-static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender)
-{
-       if (sender && sender->dbi_cb_addr)
-               iounmap(sender->dbi_cb_addr);
-}
-
-static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender,
-                                       struct mdfld_dsi_pkg *pkg,
-                                       int delay)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-
-       if (!delay) {
-               send_pkg(sender, pkg);
-               pkg_sender_put_pkg_locked(sender, pkg);
-       } else {
-               /* Queue it */
-               list_add_tail(&pkg->entry, &sender->pkg_list);
-       }
-       spin_unlock_irqrestore(&sender->lock, flags);
-}
-
-static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-
-       while (!list_empty(&sender->pkg_list)) {
-               pkg = list_first_entry(&sender->pkg_list,
-                                       struct mdfld_dsi_pkg, entry);
-               send_pkg(sender, pkg);
-               list_del_init(&pkg->entry);
-               pkg_sender_put_pkg_locked(sender, pkg);
-       }
-
-       spin_unlock_irqrestore(&sender->lock, flags);
-}
-
-static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender,
-       u32 *data, u32 len, u8 transmission, int delay)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-       pkg = pkg_sender_get_pkg_locked(sender);
-       spin_unlock_irqrestore(&sender->lock, flags);
-
-       if (!pkg) {
-               dev_err(sender->dev->dev, "No memory\n");
-               return -ENOMEM;
-       }
-       pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE;
-       pkg->transmission_type = transmission;
-       pkg->pkg.long_pkg.data = data;
-       pkg->pkg.long_pkg.len = len;
-       INIT_LIST_HEAD(&pkg->entry);
-
-       pkg_sender_queue_pkg(sender, pkg, delay);
-       return 0;
-}
-
-static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender,
-                                       u8 cmd, u8 param, u8 param_num,
-                                       u8 transmission,
-                                       int delay)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-       pkg = pkg_sender_get_pkg_locked(sender);
-       spin_unlock_irqrestore(&sender->lock, flags);
-
-       if (!pkg) {
-               dev_err(sender->dev->dev, "No memory\n");
-               return -ENOMEM;
-       }
-
-       if (param_num) {
-               pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1;
-               pkg->pkg.short_pkg.param = param;
-       } else {
-               pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0;
-               pkg->pkg.short_pkg.param = 0;
-       }
-       pkg->transmission_type = transmission;
-       pkg->pkg.short_pkg.cmd = cmd;
-       INIT_LIST_HEAD(&pkg->entry);
-
-       pkg_sender_queue_pkg(sender, pkg, delay);
-       return 0;
-}
-
-static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender,
-                                       u8 param0, u8 param1, u8 param_num,
-                                       u8 transmission,
-                                       int delay)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-       pkg = pkg_sender_get_pkg_locked(sender);
-       spin_unlock_irqrestore(&sender->lock, flags);
-
-       if (!pkg) {
-               dev_err(sender->dev->dev, "No pkg memory\n");
-               return -ENOMEM;
-       }
-
-       switch (param_num) {
-       case 0:
-               pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0;
-               pkg->pkg.short_pkg.cmd = 0;
-               pkg->pkg.short_pkg.param = 0;
-               break;
-       case 1:
-               pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1;
-               pkg->pkg.short_pkg.cmd = param0;
-               pkg->pkg.short_pkg.param = 0;
-               break;
-       case 2:
-               pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2;
-               pkg->pkg.short_pkg.cmd = param0;
-               pkg->pkg.short_pkg.param = param1;
-               break;
-       }
-
-       pkg->transmission_type = transmission;
-       INIT_LIST_HEAD(&pkg->entry);
-
-       pkg_sender_queue_pkg(sender, pkg, delay);
-       return 0;
-}
-
-static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender,
-                               u32 *data, u32 len, u8 transmission, int delay)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-       pkg = pkg_sender_get_pkg_locked(sender);
-       spin_unlock_irqrestore(&sender->lock, flags);
-
-       if (!pkg) {
-               dev_err(sender->dev->dev, "No pkg memory\n");
-               return -ENOMEM;
-       }
-
-       pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE;
-       pkg->transmission_type = transmission;
-       pkg->pkg.long_pkg.data = data;
-       pkg->pkg.long_pkg.len = len;
-
-       INIT_LIST_HEAD(&pkg->entry);
-
-       pkg_sender_queue_pkg(sender, pkg, delay);
-
-       return 0;
-}
-
-static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender,
-                               struct mdfld_dsi_pkg *pkg,
-                               u32 *data,
-                               u16 len)
-{
-       unsigned long flags;
-       struct drm_device *dev = sender->dev;
-       int i;
-       u32 gen_data_reg;
-       int retry = MDFLD_DSI_READ_MAX_COUNT;
-       u8 transmission = pkg->transmission_type;
-
-       /*
-        * do reading.
-        * 0) send out generic read request
-        * 1) polling read data avail interrupt
-        * 2) read data
-        */
-       spin_lock_irqsave(&sender->lock, flags);
-
-       REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29);
-
-       if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29)))
-               DRM_ERROR("Can NOT clean read data valid interrupt\n");
-
-       /*send out read request*/
-       send_pkg(sender, pkg);
-
-       pkg_sender_put_pkg_locked(sender, pkg);
-
-       /*polling read data avail interrupt*/
-       while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) {
-               udelay(100);
-               retry--;
-       }
-
-       if (!retry) {
-               spin_unlock_irqrestore(&sender->lock, flags);
-               return -ETIMEDOUT;
-       }
-
-       REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29));
-
-       /*read data*/
-       if (transmission == MDFLD_DSI_HS_TRANSMISSION)
-               gen_data_reg = sender->mipi_hs_gen_data_reg;
-       else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
-               gen_data_reg = sender->mipi_lp_gen_data_reg;
-       else {
-               DRM_ERROR("Unknown transmission");
-               spin_unlock_irqrestore(&sender->lock, flags);
-               return -EINVAL;
-       }
-
-       for (i=0; i<len; i++)
-               *(data + i) = REG_READ(gen_data_reg);
-
-       spin_unlock_irqrestore(&sender->lock, flags);
-       return 0;
-}
-
-static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender,
-                               u8 param0,
-                               u8 param1,
-                               u8 param_num,
-                               u32 *data,
-                               u16 len,
-                               u8 transmission)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-
-       pkg = pkg_sender_get_pkg_locked(sender);
-
-       spin_unlock_irqrestore(&sender->lock,flags);
-
-       if (!pkg) {
-               dev_err(sender->dev->dev, "No pkg memory\n");
-               return -ENOMEM;
-       }
-
-       switch (param_num) {
-       case 0:
-               pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0;
-               pkg->pkg.short_pkg.cmd = 0;
-               pkg->pkg.short_pkg.param = 0;
-               break;
-       case 1:
-               pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1;
-               pkg->pkg.short_pkg.cmd = param0;
-               pkg->pkg.short_pkg.param = 0;
-               break;
-       case 2:
-               pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2;
-               pkg->pkg.short_pkg.cmd = param0;
-               pkg->pkg.short_pkg.param = param1;
-               break;
-       }
-
-       pkg->transmission_type = transmission;
-
-       INIT_LIST_HEAD(&pkg->entry);
-
-       return __read_panel_data(sender, pkg, data, len);
-}
-static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender,
-                               u8 cmd,
-                               u32 *data,
-                               u16 len,
-                               u8 transmission)
-{
-       struct mdfld_dsi_pkg *pkg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sender->lock, flags);
-
-       pkg = pkg_sender_get_pkg_locked(sender);
-
-       spin_unlock_irqrestore(&sender->lock, flags);
-       if (!pkg) {
-               dev_err(sender->dev->dev, "No pkg memory\n");
-               return -ENOMEM;
-       }
-
-       pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ;
-       pkg->pkg.short_pkg.cmd = cmd;
-       pkg->pkg.short_pkg.param = 0;
-
-       pkg->transmission_type = transmission;
-       INIT_LIST_HEAD(&pkg->entry);
-
-       return __read_panel_data(sender, pkg, data, len);
-}
-
-void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       struct drm_device * dev = dsi_config->dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int lane_count = dsi_config->lane_count;
-       u32 val = 0;
-
-       /*un-ready device*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
-       /*init dsi adapter before kicking off*/
-       REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
-       /*TODO: figure out how to setup these registers*/
-       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-       REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014);
-       REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
-       REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
-       REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
-
-       /*enable all interrupts*/
-       REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-       /*max value: 20 clock cycles of txclkesc*/
-       REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
-       /*min 21 txclkesc, max: ffffh*/
-       REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
-       /*min: 7d0 max: 4e20*/
-       REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
-
-       /*set up max return packet size*/
-       REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset),
-                       MDFLD_DSI_MAX_RETURN_PACKET_SIZE);
-
-       /*set up func_prg*/
-       val |= lane_count;
-       val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
-       val |= DSI_DBI_COLOR_FORMAT_OPTION2;
-       REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
-       REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
-       REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
-
-       REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-       REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
-       REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       struct drm_device * dev = dsi_config->dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int lane_count = dsi_config->lane_count;
-       struct mdfld_dsi_dpi_timing dpi_timing;
-       struct drm_display_mode * mode = dsi_config->mode;
-       u32 val = 0;
-
-       /*un-ready device*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
-       /*init dsi adapter before kicking off*/
-       REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
-       /*enable all interrupts*/
-       REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-
-       /*set up func_prg*/
-       val |= lane_count;
-       val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
-
-       switch(dsi_config->bpp) {
-       case 16:
-               val |= DSI_DPI_COLOR_FORMAT_RGB565;
-               break;
-       case 18:
-               val |= DSI_DPI_COLOR_FORMAT_RGB666;
-               break;
-       case 24:
-               val |= DSI_DPI_COLOR_FORMAT_RGB888;
-               break;
-       default:
-               DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
-       }
-
-       REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
-       REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset),
-                       (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
-       REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
-
-       /*max value: 20 clock cycles of txclkesc*/
-       REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
-
-       /*min 21 txclkesc, max: ffffh*/
-       REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
-
-       REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
-
-       /*set DPI timing registers*/
-       mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
-
-       REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
-       REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
-
-       REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-
-       /*min: 7d0 max: 4e20*/
-       REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
-
-       /*set up video mode*/
-       val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
-       REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
-
-       REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
-
-       REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-
-       /*TODO: figure out how to setup these registers*/
-       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-
-       REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
-
-       /*set device ready*/
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
-       if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
-               DRM_ERROR("Invalid parameters\n");
-               return;
-       }
-
-       if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
-               dsi_controller_dpi_init(dsi_config, pipe);
-       else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
-               dsi_controller_dbi_init(dsi_config, pipe);
-       else
-               DRM_ERROR("Bad DSI encoder type\n");
-}
-
-void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender)
-{
-       process_pkg_list(sender);
-}
-
-int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 dcs, u8 *param, u32 param_num, u8 data_src,
-                       int delay)
-{
-       struct mdfld_dsi_pkg *pkg;
-       u32 cb_phy = sender->dbi_cb_phy;
-       struct drm_device *dev = sender->dev;
-       u32 index = 0;
-       u8 *cb = (u8 *)sender->dbi_cb_addr;
-       unsigned long flags;
-       int retry;
-       u8 *dst = NULL;
-       u32 len;
-
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       if (!sender->dbi_pkg_support) {
-               dev_err(dev->dev, "No DBI pkg sending on this sender\n");
-               return -ENOTSUPP;
-       }
-
-       if (param_num > MDFLD_MAX_DCS_PARAM) {
-               dev_err(dev->dev, "Sender only supports up to %d DCS params\n",
-                                                       MDFLD_MAX_DCS_PARAM);
-               return -EINVAL;
-       }
-
-       /*
-        * If dcs is write_mem_start, send it directly using DSI adapter
-        * interface
-        */
-       if (dcs == DCS_WRITE_MEM_START) {
-               if (!spin_trylock(&sender->lock))
-                       return -EAGAIN;
-
-               /*
-                * query whether DBI FIFO is empty,
-                * if not wait it becoming empty
-                */
-               retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
-               while (retry &&
-                   !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) {
-                       udelay(500);
-                       retry--;
-               }
-
-               /* If DBI FIFO timeout, drop this frame */
-               if (!retry) {
-                       spin_unlock(&sender->lock);
-                       return 0;
-               }
-
-               *(cb + (index++)) = write_mem_start;
-
-               REG_WRITE(sender->mipi_cmd_len_reg, 1);
-               REG_WRITE(sender->mipi_cmd_addr_reg,
-                                       cb_phy | (1 << 0) | (1 << 1));
-
-               retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
-               while (retry &&
-                       (REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) {
-                       udelay(1);
-                       retry--;
-               }
-
-               spin_unlock(&sender->lock);
-               return 0;
-       }
-
-       /* Get a free pkg */
-       spin_lock_irqsave(&sender->lock, flags);
-       pkg = pkg_sender_get_pkg_locked(sender);
-       spin_unlock_irqrestore(&sender->lock, flags);
-
-       if (!pkg) {
-               dev_err(dev->dev, "No packages memory\n");
-               return -ENOMEM;
-       }
-
-       dst = pkg->pkg.dcs_pkg.param;
-       memcpy(dst, param, param_num);
-
-       pkg->pkg_type = MDFLD_DSI_PKG_DCS;
-       pkg->transmission_type = MDFLD_DSI_DCS;
-       pkg->pkg.dcs_pkg.cmd = dcs;
-       pkg->pkg.dcs_pkg.param_num = param_num;
-       pkg->pkg.dcs_pkg.data_src = data_src;
-
-       INIT_LIST_HEAD(&pkg->entry);
-
-       if (param_num == 0)
-               return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay);
-       else if (param_num == 1)
-               return mdfld_dsi_send_mcs_short_hs(sender, dcs,
-                                                       param[0], 1, delay);
-       else if (param_num > 1) {
-               len = (param_num + 1) / 4;
-               if ((param_num + 1) % 4)
-                       len++;
-               return mdfld_dsi_send_mcs_long_hs(sender,
-                               (u32 *)&pkg->pkg.dcs_pkg, len, delay);
-       }
-       return 0;
-}
-
-int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
-                               u8 cmd, u8 param, u8 param_num, int delay)
-{
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
-                                       MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
-                               u8 cmd, u8 param, u8 param_num, int delay)
-{
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
-                                       MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
-                               u32 *data,
-                               u32 len,
-                               int delay)
-{
-       if (!sender || !data || !len) {
-               DRM_ERROR("Invalid parameters\n");
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_mcs_long(sender, data, len,
-                                       MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
-                               u32 *data,
-                               u32 len,
-                               int delay)
-{
-       if (!sender || !data || !len) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_mcs_long(sender, data, len,
-                               MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
-                               u8 param0, u8 param1, u8 param_num, int delay)
-{
-       if (!sender) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
-                                       MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
-                               u8 param0, u8 param1, u8 param_num, int delay)
-{
-       if (!sender || param_num < 0 || param_num > 2) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
-                                       MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
-                               u32 *data,
-                               u32 len,
-                               int delay)
-{
-       if (!sender || !data || !len) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_gen_long(sender, data, len,
-                                       MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
-                               u32 *data,
-                               u32 len,
-                               int delay)
-{
-       if (!sender || !data || !len) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       return mdfld_dsi_send_gen_long(sender, data, len,
-                                       MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 param0,
-                       u8 param1,
-                       u8 param_num,
-                       u32 *data,
-                       u16 len)
-{
-       if (!sender || !data || param_num < 0 || param_num > 2
-               || !data || !len) {
-               DRM_ERROR("Invalid parameters\n");
-               return -EINVAL;
-       }
-
-       return mdfld_dsi_read_gen(sender, param0, param1, param_num,
-                               data, len, MDFLD_DSI_HS_TRANSMISSION);
-
-}
-
-int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u8 param0,
-                       u8 param1,
-                       u8 param_num,
-                       u32 *data,
-                       u16 len)
-{
-       if (!sender || !data || param_num < 0 || param_num > 2
-               || !data || !len) {
-               DRM_ERROR("Invalid parameters\n");
-               return -EINVAL;
-       }
-
-       return mdfld_dsi_read_gen(sender, param0, param1, param_num,
-                               data, len, MDFLD_DSI_LP_TRANSMISSION);
-}
-
-int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 cmd,
-                       u32 *data,
-                       u16 len)
-{
-       if (!sender || !data || !len) {
-               DRM_ERROR("Invalid parameters\n");
-               return -EINVAL;
-       }
-
-       return mdfld_dsi_read_mcs(sender, cmd, data, len,
-                               MDFLD_DSI_HS_TRANSMISSION);
-}
-
-int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u8 cmd,
-                       u32 *data,
-                       u16 len)
-{
-       if (!sender || !data || !len) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       return mdfld_dsi_read_mcs(sender, cmd, data, len,
-                               MDFLD_DSI_LP_TRANSMISSION);
-}
-int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
-                                                               int pipe)
-{
-       int ret;
-       struct mdfld_dsi_pkg_sender *pkg_sender;
-       struct mdfld_dsi_config *dsi_config =
-                                       mdfld_dsi_get_config(dsi_connector);
-       struct drm_device *dev = dsi_config->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_gtt *pg = &dev_priv->gtt;
-       int i;
-       struct mdfld_dsi_pkg *pkg, *tmp;
-       u32 mipi_val = 0;
-
-       if (!dsi_connector) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       pkg_sender = dsi_connector->pkg_sender;
-
-       if (!pkg_sender || IS_ERR(pkg_sender)) {
-               pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
-                                                               GFP_KERNEL);
-               if (!pkg_sender) {
-                       dev_err(dev->dev, "Create DSI pkg sender failed\n");
-                       return -ENOMEM;
-               }
-
-               dsi_connector->pkg_sender = (void *)pkg_sender;
-       }
-
-       pkg_sender->dev = dev;
-       pkg_sender->dsi_connector = dsi_connector;
-       pkg_sender->pipe = pipe;
-       pkg_sender->pkg_num = 0;
-       pkg_sender->panel_mode = 0;
-       pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
-
-       /* Init dbi command buffer*/
-
-       if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
-               pkg_sender->dbi_pkg_support = 1;
-               ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe);
-               if (ret) {
-                       dev_err(dev->dev, "DBI command buffer map failed\n");
-                       goto mapping_err;
-               }
-       }
-
-       /* Init regs */
-       if (pipe == 0) {
-               pkg_sender->dpll_reg = MRST_DPLL_A;
-               pkg_sender->dspcntr_reg = DSPACNTR;
-               pkg_sender->pipeconf_reg = PIPEACONF;
-               pkg_sender->dsplinoff_reg = DSPALINOFF;
-               pkg_sender->dspsurf_reg = DSPASURF;
-               pkg_sender->pipestat_reg = PIPEASTAT;
-
-               pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG;
-               pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG;
-               pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG;
-               pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG;
-               pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
-               pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
-               pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG;
-               pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG;
-               pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG;
-               pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG;
-       } else if (pipe == 2) {
-               pkg_sender->dpll_reg = MRST_DPLL_A;
-               pkg_sender->dspcntr_reg = DSPCCNTR;
-               pkg_sender->pipeconf_reg = PIPECCONF;
-               pkg_sender->dsplinoff_reg = DSPCLINOFF;
-               pkg_sender->dspsurf_reg = DSPCSURF;
-               pkg_sender->pipestat_reg = PIPECSTAT;
-
-               pkg_sender->mipi_intr_stat_reg =
-                               MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_lp_gen_data_reg =
-                               MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_hs_gen_data_reg =
-                               MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_lp_gen_ctrl_reg =
-                               MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_hs_gen_ctrl_reg =
-                               MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_gen_fifo_stat_reg =
-                               MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_data_addr_reg =
-                               MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_data_len_reg =
-                               MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_cmd_addr_reg =
-                               MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET;
-               pkg_sender->mipi_cmd_len_reg =
-                               MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET;
-       }
-
-       /* Init pkg list */
-       INIT_LIST_HEAD(&pkg_sender->pkg_list);
-       INIT_LIST_HEAD(&pkg_sender->free_list);
-
-       spin_lock_init(&pkg_sender->lock);
-
-       /* Allocate free pkg pool */
-       for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) {
-               pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL);
-               if (!pkg) {
-                       dev_err(dev->dev, "Out of memory allocating pkg pool");
-                       ret = -ENOMEM;
-                       goto pkg_alloc_err;
-               }
-               INIT_LIST_HEAD(&pkg->entry);
-               list_add_tail(&pkg->entry, &pkg_sender->free_list);
-       }
-
-       /*
-        * For video mode, don't enable DPI timing output here,
-        * will init the DPI timing output during mode setting.
-        */
-       if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
-               mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
-       else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
-               mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX
-                       | TE_TRIGGER_GPIO_PIN;
-       else
-               DRM_ERROR("Bad DSI encoder type\n");
-
-       if (pipe == 0) {
-               mipi_val |= 0x2;
-               REG_WRITE(MIPI, mipi_val);
-               REG_READ(MIPI);
-       } else if (pipe == 2) {
-               REG_WRITE(MIPI_C, mipi_val);
-               REG_READ(MIPI_C);
-       }
-
-       /*do dsi controller init*/
-       dsi_controller_init(dsi_config, pipe);
-       
-       return 0;
-
-pkg_alloc_err:
-       list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) {
-               list_del(&pkg->entry);
-               kfree(pkg);
-       }
-
-       /* Free mapped command buffer */
-       mdfld_dbi_cb_destroy(pkg_sender);
-mapping_err:
-       kfree(pkg_sender);
-       dsi_connector->pkg_sender = NULL;
-       return ret;
-}
-
-void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
-{
-       struct mdfld_dsi_pkg *pkg, *tmp;
-
-       if (!sender || IS_ERR(sender))
-               return;
-
-       /* Free pkg pool */
-       list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) {
-               list_del(&pkg->entry);
-               kfree(pkg);
-       }
-       /* Free pkg list */
-       list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) {
-               list_del(&pkg->entry);
-               kfree(pkg);
-       }
-       mdfld_dbi_cb_destroy(sender);   /* free mapped command buffer */
-       kfree(sender);
-}
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
deleted file mode 100644 (file)
index f24abc7..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jackie Li<yaodong.li@intel.com>
- */
-#ifndef __MDFLD_DSI_PKG_SENDER_H__
-#define __MDFLD_DSI_PKG_SENDER_H__
-
-#include <linux/kthread.h>
-
-#define MDFLD_MAX_DCS_PARAM    8
-#define MDFLD_MAX_PKG_NUM      2048
-
-enum {
-       MDFLD_DSI_PKG_DCS,
-       MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03,
-       MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13,
-       MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23,
-       MDFLD_DSI_PKG_GEN_READ_0 = 0x04,
-       MDFLD_DSI_PKG_GEN_READ_1 = 0x14,
-       MDFLD_DSI_PKG_GEN_READ_2 = 0x24,
-       MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29,
-       MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05,
-       MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15,
-       MDFLD_DSI_PKG_MCS_READ = 0x06,
-       MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39,
-};
-
-enum {
-       MDFLD_DSI_LP_TRANSMISSION,
-       MDFLD_DSI_HS_TRANSMISSION,
-       MDFLD_DSI_DCS,
-};
-
-enum {
-       MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
-};
-
-enum {
-       MDFLD_DSI_PKG_SENDER_FREE = 0x0,
-       MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
-};
-
-enum {
-       MDFLD_DSI_SEND_PACKAGE,
-       MDFLD_DSI_QUEUE_PACKAGE,
-};
-
-struct mdfld_dsi_gen_short_pkg {
-       u8 cmd;
-       u8 param;
-};
-
-struct mdfld_dsi_gen_long_pkg {
-       u32 *data;
-       u32 len;
-};
-
-struct mdfld_dsi_dcs_pkg {
-       u8 cmd;
-       u8 param[MDFLD_MAX_DCS_PARAM];
-       u32 param_num;
-       u8 data_src;
-};
-
-struct mdfld_dsi_pkg {
-       u8 pkg_type;
-       u8 transmission_type;
-
-       union {
-               struct mdfld_dsi_gen_short_pkg short_pkg;
-               struct mdfld_dsi_gen_long_pkg long_pkg;
-               struct mdfld_dsi_dcs_pkg dcs_pkg;
-       } pkg;
-
-       struct list_head entry;
-};
-
-struct mdfld_dsi_pkg_sender {
-       struct drm_device *dev;
-       struct mdfld_dsi_connector *dsi_connector;
-       u32 status;
-
-       u32 panel_mode;
-
-       int pipe;
-
-       spinlock_t lock;
-       struct list_head pkg_list;
-       struct list_head free_list;
-
-       u32 pkg_num;
-
-       int dbi_pkg_support;
-
-       u32 dbi_cb_phy;
-       void *dbi_cb_addr;
-
-       /* Registers */
-       u32 dpll_reg;
-       u32 dspcntr_reg;
-       u32 pipeconf_reg;
-       u32 pipestat_reg;
-       u32 dsplinoff_reg;
-       u32 dspsurf_reg;
-
-       u32 mipi_intr_stat_reg;
-       u32 mipi_lp_gen_data_reg;
-       u32 mipi_hs_gen_data_reg;
-       u32 mipi_lp_gen_ctrl_reg;
-       u32 mipi_hs_gen_ctrl_reg;
-       u32 mipi_gen_fifo_stat_reg;
-       u32 mipi_data_addr_reg;
-       u32 mipi_data_len_reg;
-       u32 mipi_cmd_addr_reg;
-       u32 mipi_cmd_len_reg;
-};
-
-/* DCS definitions */
-#define DCS_SOFT_RESET                 0x01
-#define DCS_ENTER_SLEEP_MODE           0x10
-#define DCS_EXIT_SLEEP_MODE            0x11
-#define DCS_SET_DISPLAY_OFF            0x28
-#define DCS_SET_DISPLAY_ON             0x29
-#define DCS_SET_COLUMN_ADDRESS         0x2a
-#define DCS_SET_PAGE_ADDRESS           0x2b
-#define DCS_WRITE_MEM_START            0x2c
-#define DCS_SET_TEAR_OFF               0x34
-#define DCS_SET_TEAR_ON                0x35
-
-extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
-                       int pipe);
-extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
-extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs,
-                       u8 *param, u32 param_num, u8 data_src, int delay);
-extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 cmd, u8 param, u8 param_num, int delay);
-extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u8 cmd, u8 param, u8 param_num, int delay);
-extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u32 *data, u32 len, int delay);
-extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u32 *data, u32 len, int delay);
-extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 param0, u8 param1, u8 param_num, int delay);
-extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u8 param0, u8 param1, u8 param_num, int delay);
-extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u32 *data, u32 len, int delay);
-extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u32 *data, u32 len, int delay);
-
-extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
-extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
-extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
-                       u8 cmd, u32 *data, u16 len);
-extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
-                       u8 cmd, u32 *data, u16 len);
-
-extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender);
-
-#endif /* __MDFLD_DSI_PKG_SENDER_H__ */
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
deleted file mode 100644 (file)
index 0b37b7b..0000000
+++ /dev/null
@@ -1,1404 +0,0 @@
-/*
- * Copyright Â© 2006-2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#include "framebuffer.h"
-#include "psb_intel_display.h"
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_dbi_dpu.h"
-
-#include <linux/pm_runtime.h>
-
-#ifdef MIN
-#undef MIN
-#endif
-
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-
-/* Hardcoded currently */
-static int ksel = KSEL_CRYSTAL_19;
-
-extern void mdfld_save_display(struct drm_device *dev);
-extern bool gbgfxsuspended;
-
-struct psb_intel_range_t {
-       int min, max;
-};
-
-struct mdfld_limit_t {
-       struct psb_intel_range_t dot, m, p1;
-};
-
-struct mdfld_intel_clock_t {
-       /* given values */
-       int n;
-       int m1, m2;
-       int p1, p2;
-       /* derived values */
-       int dot;
-       int vco;
-       int m;
-       int p;
-};
-
-
-
-#define COUNT_MAX 0x10000000
-
-void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
-{
-       int count, temp;
-       u32 pipeconf_reg = PIPEACONF;
-       
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               pipeconf_reg = PIPEBCONF;
-               break;
-       case 2:
-               pipeconf_reg = PIPECCONF;
-               break;
-       default:
-               DRM_ERROR("Illegal Pipe Number. \n");
-               return;
-       }
-
-       /* FIXME JLIU7_PO */
-       psb_intel_wait_for_vblank(dev);
-       return;
-
-       /* Wait for for the pipe disable to take effect. */
-       for (count = 0; count < COUNT_MAX; count++) {
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_PIPE_STATE) == 0)
-                       break;
-       }
-}
-
-void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
-{
-       int count, temp;
-       u32 pipeconf_reg = PIPEACONF;
-       
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               pipeconf_reg = PIPEBCONF;
-               break;
-       case 2:
-               pipeconf_reg = PIPECCONF;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number.\n");
-               return;
-       }
-
-       /* FIXME JLIU7_PO */
-       psb_intel_wait_for_vblank(dev);
-       return;
-
-       /* Wait for for the pipe enable to take effect. */
-       for (count = 0; count < COUNT_MAX; count++) {
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_PIPE_STATE) == 1)
-                       break;
-       }
-}
-
-
-static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
-                                struct drm_file *file_priv,
-                                uint32_t handle,
-                                uint32_t width, uint32_t height)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       uint32_t control = CURACNTR;
-       uint32_t base = CURABASE;
-       uint32_t temp;
-       size_t addr = 0;
-       struct gtt_range *gt;
-       struct drm_gem_object *obj;
-       int ret;
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               control = CURBCNTR;
-               base = CURBBASE;
-               break;
-       case 2:
-               control = CURCCNTR;
-               base = CURCBASE;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number. \n");
-               return -EINVAL;
-       }
-       
-#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
-       if (pipe != 0)
-               return 0;
-#endif 
-       /* if we want to turn of the cursor ignore width and height */
-       if (!handle) {
-               dev_dbg(dev->dev, "cursor off\n");
-               /* turn off the cursor */
-               temp = 0;
-               temp |= CURSOR_MODE_DISABLE;
-
-               if (gma_power_begin(dev, true)) {
-                       REG_WRITE(control, temp);
-                       REG_WRITE(base, 0);
-                       gma_power_end(dev);
-               }
-               /* Unpin the old GEM object */
-               if (psb_intel_crtc->cursor_obj) {
-                       gt = container_of(psb_intel_crtc->cursor_obj,
-                                                       struct gtt_range, gem);
-                       psb_gtt_unpin(gt);
-                       drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-                       psb_intel_crtc->cursor_obj = NULL;
-               }
-               return 0;
-       }
-
-       /* Currently we only support 64x64 cursors */
-       if (width != 64 || height != 64) {
-               DRM_ERROR("we currently only support 64x64 cursors\n");
-               return -EINVAL;
-       }
-
-       obj = drm_gem_object_lookup(dev, file_priv, handle);
-       if (!obj)
-               return -ENOENT;
-
-       if (obj->size < width * height * 4) {
-               dev_dbg(dev->dev, "buffer is to small\n");
-               return -ENOMEM;
-       }
-
-       gt = container_of(obj, struct gtt_range, gem);
-
-       /* Pin the memory into the GTT */
-       ret = psb_gtt_pin(gt);
-       if (ret) {
-               dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
-               return ret;
-       }
-
-
-       addr = gt->offset;      /* Or resource.start ??? */
-
-       psb_intel_crtc->cursor_addr = addr;
-
-       temp = 0;
-       /* set the pipe for the cursor */
-       temp |= (pipe << 28);
-       temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
-       if (gma_power_begin(dev, true)) {
-               REG_WRITE(control, temp);
-               REG_WRITE(base, addr);
-               gma_power_end(dev);
-       }
-       /* unpin the old GEM object */
-       if (psb_intel_crtc->cursor_obj) {
-               gt = container_of(psb_intel_crtc->cursor_obj,
-                                                       struct gtt_range, gem);
-               psb_gtt_unpin(gt);
-               drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-               psb_intel_crtc->cursor_obj = obj;
-       }
-       return 0;
-}
-
-static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
-       struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-       struct psb_drm_dpu_rect rect;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       uint32_t pos = CURAPOS;
-       uint32_t base = CURABASE;
-       uint32_t temp = 0;
-       uint32_t addr;
-
-       switch (pipe) {
-       case 0:
-               if (dpu_info) {
-                       rect.x = x;
-                       rect.y = y;
-               
-                       mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
-                       mdfld_dpu_exit_dsr(dev);
-               } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
-                       mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0);
-               break;
-       case 1:
-               pos = CURBPOS;
-               base = CURBBASE;
-               break;
-       case 2:
-               if (dpu_info) {
-                       mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
-                       mdfld_dpu_exit_dsr(dev);
-               } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
-                       mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2);
-               pos = CURCPOS;
-               base = CURCBASE;
-               break;
-       default:
-               DRM_ERROR("Illegal Pipe Number. \n");
-               return -EINVAL;
-       }
-               
-#if 1 /* FIXME_JLIU7 can't enable cursorB/C HW issue. need to remove after HW fix */
-       if (pipe != 0)
-               return 0;
-#endif 
-       if (x < 0) {
-               temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
-               x = -x;
-       }
-       if (y < 0) {
-               temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
-               y = -y;
-       }
-
-       temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
-       temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
-       addr = psb_intel_crtc->cursor_addr;
-
-       if (gma_power_begin(dev, true)) {
-               REG_WRITE(pos, temp);
-               REG_WRITE(base, addr);
-               gma_power_end(dev);
-       }
-
-       return 0;
-}
-
-const struct drm_crtc_funcs mdfld_intel_crtc_funcs = {
-       .cursor_set = mdfld_intel_crtc_cursor_set,
-       .cursor_move = mdfld_intel_crtc_cursor_move,
-       .gamma_set = psb_intel_crtc_gamma_set,
-       .set_config = drm_crtc_helper_set_config,
-       .destroy = psb_intel_crtc_destroy,
-};
-
-static struct drm_device globle_dev;
-
-void mdfld__intel_plane_set_alpha(int enable)
-{
-       struct drm_device *dev = &globle_dev;
-       int dspcntr_reg = DSPACNTR;
-       u32 dspcntr;
-
-       dspcntr = REG_READ(dspcntr_reg);
-
-       if (enable) {
-               dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
-               dspcntr |= DISPPLANE_32BPP;
-       } else {
-               dspcntr &= ~DISPPLANE_32BPP;
-               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-       }
-
-       REG_WRITE(dspcntr_reg, dspcntr);
-}
-
-int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_i915_master_private *master_priv; */
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
-       int pipe = psb_intel_crtc->pipe;
-       unsigned long start, offset;
-       int dsplinoff = DSPALINOFF;
-       int dspsurf = DSPASURF;
-       int dspstride = DSPASTRIDE;
-       int dspcntr_reg = DSPACNTR;
-       u32 dspcntr;
-       int ret = 0;
-
-       memcpy(&globle_dev, dev, sizeof(struct drm_device));
-
-       if (!gma_power_begin(dev, true))
-               return 0;
-
-       /* no fb bound */
-       if (!crtc->fb) {
-               dev_err(dev->dev, "No FB bound\n");
-               goto psb_intel_pipe_cleaner;
-       }
-
-       switch (pipe) {
-       case 0:
-               dsplinoff = DSPALINOFF;
-               break;
-       case 1:
-               dsplinoff = DSPBLINOFF;
-               dspsurf = DSPBSURF;
-               dspstride = DSPBSTRIDE;
-               dspcntr_reg = DSPBCNTR;
-               break;
-       case 2:
-               dsplinoff = DSPCLINOFF;
-               dspsurf = DSPCSURF;
-               dspstride = DSPCSTRIDE;
-               dspcntr_reg = DSPCCNTR;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number.\n");
-               return -EINVAL;
-       }
-
-       ret = psb_gtt_pin(psbfb->gtt);
-       if (ret < 0)
-               goto psb_intel_pipe_set_base_exit;
-
-       start = psbfb->gtt->offset;
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
-       dspcntr = REG_READ(dspcntr_reg);
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               dspcntr |= DISPPLANE_8BPP;
-               break;
-       case 16:
-               if (crtc->fb->depth == 15)
-                       dspcntr |= DISPPLANE_15_16BPP;
-               else
-                       dspcntr |= DISPPLANE_16BPP;
-               break;
-       case 24:
-       case 32:
-               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-               break;
-       default:
-               dev_err(dev->dev, "Unknown color depth\n");
-               ret = -EINVAL;
-               goto psb_intel_pipe_set_base_exit;
-       }
-       REG_WRITE(dspcntr_reg, dspcntr);
-
-       dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
-                                               start, offset, x, y);
-
-       REG_WRITE(dsplinoff, offset);
-       REG_READ(dsplinoff);
-       REG_WRITE(dspsurf, start);
-       REG_READ(dspsurf);
-
-psb_intel_pipe_cleaner:
-       /* If there was a previous display we can now unpin it */
-       if (old_fb)
-               psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
-       gma_power_end(dev);
-       return ret;
-}
-
-/**
- * Disable the pipe, plane and pll.
- *
- */
-void mdfld_disable_crtc (struct drm_device *dev, int pipe)
-{
-       int dpll_reg = MRST_DPLL_A;
-       int dspcntr_reg = DSPACNTR;
-       int dspbase_reg = MRST_DSPABASE;
-       int pipeconf_reg = PIPEACONF;
-       u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
-       u32 temp;
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               dpll_reg = MDFLD_DPLL_B;
-               dspcntr_reg = DSPBCNTR;
-               dspbase_reg = DSPBSURF;
-               pipeconf_reg = PIPEBCONF;
-               break;
-       case 2:
-               dpll_reg = MRST_DPLL_A;
-               dspcntr_reg = DSPCCNTR;
-               dspbase_reg = MDFLD_DSPCBASE;
-               pipeconf_reg = PIPECCONF;
-               gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number. \n");
-               return;
-       }
-
-       if (pipe != 1)
-               mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
-       /* Disable display plane */
-       temp = REG_READ(dspcntr_reg);
-       if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-               REG_WRITE(dspcntr_reg,
-                         temp & ~DISPLAY_PLANE_ENABLE);
-               /* Flush the plane changes */
-               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-               REG_READ(dspbase_reg);
-       }
-
-       /* FIXME_JLIU7 MDFLD_PO revisit */
-       /* Wait for vblank for the disable to take effect */
-/* MDFLD_PO_JLIU7              psb_intel_wait_for_vblank(dev); */
-
-       /* Next, disable display pipes */
-       temp = REG_READ(pipeconf_reg);
-       if ((temp & PIPEACONF_ENABLE) != 0) {
-               temp &= ~PIPEACONF_ENABLE;
-               temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
-               REG_WRITE(pipeconf_reg, temp);
-               REG_READ(pipeconf_reg);
-
-               /* Wait for for the pipe disable to take effect. */
-               mdfldWaitForPipeDisable(dev, pipe);
-       }
-
-       temp = REG_READ(dpll_reg);
-       if (temp & DPLL_VCO_ENABLE) {
-               if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
-                               || (pipe == 1)){
-                       temp &= ~(DPLL_VCO_ENABLE);
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to turn off. */
-                       /* FIXME_MDFLD PO may need more delay */
-                       udelay(500);
-
-                       if (!(temp & MDFLD_PWR_GATE_EN)) {
-                               /* gating power of DPLL */
-                               REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
-                               /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                               udelay(5000);
-                       }
-               }
-       }
-
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = MRST_DPLL_A;
-       int dspcntr_reg = DSPACNTR;
-       int dspbase_reg = MRST_DSPABASE;
-       int pipeconf_reg = PIPEACONF;
-       u32 pipestat_reg = PIPEASTAT;
-       u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
-       u32 pipeconf = dev_priv->pipeconf;
-       u32 dspcntr = dev_priv->dspcntr;
-       u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG;
-       u32 temp;
-       bool enabled;
-       int timeout = 0;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-        /* Ignore if system is already in DSR and in suspended state. */
-       if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){
-           if(dev_priv->rpm_enabled && pipe == 1){
-       //          dev_priv->is_mipi_on = false;
-                 pm_request_idle(&dev->pdev->dev);
-           }
-           return;
-       }else if(mode == 0) {
-               //do not need to set gbdispstatus=true in crtc.
-               //this will be set in encoder such as mdfld_dsi_dbi_dpms
-           //gbdispstatus = true;
-       }
-
-/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
-/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               dpll_reg = DPLL_B;
-               dspcntr_reg = DSPBCNTR;
-               dspbase_reg = MRST_DSPBBASE;
-               pipeconf_reg = PIPEBCONF;
-               pipeconf = dev_priv->pipeconf1;
-               dspcntr = dev_priv->dspcntr1;
-               dpll_reg = MDFLD_DPLL_B;
-               break;
-       case 2:
-               dpll_reg = MRST_DPLL_A;
-               dspcntr_reg = DSPCCNTR;
-               dspbase_reg = MDFLD_DSPCBASE;
-               pipeconf_reg = PIPECCONF;
-               pipestat_reg = PIPECSTAT;
-               pipeconf = dev_priv->pipeconf2;
-               dspcntr = dev_priv->dspcntr2;
-               gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
-               mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number.\n");
-               return;
-       }
-
-       /* XXX: When our outputs are all unaware of DPMS modes other than off
-        * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-        */
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-               /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
-
-               if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
-                       if (temp & MDFLD_PWR_GATE_EN) {
-                               temp &= ~MDFLD_PWR_GATE_EN;
-                               REG_WRITE(dpll_reg, temp);
-                               /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                               udelay(500);
-                       }
-
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
-                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                       udelay(500);
-                       
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-
-                       /**
-                        * wait for DSI PLL to lock
-                        * NOTE: only need to poll status of pipe 0 and pipe 1,
-                        * since both MIPI pipes share the same PLL.
-                        */
-                       while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
-                               udelay(150);
-                               timeout ++;
-                       }
-               }
-
-               /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
-                               temp | DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-               }
-
-               /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) == 0) {
-                       REG_WRITE(pipeconf_reg, pipeconf);
-
-                       /* Wait for for the pipe enable to take effect. */
-                       mdfldWaitForPipeEnable(dev, pipe);
-               }
-
-               /*workaround for sighting 3741701 Random X blank display*/
-               /*perform w/a in video mode only on pipe A or C*/
-               if ((pipe == 0 || pipe == 2) &&
-                       (mdfld_panel_dpi(dev) == true)) {
-                       REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
-                       msleep(100);
-                       if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
-                               printk(KERN_ALERT "OK");
-                       } else {
-                               printk(KERN_ALERT "STUCK!!!!");
-                               /*shutdown controller*/
-                               temp = REG_READ(dspcntr_reg);
-                               REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
-                               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                               /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
-                               REG_WRITE(0xb048, 1);
-                               msleep(100);
-                               temp = REG_READ(pipeconf_reg);
-                               temp &= ~PIPEACONF_ENABLE;
-                               REG_WRITE(pipeconf_reg, temp);
-                               msleep(100); /*wait for pipe disable*/
-                       /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
-                       printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
-                               REG_WRITE(mipi_enable_reg, 0);
-                               msleep(100);
-                       printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
-                       printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
-                               REG_WRITE(0xb004, REG_READ(0xb004));
-                               /* try to bring the controller back up again*/
-                               REG_WRITE(mipi_enable_reg, 1);
-                               temp = REG_READ(dspcntr_reg);
-                               REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
-                               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                               /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
-                               REG_WRITE(0xb048, 2);
-                               msleep(100);
-                               temp = REG_READ(pipeconf_reg);
-                               temp |= PIPEACONF_ENABLE;
-                               REG_WRITE(pipeconf_reg, temp);
-                       }
-               }
-
-               psb_intel_crtc_load_lut(crtc);
-
-               /* Give the overlay scaler a chance to enable
-                  if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, true); TODO */
-
-               break;
-       case DRM_MODE_DPMS_OFF:
-               /* Give the overlay scaler a chance to disable
-                * if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-               if (pipe != 1)
-                       mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
-               /* Disable the VGA plane that we never use */
-               REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
-               /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp & ~DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
-               }
-
-               /* FIXME_JLIU7 MDFLD_PO revisit */
-               /* Wait for vblank for the disable to take effect */
-// MDFLD_PO_JLIU7              psb_intel_wait_for_vblank(dev);
-
-               /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) != 0) {
-                       temp &= ~PIPEACONF_ENABLE;
-                       temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
-                       REG_WRITE(pipeconf_reg, temp);
-//                     REG_WRITE(pipeconf_reg, 0);
-                       REG_READ(pipeconf_reg);
-
-                       /* Wait for for the pipe disable to take effect. */
-                       mdfldWaitForPipeDisable(dev, pipe);
-               }
-
-               temp = REG_READ(dpll_reg);
-               if (temp & DPLL_VCO_ENABLE) {
-                       if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
-                                       || (pipe == 1)){
-                               temp &= ~(DPLL_VCO_ENABLE);
-                               REG_WRITE(dpll_reg, temp);
-                               REG_READ(dpll_reg);
-                               /* Wait for the clocks to turn off. */
-                               /* FIXME_MDFLD PO may need more delay */
-                               udelay(500);
-#if 0 /* MDFLD_PO_JLIU7 */     
-               if (!(temp & MDFLD_PWR_GATE_EN)) {
-                       /* gating power of DPLL */
-                       REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
-                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                       udelay(5000);
-               }
-#endif  /* MDFLD_PO_JLIU7 */   
-                       }
-               }
-               break;
-       }
-
-       enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
-#if 0                          /* JB: Add vblank support later */
-       if (enabled)
-               dev_priv->vblank_pipe |= (1 << pipe);
-       else
-               dev_priv->vblank_pipe &= ~(1 << pipe);
-#endif
-
-       gma_power_end(dev);
-}
-
-
-#define MDFLD_LIMT_DPLL_19         0
-#define MDFLD_LIMT_DPLL_25         1
-#define MDFLD_LIMT_DPLL_83         2
-#define MDFLD_LIMT_DPLL_100        3
-#define MDFLD_LIMT_DSIPLL_19       4
-#define MDFLD_LIMT_DSIPLL_25       5
-#define MDFLD_LIMT_DSIPLL_83       6
-#define MDFLD_LIMT_DSIPLL_100      7
-
-#define MDFLD_DOT_MIN            19750  /* FIXME_MDFLD JLIU7 need to find out  min & max for MDFLD */
-#define MDFLD_DOT_MAX            120000
-#define MDFLD_DPLL_M_MIN_19        113
-#define MDFLD_DPLL_M_MAX_19        155
-#define MDFLD_DPLL_P1_MIN_19       2
-#define MDFLD_DPLL_P1_MAX_19       10
-#define MDFLD_DPLL_M_MIN_25        101
-#define MDFLD_DPLL_M_MAX_25        130
-#define MDFLD_DPLL_P1_MIN_25       2
-#define MDFLD_DPLL_P1_MAX_25       10
-#define MDFLD_DPLL_M_MIN_83        64
-#define MDFLD_DPLL_M_MAX_83        64
-#define MDFLD_DPLL_P1_MIN_83       2
-#define MDFLD_DPLL_P1_MAX_83       2
-#define MDFLD_DPLL_M_MIN_100       64
-#define MDFLD_DPLL_M_MAX_100       64
-#define MDFLD_DPLL_P1_MIN_100      2
-#define MDFLD_DPLL_P1_MAX_100      2
-#define MDFLD_DSIPLL_M_MIN_19      131
-#define MDFLD_DSIPLL_M_MAX_19      175
-#define MDFLD_DSIPLL_P1_MIN_19     3
-#define MDFLD_DSIPLL_P1_MAX_19     8
-#define MDFLD_DSIPLL_M_MIN_25      97
-#define MDFLD_DSIPLL_M_MAX_25      140
-#define MDFLD_DSIPLL_P1_MIN_25     3
-#define MDFLD_DSIPLL_P1_MAX_25     9
-#define MDFLD_DSIPLL_M_MIN_83      33
-#define MDFLD_DSIPLL_M_MAX_83      92
-#define MDFLD_DSIPLL_P1_MIN_83     2
-#define MDFLD_DSIPLL_P1_MAX_83     3
-#define MDFLD_DSIPLL_M_MIN_100     97
-#define MDFLD_DSIPLL_M_MAX_100     140
-#define MDFLD_DSIPLL_P1_MIN_100            3
-#define MDFLD_DSIPLL_P1_MAX_100            9
-
-static const struct mdfld_limit_t mdfld_limits[] = {
-       {                       /* MDFLD_LIMT_DPLL_19 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
-        .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
-        },
-       {                       /* MDFLD_LIMT_DPLL_25 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
-        .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
-        },
-       {                       /* MDFLD_LIMT_DPLL_83 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
-        .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
-        },
-       {                       /* MDFLD_LIMT_DPLL_100 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
-        .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
-        },
-       {                       /* MDFLD_LIMT_DSIPLL_19 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
-        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
-        },
-       {                       /* MDFLD_LIMT_DSIPLL_25 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
-        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
-        },
-       {                       /* MDFLD_LIMT_DSIPLL_83 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
-        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
-        },
-       {                       /* MDFLD_LIMT_DSIPLL_100 */
-        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
-        .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
-        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
-        },
-};
-
-#define MDFLD_M_MIN        21
-#define MDFLD_M_MAX        180
-static const u32 mdfld_m_converts[] = {
-/* M configuration table from 9-bit LFSR table */
-       224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
-       173, 342, 171, 85, 298, 149, 74, 37, 18, 265,   /* 31 - 40 */
-       388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
-       83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
-       341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
-       461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
-       106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
-       71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
-       253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
-       478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
-       477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
-       210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
-       145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
-       380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
-       103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
-       396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
-};
-
-static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc)
-{
-       const struct mdfld_limit_t *limit = NULL;
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
-           || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
-               if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
-                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
-               else if (ksel == KSEL_BYPASS_25) 
-                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
-               else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
-                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
-               else if ((ksel == KSEL_BYPASS_83_100) &&
-                        (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
-                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
-       } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
-               if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
-                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
-               else if (ksel == KSEL_BYPASS_25) 
-                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
-               else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
-                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
-               else if ((ksel == KSEL_BYPASS_83_100) &&
-                        (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
-                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
-       } else {
-               limit = NULL;
-               dev_err(dev->dev, "mdfld_limit Wrong display type.\n");
-       }
-
-       return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock)
-{
-       clock->dot = (refclk * clock->m) / clock->p1;
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given refclk,
- * or FALSE.  Divisor values are the actual divisors for
- */
-static bool
-mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
-               struct mdfld_intel_clock_t *best_clock)
-{
-       struct mdfld_intel_clock_t clock;
-       const struct mdfld_limit_t *limit = mdfld_limit(crtc);
-       int err = target;
-
-       memset(best_clock, 0, sizeof(*best_clock));
-
-       for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
-               for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
-                    clock.p1++) {
-                       int this_err;
-
-                       mdfld_clock(refclk, &clock);
-
-                       this_err = abs(clock.dot - target);
-                       if (this_err < err) {
-                               *best_clock = clock;
-                               err = this_err;
-                       }
-               }
-       }
-       return err != target;
-}
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int mdfld_panel_fitter_pipe(struct drm_device *dev)
-{
-       u32 pfit_control;
-
-       pfit_control = REG_READ(PFIT_CONTROL);
-
-       /* See if the panel fitter is in use */
-       if ((pfit_control & PFIT_ENABLE) == 0)
-               return -1;
-       return (pfit_control >> 29) & 3;
-}
-
-static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode,
-                             int x, int y,
-                             struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int pipe = psb_intel_crtc->pipe;
-       int fp_reg = MRST_FPA0;
-       int dpll_reg = MRST_DPLL_A;
-       int dspcntr_reg = DSPACNTR;
-       int pipeconf_reg = PIPEACONF;
-       int htot_reg = HTOTAL_A;
-       int hblank_reg = HBLANK_A;
-       int hsync_reg = HSYNC_A;
-       int vtot_reg = VTOTAL_A;
-       int vblank_reg = VBLANK_A;
-       int vsync_reg = VSYNC_A;
-       int dspsize_reg = DSPASIZE; 
-       int dsppos_reg = DSPAPOS; 
-       int pipesrc_reg = PIPEASRC;
-       u32 *pipeconf = &dev_priv->pipeconf;
-       u32 *dspcntr = &dev_priv->dspcntr;
-       int refclk = 0;
-       int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
-       struct mdfld_intel_clock_t clock;
-       bool ok;
-       u32 dpll = 0, fp = 0;
-       bool is_crt = false, is_lvds = false, is_tv = false;
-       bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct psb_intel_output *psb_intel_output = NULL;
-       uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
-       int timeout = 0;
-
-       dev_dbg(dev->dev, "pipe = 0x%x \n", pipe);
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               fp_reg = FPB0;
-               dpll_reg = DPLL_B;
-               dspcntr_reg = DSPBCNTR;
-               pipeconf_reg = PIPEBCONF;
-               htot_reg = HTOTAL_B;
-               hblank_reg = HBLANK_B;
-               hsync_reg = HSYNC_B;
-               vtot_reg = VTOTAL_B;
-               vblank_reg = VBLANK_B;
-               vsync_reg = VSYNC_B;
-               dspsize_reg = DSPBSIZE; 
-               dsppos_reg = DSPBPOS; 
-               pipesrc_reg = PIPEBSRC;
-               pipeconf = &dev_priv->pipeconf1;
-               dspcntr = &dev_priv->dspcntr1;
-               fp_reg = MDFLD_DPLL_DIV0;
-               dpll_reg = MDFLD_DPLL_B;
-               break;
-       case 2:
-               dpll_reg = MRST_DPLL_A;
-               dspcntr_reg = DSPCCNTR;
-               pipeconf_reg = PIPECCONF;
-               htot_reg = HTOTAL_C;
-               hblank_reg = HBLANK_C;
-               hsync_reg = HSYNC_C;
-               vtot_reg = VTOTAL_C;
-               vblank_reg = VBLANK_C;
-               vsync_reg = VSYNC_C;
-               dspsize_reg = DSPCSIZE; 
-               dsppos_reg = DSPCPOS; 
-               pipesrc_reg = PIPECSRC;
-               pipeconf = &dev_priv->pipeconf2;
-               dspcntr = &dev_priv->dspcntr2;
-               break;
-       default:
-               DRM_ERROR("Illegal Pipe Number. \n");
-               return 0;
-       }
-
-       dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
-                adjusted_mode->hdisplay);
-       dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
-                adjusted_mode->vdisplay);
-       dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
-                adjusted_mode->hsync_start);
-       dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
-                adjusted_mode->hsync_end);
-       dev_dbg(dev->dev, "adjusted_htotal = %d\n",
-                adjusted_mode->htotal);
-       dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
-                adjusted_mode->vsync_start);
-       dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
-                adjusted_mode->vsync_end);
-       dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
-                adjusted_mode->vtotal);
-       dev_dbg(dev->dev, "adjusted_clock = %d\n",
-                adjusted_mode->clock);
-       dev_dbg(dev->dev, "hdisplay = %d\n",
-                mode->hdisplay);
-       dev_dbg(dev->dev, "vdisplay = %d\n",
-                mode->vdisplay);
-
-       if (!gma_power_begin(dev, true))
-               return 0;
-
-       memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
-       memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
-
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-                       
-               encoder = connector->encoder;
-               
-               if(!encoder)
-                       continue;
-
-               if (encoder->crtc != crtc)
-                       continue;
-
-               psb_intel_output = to_psb_intel_output(connector);
-               
-               dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type);
-
-               switch (psb_intel_output->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       is_tv = true;
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       is_crt = true;
-                       break;
-               case INTEL_OUTPUT_MIPI:
-                       is_mipi = true;
-                       break;
-               case INTEL_OUTPUT_MIPI2:
-                       is_mipi2 = true;
-                       break;
-               case INTEL_OUTPUT_HDMI:
-                       is_hdmi = true;
-                       break;
-               }
-       }
-
-       /* Disable the VGA plane that we never use */
-       REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
-       /* Disable the panel fitter if it was on our pipe */
-       if (mdfld_panel_fitter_pipe(dev) == pipe)
-               REG_WRITE(PFIT_CONTROL, 0);
-
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
-       if (pipe == 1) {
-               /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite
-                * width/height and souce image size registers with the adjusted mode for pipe B. */
-
-               /* The defined sprite rectangle must always be completely contained within the displayable
-                * area of the screen image (frame buffer). */
-               REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
-                               | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
-               /* Set the CRTC with encoder mode. */
-               REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
-                                | (mode->crtc_vdisplay - 1));
-       } else {
-               REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
-               REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
-       }
-
-       REG_WRITE(dsppos_reg, 0);
-
-       if (psb_intel_output)
-               drm_connector_property_get_value(&psb_intel_output->base,
-                       dev->mode_config.scaling_mode_property, &scalingType);
-
-       if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
-               /*
-                *      Medfield doesn't have register support for centering so
-                *      we need to mess with the h/vblank and h/vsync start and
-                *      ends to get central
-                */
-               int offsetX = 0, offsetY = 0;
-
-               offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
-               offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
-
-               REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
-                       ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
-                       ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
-                       ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
-               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
-                       ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
-               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
-                       ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
-               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
-                       ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
-       } else {
-               REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
-                       ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
-                       ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
-                       ((adjusted_mode->crtc_hblank_end - 1) << 16));
-               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
-                       ((adjusted_mode->crtc_hsync_end - 1) << 16));
-               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
-                       ((adjusted_mode->crtc_vblank_end - 1) << 16));
-               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
-                       ((adjusted_mode->crtc_vsync_end - 1) << 16));
-       }
-
-       /* Flush the plane changes */
-       {
-               struct drm_crtc_helper_funcs *crtc_funcs =
-                   crtc->helper_private;
-               crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-       }
-
-       /* setup pipeconf */
-       *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
-
-       /* Set up the display plane register */
-       *dspcntr = REG_READ(dspcntr_reg);
-       *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
-       *dspcntr |= DISPLAY_PLANE_ENABLE;
-/* MDFLD_PO_JLIU7      dspcntr |= DISPPLANE_BOTTOM; */
-/* MDFLD_PO_JLIU7      dspcntr |= DISPPLANE_GAMMA_ENABLE; */
-
-       if (is_mipi2)
-       {
-               goto mrst_crtc_mode_set_exit;
-       }
-/* FIXME JLIU7 Add MDFLD HDMI supports */
-/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
-/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
-       clk = adjusted_mode->clock;
-
-       if (is_hdmi) {
-               if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
-               {
-                       refclk = 19200;
-
-                       if (is_mipi || is_mipi2)
-                       {
-                               clk_n = 1, clk_p2 = 8;
-                       } else if (is_hdmi) {
-                               clk_n = 1, clk_p2 = 10;
-                       }
-               } else if (ksel == KSEL_BYPASS_25) { 
-                       refclk = 25000;
-
-                       if (is_mipi || is_mipi2)
-                       {
-                               clk_n = 1, clk_p2 = 8;
-                       } else if (is_hdmi) {
-                               clk_n = 1, clk_p2 = 10;
-                       }
-               } else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
-                       refclk = 83000;
-
-                       if (is_mipi || is_mipi2)
-                       {
-                               clk_n = 4, clk_p2 = 8;
-                       } else if (is_hdmi) {
-                               clk_n = 4, clk_p2 = 10;
-                       }
-               } else if ((ksel == KSEL_BYPASS_83_100) &&
-                          (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
-                       refclk = 100000;
-                       if (is_mipi || is_mipi2)
-                       {
-                               clk_n = 4, clk_p2 = 8;
-                       } else if (is_hdmi) {
-                               clk_n = 4, clk_p2 = 10;
-                       }
-               }
-
-               if (is_mipi)
-                       clk_byte = dev_priv->bpp / 8;
-               else if (is_mipi2)
-                       clk_byte = dev_priv->bpp2 / 8;
-       
-               clk_tmp = clk * clk_n * clk_p2 * clk_byte;
-
-               dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
-               dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
-
-               ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
-
-               if (!ok) {
-                       dev_err(dev->dev, 
-                          "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
-               } else {
-                       m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
-
-                       dev_dbg(dev->dev, "dot clock = %d,"
-                                "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
-                                clock.p1, m_conv);
-               }
-
-               dpll = REG_READ(dpll_reg);
-
-               if (dpll & DPLL_VCO_ENABLE) {
-                       dpll &= ~DPLL_VCO_ENABLE;
-                       REG_WRITE(dpll_reg, dpll);
-                       REG_READ(dpll_reg);
-
-                       /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
-                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                       udelay(500);
-
-                       /* reset M1, N1 & P1 */
-                       REG_WRITE(fp_reg, 0);
-                       dpll &= ~MDFLD_P1_MASK;
-                       REG_WRITE(dpll_reg, dpll);
-                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                       udelay(500);
-               }
-
-               /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
-               if (dpll & MDFLD_PWR_GATE_EN) {
-                       dpll &= ~MDFLD_PWR_GATE_EN;
-                       REG_WRITE(dpll_reg, dpll);
-                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-                       udelay(500);
-               }       
-
-               dpll = 0; 
-
-#if 0 /* FIXME revisit later */
-               if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) {
-                       dpll &= ~MDFLD_INPUT_REF_SEL;   
-               } else if (ksel == KSEL_BYPASS_83_100) { 
-                       dpll |= MDFLD_INPUT_REF_SEL;    
-               }
-#endif /* FIXME revisit later */
-
-               if (is_hdmi)
-                       dpll |= MDFLD_VCO_SEL;  
-
-               fp = (clk_n / 2) << 16;
-               fp |= m_conv; 
-
-               /* compute bitmask from p1 value */
-               dpll |= (1 << (clock.p1 - 2)) << 17;
-
-#if 0 /* 1080p30 & 720p */
-               dpll = 0x00050000;
-               fp = 0x000001be;
-#endif 
-#if 0 /* 480p */
-               dpll = 0x02010000;
-               fp = 0x000000d2;
-#endif 
-       } else {
-#if 0 /*DBI_TPO_480x864*/
-               dpll = 0x00020000;
-               fp = 0x00000156; 
-#endif /* DBI_TPO_480x864 */ /* get from spec. */
-
-               dpll = 0x00800000;
-               fp = 0x000000c1;
-}
-
-       REG_WRITE(fp_reg, fp);
-       REG_WRITE(dpll_reg, dpll);
-       /* FIXME_MDFLD PO - change 500 to 1 after PO */
-       udelay(500);
-
-       dpll |= DPLL_VCO_ENABLE;
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
-
-       /* wait for DSI PLL to lock */
-       while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
-               udelay(150);
-               timeout ++;
-       }
-
-       if (is_mipi)
-               goto mrst_crtc_mode_set_exit;
-
-       dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi);
-
-       REG_WRITE(pipeconf_reg, *pipeconf);
-       REG_READ(pipeconf_reg);
-
-       /* Wait for for the pipe enable to take effect. */
-//FIXME_JLIU7 HDMI     mrstWaitForPipeEnable(dev);
-
-       REG_WRITE(dspcntr_reg, *dspcntr);
-       psb_intel_wait_for_vblank(dev);
-
-mrst_crtc_mode_set_exit:
-
-       gma_power_end(dev);
-
-       return 0;
-}
-
-static void mdfld_crtc_prepare(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void mdfld_crtc_commit(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
-       .dpms = mdfld_crtc_dpms,
-       .mode_fixup = mdfld_crtc_mode_fixup,
-       .mode_set = mdfld_crtc_mode_set,
-       .mode_set_base = mdfld__intel_pipe_set_base,
-       .prepare = mdfld_crtc_prepare,
-       .commit = mdfld_crtc_commit,
-};
diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h
deleted file mode 100644 (file)
index a7ad654..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     Jim Liu <jim.liu@intel.com>
- */
-
-#define MSIC_PCI_DEVICE_ID     0x831
-
-int msic_regsiter_driver(void);
-int msic_unregister_driver(void);
-extern void hpd_notify_um(void);
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
deleted file mode 100644 (file)
index eabf53d..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_dbi_dpu.h"
-
-#include "displays/tpo_cmd.h"
-#include "displays/tpo_vid.h"
-#include "displays/tmd_cmd.h"
-#include "displays/tmd_vid.h"
-#include "displays/pyr_cmd.h"
-#include "displays/pyr_vid.h"
-/* #include "displays/hdmi.h" */
-
-static int mdfld_dual_mipi;
-static int mdfld_hdmi;
-static int mdfld_dpu;
-
-module_param(mdfld_dual_mipi, int, 0600);
-MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration");
-module_param(mdfld_hdmi, int, 0600);
-MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI");
-module_param(mdfld_dpu, int, 0600);
-MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU");
-
-/* For now a single type per device is all we cope with */
-int mdfld_get_panel_type(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       return dev_priv->panel_id;
-}
-
-int mdfld_panel_dpi(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       switch (dev_priv->panel_id) {
-       case TMD_VID:
-       case TPO_VID:
-       case PYR_VID:
-               return true;
-       case TMD_CMD:
-       case TPO_CMD:
-       case PYR_CMD:
-       default:
-               return false;
-       }
-}
-
-static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
-{
-       struct panel_funcs *p_cmd_funcs;
-       struct panel_funcs *p_vid_funcs;
-
-       /* Oh boy ... FIXME */
-       p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
-       if (p_cmd_funcs == NULL)
-               return -ENODEV;
-       p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
-       if (p_vid_funcs == NULL) {
-               kfree(p_cmd_funcs);
-               return -ENODEV;
-       }
-
-       switch (p_type) {
-       case TPO_CMD:
-               tpo_cmd_init(dev, p_cmd_funcs);
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
-               break;
-       case TPO_VID:
-               tpo_vid_init(dev, p_vid_funcs);
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
-               break;
-       case TMD_CMD:
-               /*tmd_cmd_init(dev, p_cmd_funcs); */
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
-               break;
-       case TMD_VID:
-               tmd_vid_init(dev, p_vid_funcs);
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
-               break;
-       case PYR_CMD:
-               pyr_cmd_init(dev, p_cmd_funcs);
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
-               break;
-       case PYR_VID:
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
-               break;
-       case TPO:       /* TPO panel supports both cmd & vid interfaces */
-               tpo_cmd_init(dev, p_cmd_funcs);
-               tpo_vid_init(dev, p_vid_funcs);
-               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs,
-                                     p_vid_funcs);
-               break;
-       case TMD:
-               break;
-       case PYR:
-               break;
-#if 0
-       case HDMI:
-               dev_dbg(dev->dev, "Initializing HDMI");
-               mdfld_hdmi_init(dev, &dev_priv->mode_dev);
-               break;
-#endif
-       default:
-               dev_err(dev->dev, "Unsupported interface %d", p_type);
-               return -ENODEV;
-       }
-       return 0;
-}
-
-int mdfld_output_init(struct drm_device *dev)
-{
-       int type;
-
-       /* MIPI panel 1 */
-       type = mdfld_get_panel_type(dev, 0);
-       dev_info(dev->dev, "panel 1: type is %d\n", type);
-       init_panel(dev, 0, type);
-
-       if (mdfld_dual_mipi) {
-               /* MIPI panel 2 */
-               type = mdfld_get_panel_type(dev, 2);
-               dev_info(dev->dev, "panel 2: type is %d\n", type);
-               init_panel(dev, 2, type);
-       }
-       if (mdfld_hdmi)
-               /* HDMI panel */
-               init_panel(dev, 0, HDMI);
-       return 0;
-}
-
-void mdfld_output_setup(struct drm_device *dev)
-{
-       /* FIXME: this is not the right place for this stuff ! */
-       if (IS_MFLD(dev)) {
-               if (mdfld_dpu)
-                       mdfld_dbi_dpu_init(dev);
-               else
-                       mdfld_dbi_dsr_init(dev);
-       }
-}
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
deleted file mode 100644 (file)
index daf33e7..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef MDFLD_OUTPUT_H
-#define MDFLD_OUTPUT_H
-
-int mdfld_output_init(struct drm_device *dev);
-int mdfld_panel_dpi(struct drm_device *dev);
-int mdfld_get_panel_type(struct drm_device *dev, int pipe);
-void mdfld_disable_crtc (struct drm_device *dev, int pipe);
-
-extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
-extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
-
-extern void mdfld_output_setup(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c
deleted file mode 100644 (file)
index 523f2d8..0000000
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/pyr_cmd.h"
-
-static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev)
-{
-       struct drm_display_mode *mode;
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode) {
-               dev_err(dev->dev, "Out of memory\n");
-               return NULL;
-       }
-
-       dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
-       dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
-       dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
-       dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
-       dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
-       dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
-       dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
-       dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
-       dev_dbg(dev->dev, "clock is %d\n", mode->clock);
-
-       mode->hdisplay = 480;
-       mode->vdisplay = 864;
-       mode->hsync_start = 487;
-       mode->hsync_end = 490;
-       mode->htotal = 499;
-       mode->vsync_start = 874;
-       mode->vsync_end = 878;
-       mode->vtotal = 886;
-       mode->clock = 25777;
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-
-       return mode;
-}
-
-static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
-                               struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev);
-
-       if (fixed_mode) {
-               adjusted_mode->hdisplay = fixed_mode->hdisplay;
-               adjusted_mode->hsync_start = fixed_mode->hsync_start;
-               adjusted_mode->hsync_end = fixed_mode->hsync_end;
-               adjusted_mode->htotal = fixed_mode->htotal;
-               adjusted_mode->vdisplay = fixed_mode->vdisplay;
-               adjusted_mode->vsync_start = fixed_mode->vsync_start;
-               adjusted_mode->vsync_end = fixed_mode->vsync_end;
-               adjusted_mode->vtotal = fixed_mode->vtotal;
-               adjusted_mode->clock = fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-               kfree(fixed_mode);
-       }
-       return true;
-}
-
-static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
-{
-       int ret = 0;
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output =
-                               MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct drm_device *dev = encoder->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 reg_offset = 0;
-       int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
-
-       dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe,
-                       on ? "On" : "Off",
-                       dbi_output->dbi_panel_on ? "True" : "False");
-
-       if (pipe == 2) {
-               if (on)
-                       dev_priv->dual_mipi = true;
-               else
-                       dev_priv->dual_mipi = false;
-
-               reg_offset = MIPIC_REG_OFFSET;
-       } else {
-               if (!on)
-                       dev_priv->dual_mipi = false;
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-
-       if (on) {
-               if (dbi_output->dbi_panel_on)
-                       goto out_err;
-
-               ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
-               if (ret) {
-                       dev_err(dev->dev, "power on error\n");
-                       goto out_err;
-               }
-
-               dbi_output->dbi_panel_on = true;
-
-               if (pipe == 2) {
-                       dev_priv->dbi_panel_on2 = true;
-               } else {
-                       dev_priv->dbi_panel_on = true;
-                       mdfld_enable_te(dev, 0);
-               }
-       } else {
-               if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
-                       goto out_err;
-
-               dbi_output->dbi_panel_on = false;
-               dbi_output->first_boot = false;
-
-               if (pipe == 2) {
-                       dev_priv->dbi_panel_on2 = false;
-                       mdfld_disable_te(dev, 2);
-               } else {
-                       dev_priv->dbi_panel_on = false;
-                       mdfld_disable_te(dev, 0);
-
-                       if (dev_priv->dbi_panel_on2)
-                               mdfld_enable_te(dev, 2);
-               }
-
-               ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
-               if (ret) {
-                       dev_err(dev->dev, "power on error\n");
-                       goto out_err;
-               }
-       }
-
-out_err:
-       gma_power_end(dev);
-
-       if (ret)
-               dev_err(dev->dev, "failed\n");
-}
-
-static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
-                                                               int pipe)
-{
-       struct drm_device *dev = dsi_config->dev;
-       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
-       int lane_count = dsi_config->lane_count;
-       u32 val = 0;
-
-       dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
-
-       /* Un-ready device */
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
-       /* Init dsi adapter before kicking off */
-       REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
-       /* TODO: figure out how to setup these registers */
-       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F);
-       REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
-                                                               0x000a0014);
-       REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
-       REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
-
-       /* Enable all interrupts */
-       REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-       /* Max value: 20 clock cycles of txclkesc */
-       REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
-       /* Min 21 txclkesc, max: ffffh */
-       REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
-       /* Min: 7d0 max: 4e20 */
-       REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
-
-       /* Set up func_prg */
-       val |= lane_count;
-       val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
-       val |= DSI_DBI_COLOR_FORMAT_OPTION2;
-       REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
-       REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
-       REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
-
-       /* De-assert dbi_stall when half of DBI FIFO is empty */
-       /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
-
-       REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-       REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002);
-       REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-       REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder,
-                               struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
-{
-       int ret = 0;
-       struct drm_device *dev = encoder->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dsi_output =
-                                       MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct mdfld_dsi_config *dsi_config =
-                               mdfld_dsi_encoder_get_config(dsi_encoder);
-       struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
-       int pipe = dsi_connector->pipe;
-       u8 param = 0;
-
-       /* Regs */
-       u32 mipi_reg = MIPI;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 reg_offset = 0;
-
-       /* Values */
-       u32 dspcntr_val = dev_priv->dspcntr;
-       u32 pipeconf_val = dev_priv->pipeconf;
-       u32 h_active_area = mode->hdisplay;
-       u32 v_active_area = mode->vdisplay;
-       u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
-                                                       TE_TRIGGER_GPIO_PIN);
-
-       dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
-
-       dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
-       dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
-
-       if (pipe == 2) {
-               mipi_reg = MIPI_C;
-               dspcntr_reg = DSPCCNTR;
-               pipeconf_reg = PIPECCONF;
-
-               reg_offset = MIPIC_REG_OFFSET;
-
-               dspcntr_val = dev_priv->dspcntr2;
-               pipeconf_val = dev_priv->pipeconf2;
-       } else {
-               mipi_val |= 0x2; /* Two lanes for port A and C respectively */
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-       /* Set up pipe related registers */
-       REG_WRITE(mipi_reg, mipi_val);
-       REG_READ(mipi_reg);
-
-       pyr_dsi_controller_dbi_init(dsi_config, pipe);
-
-       msleep(20);
-
-       REG_WRITE(dspcntr_reg, dspcntr_val);
-       REG_READ(dspcntr_reg);
-
-       /* 20ms delay before sending exit_sleep_mode */
-       msleep(20);
-
-       /* Send exit_sleep_mode DCS */
-       ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL,
-                                               0, CMD_DATA_SRC_SYSTEM_MEM);
-       if (ret) {
-               dev_err(dev->dev, "sent exit_sleep_mode faild\n");
-               goto out_err;
-       }
-
-       /*send set_tear_on DCS*/
-       ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
-                                       &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
-       if (ret) {
-               dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
-               goto out_err;
-       }
-
-       /* Do some init stuff */
-       mdfld_dsi_brightness_init(dsi_config, pipe);
-       mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
-                               HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
-       REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
-       REG_READ(pipeconf_reg);
-
-       /* TODO: this looks ugly, try to move it to CRTC mode setting */
-       if (pipe == 2)
-               dev_priv->pipeconf2 |= PIPEACONF_DSR;
-       else
-               dev_priv->pipeconf |= PIPEACONF_DSR;
-
-       dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
-
-       ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
-                               h_active_area - 1, v_active_area - 1);
-       if (ret) {
-               dev_err(dev->dev, "update area failed\n");
-               goto out_err;
-       }
-
-out_err:
-       gma_power_end(dev);
-
-       if (ret)
-               dev_err(dev->dev, "mode set failed\n");
-       else
-               dev_dbg(dev->dev, "mode set done successfully\n");
-}
-
-static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output =
-                                       MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-
-       dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
-       dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
-
-       pyr_dsi_dbi_set_power(encoder, false);
-}
-
-static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output =
-                                       MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_drm_dpu_rect rect;
-
-       pyr_dsi_dbi_set_power(encoder, true);
-
-       dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
-
-       rect.x = rect.y = 0;
-       rect.width = 864;
-       rect.height = 480;
-
-       if (dbi_output->channel_num == 1) {
-               dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
-               /* If DPU enabled report a fullscreen damage */
-               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
-       } else {
-               dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
-               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
-       }
-       dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
-}
-
-static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output =
-                                       MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct drm_device *dev = dbi_output->dev;
-
-       dev_dbg(dev->dev, "%s\n",  (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
-
-       if (mode == DRM_MODE_DPMS_ON)
-               pyr_dsi_dbi_set_power(encoder, true);
-       else
-               pyr_dsi_dbi_set_power(encoder, false);
-}
-
-/*
- * Update the DBI MIPI Panel Frame Buffer.
- */
-static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
-                                                               int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender =
-               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_crtc *crtc = dbi_output->base.base.crtc;
-       struct psb_intel_crtc *psb_crtc = (crtc) ?
-                               to_psb_intel_crtc(crtc) : NULL;
-
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dspsurf_reg = DSPASURF;
-       u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG;
-       u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
-       u32 reg_offset = 0;
-
-       u32 intr_status;
-       u32 fifo_stat_reg_val;
-       u32 dpll_reg_val;
-       u32 dspcntr_reg_val;
-       u32 pipeconf_reg_val;
-
-       /* If mode setting on-going, back off */
-       if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
-               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
-               !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
-               return;
-
-       /*
-        * Look for errors here.  In particular we're checking for whatever
-        * error status might have appeared during the last frame transmit
-        * (memory write).
-        *
-        * Normally, the bits we're testing here would be set infrequently,
-        * if at all.  However, one panel (at least) returns at least one
-        * error bit on most frames.  So we've disabled the kernel message
-        * for now.
-        *
-        * Still clear whatever error bits are set, except don't clear the
-        * ones that would make the Penwell DSI controller reset if we
-        * cleared them.
-        */
-       intr_status = REG_READ(INTR_STAT_REG);
-       if ((intr_status & 0x26FFFFFF) != 0) {
-               /* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */
-               intr_status &= 0x26F3FFFF;
-               REG_WRITE(INTR_STAT_REG, intr_status);
-       }
-
-       if (pipe == 2) {
-               dspcntr_reg = DSPCCNTR;
-               pipeconf_reg = PIPECCONF;
-               dsplinoff_reg = DSPCLINOFF;
-               dspsurf_reg = DSPCSURF;
-
-               hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
-               gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET,
-
-               reg_offset = MIPIC_REG_OFFSET;
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-       fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset);
-       dpll_reg_val = REG_READ(dpll_reg);
-       dspcntr_reg_val = REG_READ(dspcntr_reg);
-       pipeconf_reg_val = REG_READ(pipeconf_reg);
-
-       if (!(fifo_stat_reg_val & (1 << 27)) ||
-               (dpll_reg_val & DPLL_VCO_ENABLE) ||
-               !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) ||
-               !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) {
-               goto update_fb_out0;
-       }
-
-       /* Refresh plane changes */
-       REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
-       REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
-       REG_READ(dspsurf_reg);
-
-       mdfld_dsi_send_dcs(sender,
-                          write_mem_start,
-                          NULL,
-                          0,
-                          CMD_DATA_SRC_PIPE,
-                          MDFLD_DSI_SEND_PACKAGE);
-
-       /*
-        * The idea here is to transmit a Generic Read command after the
-        * Write Memory Start/Continue commands finish.  This asks for
-        * the panel to return an "ACK No Errors," or (if it has errors
-        * to report) an Error Report.  This allows us to monitor the
-        * panel's perception of the health of the DSI.
-        */
-       mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg,
-                               HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-       REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0);
-
-       dbi_output->dsr_fb_update_done = true;
-update_fb_out0:
-       gma_power_end(dev);
-}
-
-/*
- * TODO: will be removed later, should work out display interfaces for power
- */
-void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
-       if (!dsi_config || (pipe != 0 && pipe != 2)) {
-               WARN_ON(1);
-               return;
-       }
-       pyr_dsi_controller_dbi_init(dsi_config, pipe);
-}
-
-static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe,
-                                                       struct panel_info *pi)
-{
-       if (!dev || !pi)
-               return -EINVAL;
-
-       pi->width_mm = PYR_PANEL_WIDTH;
-       pi->height_mm = PYR_PANEL_HEIGHT;
-
-       return 0;
-}
-
-/* PYR DBI encoder helper funcs */
-static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = {
-       .dpms = pyr_dsi_dbi_dpms,
-       .mode_fixup = pyr_dsi_dbi_mode_fixup,
-       .prepare = pyr_dsi_dbi_prepare,
-       .mode_set = pyr_dsi_dbi_mode_set,
-       .commit = pyr_dsi_dbi_commit,
-};
-
-/* PYR DBI encoder funcs */
-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
-       p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
-       p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs;
-       p_funcs->get_config_mode = &pyr_cmd_get_config_mode;
-       p_funcs->update_fb = pyr_dsi_dbi_update_fb;
-       p_funcs->get_panel_info = pyr_cmd_get_panel_info;
-}
diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c
deleted file mode 100644 (file)
index affdc09..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jim Liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- * Gideon Eaton <eaton.
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/tmd_vid.h"
-
-/* FIXME: static ? */
-struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
-{
-       struct drm_display_mode *mode;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
-       bool use_gct = false; /*Disable GCT for now*/
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode) {
-               dev_err(dev->dev, "Out of memory\n");
-               return NULL;
-       }
-
-       if (use_gct) {
-               dev_dbg(dev->dev, "gct find MIPI panel.\n");
-
-               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
-               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
-               mode->hsync_start = mode->hdisplay +
-                               ((ti->hsync_offset_hi << 8) |
-                               ti->hsync_offset_lo);
-               mode->hsync_end = mode->hsync_start +
-                               ((ti->hsync_pulse_width_hi << 8) |
-                               ti->hsync_pulse_width_lo);
-               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
-                                                               ti->hblank_lo);
-               mode->vsync_start = \
-                       mode->vdisplay + ((ti->vsync_offset_hi << 8) |
-                                               ti->vsync_offset_lo);
-               mode->vsync_end = \
-                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
-                                               ti->vsync_pulse_width_lo);
-               mode->vtotal = mode->vdisplay +
-                               ((ti->vblank_hi << 8) | ti->vblank_lo);
-               mode->clock = ti->pixel_clock * 10;
-
-               dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
-               dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
-               dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
-               dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
-               dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
-               dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
-               dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
-               dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
-               dev_dbg(dev->dev, "clock is %d\n", mode->clock);
-       } else {
-               mode->hdisplay = 480;
-               mode->vdisplay = 854;
-               mode->hsync_start = 487;
-               mode->hsync_end = 490;
-               mode->htotal = 499;
-               mode->vsync_start = 861;
-               mode->vsync_end = 865;
-               mode->vtotal = 873;
-               mode->clock = 33264;
-       }
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-
-       return mode;
-}
-
-static int tmd_vid_get_panel_info(struct drm_device *dev,
-                               int pipe,
-                               struct panel_info *pi)
-{
-       if (!dev || !pi)
-               return -EINVAL;
-
-       pi->width_mm = TMD_PANEL_WIDTH;
-       pi->height_mm = TMD_PANEL_HEIGHT;
-
-       return 0;
-}
-
-/*
- *     mdfld_init_TMD_MIPI     -       initialise a TMD interface
- *     @dsi_config: configuration
- *     @pipe: pipe to configure
- *
- *     This function is called only by mrst_dsi_mode_set and
- *     restore_display_registers.  since this function does not
- *     acquire the mutex, it is important that the calling function
- *     does!
- */
-
-
-static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
-                                     int pipe)
-{
-       static u32 tmd_cmd_mcap_off[] = {0x000000b2};
-       static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
-       static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
-       static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
-       static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
-       static u32 tmd_cmd_set_mode[] = {0x000000b3};
-       static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
-       static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
-       static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
-       static u32 tmd_cmd_set_video_mode[] = {0x00000153};
-       /*no auto_bl,need add in furture*/
-       static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
-       static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
-
-       struct mdfld_dsi_pkg_sender *sender
-                       = mdfld_dsi_get_pkg_sender(dsi_config);
-
-       DRM_INFO("Enter mdfld init TMD MIPI display.\n");
-
-       if (!sender) {
-               DRM_ERROR("Cannot get sender\n");
-               return;
-       }
-
-       if (dsi_config->dvr_ic_inited)
-               return;
-
-       msleep(3);
-
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0);
-       mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0);
-       mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0);
-       mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0);
-
-       dsi_config->dvr_ic_inited = 1;
-}
-
-/* TMD DPI encoder helper funcs */
-static const struct drm_encoder_helper_funcs
-                                       mdfld_tpo_dpi_encoder_helper_funcs = {
-       .dpms = mdfld_dsi_dpi_dpms,
-       .mode_fixup = mdfld_dsi_dpi_mode_fixup,
-       .prepare = mdfld_dsi_dpi_prepare,
-       .mode_set = mdfld_dsi_dpi_mode_set,
-       .commit = mdfld_dsi_dpi_commit,
-};
-
-/* TMD DPI encoder funcs */
-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
-       if (!dev || !p_funcs) {
-               dev_err(dev->dev, "Invalid parameters\n");
-               return;
-       }
-
-       p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
-       p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
-       p_funcs->get_config_mode = &tmd_vid_get_config_mode;
-       p_funcs->update_fb = NULL;
-       p_funcs->get_panel_info = tmd_vid_get_panel_info;
-       p_funcs->reset = mdfld_dsi_panel_reset;
-       p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init;
-}
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c
deleted file mode 100644 (file)
index c7f7c9c..0000000
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Copyright (c)  2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/tpo_cmd.h"
-
-static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev)
-{
-       struct drm_display_mode *mode;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
-       bool use_gct = false;
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode)
-               return NULL;
-
-       if (use_gct) {
-               dev_dbg(dev->dev, "gct find MIPI panel.\n");
-
-               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
-               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
-               mode->hsync_start = mode->hdisplay + \
-                               ((ti->hsync_offset_hi << 8) | \
-                               ti->hsync_offset_lo);
-               mode->hsync_end = mode->hsync_start + \
-                               ((ti->hsync_pulse_width_hi << 8) | \
-                               ti->hsync_pulse_width_lo);
-               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
-                                                               ti->hblank_lo);
-               mode->vsync_start = \
-                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
-                                               ti->vsync_offset_lo);
-               mode->vsync_end = \
-                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
-                                               ti->vsync_pulse_width_lo);
-               mode->vtotal = mode->vdisplay + \
-                               ((ti->vblank_hi << 8) | ti->vblank_lo);
-               mode->clock = ti->pixel_clock * 10;
-
-               dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
-               dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
-               dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
-               dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
-               dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
-               dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
-               dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
-               dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
-               dev_dbg(dev->dev, "clock is %d\n", mode->clock);
-       } else {
-               mode->hdisplay = 864;
-               mode->vdisplay = 480;
-               mode->hsync_start = 872;
-               mode->hsync_end = 876;
-               mode->htotal = 884;
-               mode->vsync_start = 482;
-               mode->vsync_end = 494;
-               mode->vtotal = 486;
-               mode->clock = 25777;
-       }
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-
-       return mode;
-}
-
-static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
-                                    struct drm_display_mode *mode,
-                                    struct drm_display_mode *adjusted_mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev);
-
-       if (fixed_mode) {
-               adjusted_mode->hdisplay = fixed_mode->hdisplay;
-               adjusted_mode->hsync_start = fixed_mode->hsync_start;
-               adjusted_mode->hsync_end = fixed_mode->hsync_end;
-               adjusted_mode->htotal = fixed_mode->htotal;
-               adjusted_mode->vdisplay = fixed_mode->vdisplay;
-               adjusted_mode->vsync_start = fixed_mode->vsync_start;
-               adjusted_mode->vsync_end = fixed_mode->vsync_end;
-               adjusted_mode->vtotal = fixed_mode->vtotal;
-               adjusted_mode->clock = fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-               kfree(fixed_mode);
-       }
-       return true;
-}
-
-static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
-{
-       int ret = 0;
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output =
-                               MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct mdfld_dsi_config *dsi_config =
-               mdfld_dsi_encoder_get_config(dsi_encoder);
-       struct mdfld_dsi_pkg_sender *sender =
-               mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
-       struct drm_device *dev = encoder->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 reg_offset = 0;
-       int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
-       u32 data = 0;
-
-       dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n",
-                       pipe, on ? "On" : "Off",
-                       dbi_output->dbi_panel_on ? "True" : "False");
-
-       if (pipe == 2) {
-               if (on)
-                       dev_priv->dual_mipi = true;
-               else
-                       dev_priv->dual_mipi = false;
-               reg_offset = MIPIC_REG_OFFSET;
-       } else {
-               if (!on)
-                       dev_priv->dual_mipi = false;
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-       if (on) {
-               if (dbi_output->dbi_panel_on)
-                       goto out_err;
-
-               ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
-               if (ret) {
-                       dev_err(dev->dev, "power on error\n");
-                       goto out_err;
-               }
-
-               dbi_output->dbi_panel_on = true;
-
-               if (pipe == 2)
-                       dev_priv->dbi_panel_on2 = true;
-               else
-                       dev_priv->dbi_panel_on = true;
-               mdfld_enable_te(dev, pipe);
-       } else {
-               if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
-                       goto out_err;
-
-               dbi_output->dbi_panel_on = false;
-               dbi_output->first_boot = false;
-
-               if (pipe == 2)
-                       dev_priv->dbi_panel_on2 = false;
-               else
-                       dev_priv->dbi_panel_on = false;
-
-               mdfld_disable_te(dev, pipe);
-
-               ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
-               if (ret) {
-                       dev_err(dev->dev, "power on error\n");
-                       goto out_err;
-               }
-       }
-
-       /*
-        * FIXME: this is a WA for TPO panel crash on DPMS on & off around
-        * 83 times. the root cause of this issue is that Booster in
-        * drvIC crashed. Add this WA so that we can resume the driver IC
-        * once we found that booster has a fault
-        */
-       mdfld_dsi_get_power_mode(dsi_config,
-                               &data,
-                               MDFLD_DSI_HS_TRANSMISSION);
-
-       if (on && data && !(data & (1 << 7))) {
-               /* Soft reset */
-               mdfld_dsi_send_dcs(sender,
-                                  DCS_SOFT_RESET,
-                                  NULL,
-                                  0,
-                                  CMD_DATA_SRC_PIPE,
-                                  MDFLD_DSI_SEND_PACKAGE);
-
-               /* Init drvIC */
-               if (dbi_output->p_funcs->drv_ic_init)
-                       dbi_output->p_funcs->drv_ic_init(dsi_config,
-                                                        pipe);
-       }
-out_err:
-       gma_power_end(dev);
-       if (ret)
-               dev_err(dev->dev, "failed\n");
-}
-
-
-static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
-                                  struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted_mode)
-{
-       int ret = 0;
-       struct drm_device *dev = encoder->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dsi_output =
-                                       MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct mdfld_dsi_config *dsi_config =
-                               mdfld_dsi_encoder_get_config(dsi_encoder);
-       struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
-       int pipe = dsi_connector->pipe;
-       u8 param = 0;
-
-       /* Regs */
-       u32 mipi_reg = MIPI;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 reg_offset = 0;
-
-       /* Values */
-       u32 dspcntr_val = dev_priv->dspcntr;
-       u32 pipeconf_val = dev_priv->pipeconf;
-       u32 h_active_area = mode->hdisplay;
-       u32 v_active_area = mode->vdisplay;
-       u32 mipi_val;
-
-       mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
-                                               TE_TRIGGER_GPIO_PIN);
-
-       dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
-
-       dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
-       dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
-
-       if (pipe == 2) {
-               mipi_reg = MIPI_C;
-               dspcntr_reg = DSPCCNTR;
-               pipeconf_reg = PIPECCONF;
-
-               reg_offset = MIPIC_REG_OFFSET;
-
-               dspcntr_val = dev_priv->dspcntr2;
-               pipeconf_val = dev_priv->pipeconf2;
-       } else {
-               mipi_val |= 0x2; /*two lanes for port A and C respectively*/
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-       REG_WRITE(dspcntr_reg, dspcntr_val);
-       REG_READ(dspcntr_reg);
-
-       /* 20ms delay before sending exit_sleep_mode */
-       msleep(20);
-
-       /* Send exit_sleep_mode DCS */
-       ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE,
-                                       NULL, 0, CMD_DATA_SRC_SYSTEM_MEM);
-       if (ret) {
-               dev_err(dev->dev, "sent exit_sleep_mode faild\n");
-               goto out_err;
-       }
-
-       /* Send set_tear_on DCS */
-       ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON,
-                                       &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
-       if (ret) {
-               dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
-               goto out_err;
-       }
-
-       /* Do some init stuff */
-       REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
-       REG_READ(pipeconf_reg);
-
-       /* TODO: this looks ugly, try to move it to CRTC mode setting*/
-       if (pipe == 2)
-               dev_priv->pipeconf2 |= PIPEACONF_DSR;
-       else
-               dev_priv->pipeconf |= PIPEACONF_DSR;
-
-       dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
-
-       ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
-                               h_active_area - 1, v_active_area - 1);
-       if (ret) {
-               dev_err(dev->dev, "update area failed\n");
-               goto out_err;
-       }
-
-out_err:
-       gma_power_end(dev);
-
-       if (ret)
-               dev_err(dev->dev, "mode set failed\n");
-}
-
-static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output
-                               = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-
-       dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
-       dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
-
-       mdfld_dsi_dbi_set_power(encoder, false);
-}
-
-static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output =
-                                       MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_drm_dpu_rect rect;
-
-       mdfld_dsi_dbi_set_power(encoder, true);
-       dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
-
-       rect.x = rect.y = 0;
-       rect.width = 864;
-       rect.height = 480;
-
-       if (dbi_output->channel_num == 1) {
-               dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
-               /*if dpu enabled report a fullscreen damage*/
-               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
-       } else {
-               dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
-               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
-       }
-       dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
-}
-
-static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
-       struct mdfld_dsi_dbi_output *dbi_output
-                               = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       static bool bdispoff;
-
-       dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
-
-       if (mode == DRM_MODE_DPMS_ON) {
-               /*
-                * FIXME: in case I am wrong!
-                * we don't need to exit dsr here to wake up plane/pipe/pll
-                * if everything goes right, hw_begin will resume them all
-                * during set_power.
-                */
-               if (bdispoff /* FIXME && gbgfxsuspended */) {
-                       mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
-                       bdispoff = false;
-                       dev_priv->dispstatus = true;
-               }
-
-               mdfld_dsi_dbi_set_power(encoder, true);
-               /* FIXME if (gbgfxsuspended)
-                       gbgfxsuspended = false; */
-       } else {
-               /*
-                * I am not sure whether this is the perfect place to
-                * turn rpm on since we still have a lot of CRTC turnning
-                * on work to do.
-                */
-               bdispoff = true;
-               dev_priv->dispstatus = false;
-               mdfld_dsi_dbi_set_power(encoder, false);
-       }
-}
-
-
-/*
- * Update the DBI MIPI Panel Frame Buffer.
- */
-static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
-                                                               int pipe)
-{
-       struct mdfld_dsi_pkg_sender *sender =
-               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
-       struct drm_device *dev = dbi_output->dev;
-       struct drm_crtc *crtc = dbi_output->base.base.crtc;
-       struct psb_intel_crtc *psb_crtc = (crtc) ?
-                                       to_psb_intel_crtc(crtc) : NULL;
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dspsurf_reg = DSPASURF;
-       u32 reg_offset = 0;
-
-       /* If mode setting on-going, back off */
-       if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
-               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
-               !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
-               return;
-
-       if (pipe == 2) {
-               dspcntr_reg = DSPCCNTR;
-               pipeconf_reg = PIPECCONF;
-               dsplinoff_reg = DSPCLINOFF;
-               dspsurf_reg = DSPCSURF;
-               reg_offset = MIPIC_REG_OFFSET;
-       }
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "hw begin failed\n");
-               return;
-       }
-
-       /* Check DBI FIFO status */
-       if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
-          !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
-          !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
-               goto update_fb_out0;
-
-       /* Refresh plane changes */
-       REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
-       REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
-       REG_READ(dspsurf_reg);
-
-       mdfld_dsi_send_dcs(sender,
-                          DCS_WRITE_MEM_START,
-                          NULL,
-                          0,
-                          CMD_DATA_SRC_PIPE,
-                          MDFLD_DSI_SEND_PACKAGE);
-
-       dbi_output->dsr_fb_update_done = true;
-update_fb_out0:
-       gma_power_end(dev);
-}
-
-static int tpo_cmd_get_panel_info(struct drm_device *dev,
-                               int pipe,
-                               struct panel_info *pi)
-{
-       if (!dev || !pi)
-               return -EINVAL;
-
-       pi->width_mm = TPO_PANEL_WIDTH;
-       pi->height_mm = TPO_PANEL_HEIGHT;
-
-       return 0;
-}
-
-
-/* TPO DBI encoder helper funcs */
-static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
-       .dpms = mdfld_dsi_dbi_dpms,
-       .mode_fixup = mdfld_dsi_dbi_mode_fixup,
-       .prepare = mdfld_dsi_dbi_prepare,
-       .mode_set = mdfld_dsi_dbi_mode_set,
-       .commit = mdfld_dsi_dbi_commit,
-};
-
-/* TPO DBI encoder funcs */
-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
-       p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
-       p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
-       p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
-       p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
-       p_funcs->get_panel_info = tpo_cmd_get_panel_info;
-       p_funcs->reset = mdfld_dsi_panel_reset;
-       p_funcs->drv_ic_init = mdfld_dsi_brightness_init;
-}
diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c
deleted file mode 100644 (file)
index 9549017..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/tpo_vid.h"
-
-static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
-{
-       struct drm_display_mode *mode;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
-       bool use_gct = false;
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode) {
-               dev_err(dev->dev, "out of memory\n");
-               return NULL;
-       }
-
-       if (use_gct) {
-               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
-               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
-               mode->hsync_start = mode->hdisplay + \
-                               ((ti->hsync_offset_hi << 8) | \
-                               ti->hsync_offset_lo);
-               mode->hsync_end = mode->hsync_start + \
-                               ((ti->hsync_pulse_width_hi << 8) | \
-                               ti->hsync_pulse_width_lo);
-               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
-                                                               ti->hblank_lo);
-               mode->vsync_start = \
-                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
-                                               ti->vsync_offset_lo);
-               mode->vsync_end = \
-                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
-                                               ti->vsync_pulse_width_lo);
-               mode->vtotal = mode->vdisplay + \
-                               ((ti->vblank_hi << 8) | ti->vblank_lo);
-               mode->clock = ti->pixel_clock * 10;
-
-               dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
-               dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
-               dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
-               dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
-               dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
-               dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
-               dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
-               dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
-               dev_dbg(dev->dev, "clock is %d\n", mode->clock);
-       } else {
-               mode->hdisplay = 864;
-               mode->vdisplay = 480;
-               mode->hsync_start = 873;
-               mode->hsync_end = 876;
-               mode->htotal = 887;
-               mode->vsync_start = 487;
-               mode->vsync_end = 490;
-               mode->vtotal = 499;
-               mode->clock = 33264;
-       }
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-
-       return mode;
-}
-
-static int tpo_vid_get_panel_info(struct drm_device *dev,
-                               int pipe,
-                               struct panel_info *pi)
-{
-       if (!dev || !pi)
-               return -EINVAL;
-
-       pi->width_mm = TPO_PANEL_WIDTH;
-       pi->height_mm = TPO_PANEL_HEIGHT;
-
-       return 0;
-}
-
-/*TPO DPI encoder helper funcs*/
-static const struct drm_encoder_helper_funcs
-                                       mdfld_tpo_dpi_encoder_helper_funcs = {
-       .dpms = mdfld_dsi_dpi_dpms,
-       .mode_fixup = mdfld_dsi_dpi_mode_fixup,
-       .prepare = mdfld_dsi_dpi_prepare,
-       .mode_set = mdfld_dsi_dpi_mode_set,
-       .commit = mdfld_dsi_dpi_commit,
-};
-
-/*TPO DPI encoder funcs*/
-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
-       if (!dev || !p_funcs) {
-               dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n");
-               return;
-       }
-
-       p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
-       p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
-       p_funcs->get_config_mode = &tpo_vid_get_config_mode;
-       p_funcs->update_fb = NULL;
-       p_funcs->get_panel_info = tpo_vid_get_panel_info;
-}
diff --git a/drivers/staging/gma500/medfield.h b/drivers/staging/gma500/medfield.h
deleted file mode 100644 (file)
index 09e9687..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright Â© 2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/* Medfield DSI controller registers */
-
-#define MIPIA_DEVICE_READY_REG                         0xb000
-#define MIPIA_INTR_STAT_REG                            0xb004
-#define MIPIA_INTR_EN_REG                              0xb008
-#define MIPIA_DSI_FUNC_PRG_REG                         0xb00c
-#define MIPIA_HS_TX_TIMEOUT_REG                                0xb010
-#define MIPIA_LP_RX_TIMEOUT_REG                                0xb014
-#define MIPIA_TURN_AROUND_TIMEOUT_REG                  0xb018
-#define MIPIA_DEVICE_RESET_TIMER_REG                   0xb01c
-#define MIPIA_DPI_RESOLUTION_REG                       0xb020
-#define MIPIA_DBI_FIFO_THROTTLE_REG                    0xb024
-#define MIPIA_HSYNC_COUNT_REG                          0xb028
-#define MIPIA_HBP_COUNT_REG                            0xb02c
-#define MIPIA_HFP_COUNT_REG                            0xb030
-#define MIPIA_HACTIVE_COUNT_REG                                0xb034
-#define MIPIA_VSYNC_COUNT_REG                          0xb038
-#define MIPIA_VBP_COUNT_REG                            0xb03c
-#define MIPIA_VFP_COUNT_REG                            0xb040
-#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG                        0xb044
-#define MIPIA_DPI_CONTROL_REG                          0xb048
-#define MIPIA_DPI_DATA_REG                             0xb04c
-#define MIPIA_INIT_COUNT_REG                           0xb050
-#define MIPIA_MAX_RETURN_PACK_SIZE_REG                 0xb054
-#define MIPIA_VIDEO_MODE_FORMAT_REG                    0xb058
-#define MIPIA_EOT_DISABLE_REG                          0xb05c
-#define MIPIA_LP_BYTECLK_REG                           0xb060
-#define MIPIA_LP_GEN_DATA_REG                          0xb064
-#define MIPIA_HS_GEN_DATA_REG                          0xb068
-#define MIPIA_LP_GEN_CTRL_REG                          0xb06c
-#define MIPIA_HS_GEN_CTRL_REG                          0xb070
-#define MIPIA_GEN_FIFO_STAT_REG                                0xb074
-#define MIPIA_HS_LS_DBI_ENABLE_REG                     0xb078
-#define MIPIA_DPHY_PARAM_REG                           0xb080
-#define MIPIA_DBI_BW_CTRL_REG                          0xb084
-#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG             0xb088
-
-#define DSI_DEVICE_READY                               (0x1)
-#define DSI_POWER_STATE_ULPS_ENTER                     (0x2 << 1)
-#define DSI_POWER_STATE_ULPS_EXIT                      (0x1 << 1)
-#define DSI_POWER_STATE_ULPS_OFFSET                    (0x1)
-
-
-#define DSI_ONE_DATA_LANE                              (0x1)
-#define DSI_TWO_DATA_LANE                              (0x2)
-#define DSI_THREE_DATA_LANE                            (0X3)
-#define DSI_FOUR_DATA_LANE                             (0x4)
-#define DSI_DPI_VIRT_CHANNEL_OFFSET                    (0x3)
-#define DSI_DBI_VIRT_CHANNEL_OFFSET                    (0x5)
-#define DSI_DPI_COLOR_FORMAT_RGB565                    (0x01 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB666                    (0x02 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK             (0x03 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB888                    (0x04 << 7)
-#define DSI_DBI_COLOR_FORMAT_OPTION2                   (0x05 << 13)
-
-#define DSI_INTR_STATE_RXSOTERROR                      1
-
-#define DSI_INTR_STATE_SPL_PKG_SENT                    (1 << 30)
-#define DSI_INTR_STATE_TE                              (1 << 31)
-
-#define DSI_HS_TX_TIMEOUT_MASK                         (0xffffff)
-
-#define DSI_LP_RX_TIMEOUT_MASK                         (0xffffff)
-
-#define DSI_TURN_AROUND_TIMEOUT_MASK                   (0x3f)
-
-#define DSI_RESET_TIMER_MASK                           (0xffff)
-
-#define DSI_DBI_FIFO_WM_HALF                           (0x0)
-#define DSI_DBI_FIFO_WM_QUARTER                                (0x1)
-#define DSI_DBI_FIFO_WM_LOW                            (0x2)
-
-#define DSI_DPI_TIMING_MASK                            (0xffff)
-
-#define DSI_INIT_TIMER_MASK                            (0xffff)
-
-#define DSI_DBI_RETURN_PACK_SIZE_MASK                  (0x3ff)
-
-#define DSI_LP_BYTECLK_MASK                            (0x0ffff)
-
-#define DSI_HS_CTRL_GEN_SHORT_W0                       (0x03)
-#define DSI_HS_CTRL_GEN_SHORT_W1                       (0x13)
-#define DSI_HS_CTRL_GEN_SHORT_W2                       (0x23)
-#define DSI_HS_CTRL_GEN_R0                             (0x04)
-#define DSI_HS_CTRL_GEN_R1                             (0x14)
-#define DSI_HS_CTRL_GEN_R2                             (0x24)
-#define DSI_HS_CTRL_GEN_LONG_W                         (0x29)
-#define DSI_HS_CTRL_MCS_SHORT_W0                       (0x05)
-#define DSI_HS_CTRL_MCS_SHORT_W1                       (0x15)
-#define DSI_HS_CTRL_MCS_R0                             (0x06)
-#define DSI_HS_CTRL_MCS_LONG_W                         (0x39)
-#define DSI_HS_CTRL_VC_OFFSET                          (0x06)
-#define DSI_HS_CTRL_WC_OFFSET                          (0x08)
-
-#define        DSI_FIFO_GEN_HS_DATA_FULL                       (1 << 0)
-#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY                        (1 << 1)
-#define DSI_FIFO_GEN_HS_DATA_EMPTY                     (1 << 2)
-#define DSI_FIFO_GEN_LP_DATA_FULL                      (1 << 8)
-#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY                        (1 << 9)
-#define DSI_FIFO_GEN_LP_DATA_EMPTY                     (1 << 10)
-#define DSI_FIFO_GEN_HS_CTRL_FULL                      (1 << 16)
-#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY                        (1 << 17)
-#define DSI_FIFO_GEN_HS_CTRL_EMPTY                     (1 << 18)
-#define DSI_FIFO_GEN_LP_CTRL_FULL                      (1 << 24)
-#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY                        (1 << 25)
-#define DSI_FIFO_GEN_LP_CTRL_EMPTY                     (1 << 26)
-#define DSI_FIFO_DBI_EMPTY                             (1 << 27)
-#define DSI_FIFO_DPI_EMPTY                             (1 << 28)
-
-#define DSI_DBI_HS_LP_SWITCH_MASK                      (0x1)
-
-#define DSI_HS_LP_SWITCH_COUNTER_OFFSET                        (0x0)
-#define DSI_LP_HS_SWITCH_COUNTER_OFFSET                        (0x16)
-
-#define DSI_DPI_CTRL_HS_SHUTDOWN                       (0x00000001)
-#define DSI_DPI_CTRL_HS_TURN_ON                                (0x00000002)
-
-/* Medfield DSI adapter registers */
-#define MIPIA_CONTROL_REG                              0xb104
-#define MIPIA_DATA_ADD_REG                             0xb108
-#define MIPIA_DATA_LEN_REG                             0xb10c
-#define MIPIA_CMD_ADD_REG                              0xb110
-#define MIPIA_CMD_LEN_REG                              0xb114
-
-/*dsi power modes*/
-#define DSI_POWER_MODE_DISPLAY_ON      (1 << 2)
-#define DSI_POWER_MODE_NORMAL_ON       (1 << 3)
-#define DSI_POWER_MODE_SLEEP_OUT       (1 << 4)
-#define DSI_POWER_MODE_PARTIAL_ON      (1 << 5)
-#define DSI_POWER_MODE_IDLE_ON         (1 << 6)
-
-enum {
-       MDFLD_DSI_ENCODER_DBI = 0,
-       MDFLD_DSI_ENCODER_DPI,
-};
-
-enum {
-       MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
-       MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
-       MDFLD_DSI_VIDEO_BURST_MODE = 3,
-};
-
-#define DSI_DPI_COMPLETE_LAST_LINE                     (1 << 2)
-#define DSI_DPI_DISABLE_BTA                            (1 << 3)
-/* Panel types */
-enum {
-       TPO_CMD,
-       TPO_VID,
-       TMD_CMD,
-       TMD_VID,
-       PYR_CMD,
-       PYR_VID,
-       TPO,
-       TMD,
-       PYR,
-       HDMI,
-       GCT_DETECT
-};
-
-/* Junk that belongs elsewhere */
-#define TPO_PANEL_WIDTH                84
-#define TPO_PANEL_HEIGHT       46
-#define TMD_PANEL_WIDTH                39
-#define TMD_PANEL_HEIGHT       71
-#define PYR_PANEL_WIDTH                53
-#define PYR_PANEL_HEIGHT       95
-
-/* Panel interface */
-struct panel_info {
-       u32 width_mm;
-       u32 height_mm;
-};
-
-struct mdfld_dsi_dbi_output;
-
-struct mdfld_dsi_connector_state {
-       u32 mipi_ctrl_reg;
-};
-
-struct mdfld_dsi_encoder_state {
-
-};
-
-struct mdfld_dsi_connector {
-       /*
-        * This is ugly, but I have to use connector in it! :-(
-        * FIXME: use drm_connector instead.
-        */
-       struct psb_intel_output base;
-
-       int pipe;
-       void *private;
-       void *pkg_sender;
-
-       /* Connection status */
-       enum drm_connector_status status;
-};
-
-struct mdfld_dsi_encoder {
-       struct drm_encoder base;
-       void *private;
-};
-
-/*
- * DSI config, consists of one DSI connector, two DSI encoders.
- * DRM will pick up on DSI encoder basing on differents configs.
- */
-struct mdfld_dsi_config {
-       struct drm_device *dev;
-       struct drm_display_mode *fixed_mode;
-       struct drm_display_mode *mode;
-
-       struct mdfld_dsi_connector *connector;
-       struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER];
-       struct mdfld_dsi_encoder *encoder;
-
-       int changed;
-
-       int bpp;
-       int type;
-       int lane_count;
-       /*Virtual channel number for this encoder*/
-       int channel_num;
-       /*video mode configure*/
-       int video_mode;
-
-       int dvr_ic_inited;
-};
-
-#define MDFLD_DSI_CONNECTOR(psb_output) \
-               (container_of(psb_output, struct mdfld_dsi_connector, base))
-
-#define MDFLD_DSI_ENCODER(encoder) \
-               (container_of(encoder, struct mdfld_dsi_encoder, base))
-
-struct panel_funcs {
-       const struct drm_encoder_funcs *encoder_funcs;
-       const struct drm_encoder_helper_funcs *encoder_helper_funcs;
-       struct drm_display_mode *(*get_config_mode) (struct drm_device *);
-       void (*update_fb) (struct mdfld_dsi_dbi_output *, int);
-       int (*get_panel_info) (struct drm_device *, int, struct panel_info *);
-       int (*reset)(int pipe);
-       void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
-};
-
diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c
deleted file mode 100644 (file)
index ee3c036..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-/* TODO
- * - Split functions by vbt type
- * - Make them all take drm_device
- * - Check ioremap failures
- */
-
-#include <linux/moduleparam.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "mid_bios.h"
-#include "mdfld_output.h"
-
-static int panel_id = GCT_DETECT;
-module_param_named(panel_id, panel_id, int, 0600);
-MODULE_PARM_DESC(panel_id, "Panel Identifier");
-
-
-static void mid_get_fuse_settings(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       uint32_t fuse_value = 0;
-       uint32_t fuse_value_tmp = 0;
-
-#define FB_REG06 0xD0810600
-#define FB_MIPI_DISABLE  (1 << 11)
-#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
-#define FB_SKU_MASK  0x7000
-#define FB_SKU_SHIFT 12
-#define FB_SKU_100 0
-#define FB_SKU_100L 1
-#define FB_SKU_83 2
-       pci_write_config_dword(pci_root, 0xD0, FB_REG06);
-       pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-       /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
-       if (IS_MRST(dev))
-               dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
-
-       DRM_INFO("internal display is %s\n",
-                dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
-
-        /* Prevent runtime suspend at start*/
-        if (dev_priv->iLVDS_enable) {
-               dev_priv->is_lvds_on = true;
-               dev_priv->is_mipi_on = false;
-       } else {
-               dev_priv->is_mipi_on = true;
-               dev_priv->is_lvds_on = false;
-       }
-
-       dev_priv->video_device_fuse = fuse_value;
-
-       pci_write_config_dword(pci_root, 0xD0, FB_REG09);
-       pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-       dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
-       fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
-
-       dev_priv->fuse_reg_value = fuse_value;
-
-       switch (fuse_value_tmp) {
-       case FB_SKU_100:
-               dev_priv->core_freq = 200;
-               break;
-       case FB_SKU_100L:
-               dev_priv->core_freq = 100;
-               break;
-       case FB_SKU_83:
-               dev_priv->core_freq = 166;
-               break;
-       default:
-               dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
-                                                               fuse_value_tmp);
-               dev_priv->core_freq = 0;
-       }
-       dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
-       pci_dev_put(pci_root);
-}
-
-/*
- *     Get the revison ID, B0:D2:F0;0x08
- */
-static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
-{
-       uint32_t platform_rev_id = 0;
-       struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-       pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
-       dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
-       pci_dev_put(pci_gfx_root);
-       dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
-                                       dev_priv->platform_rev_id);
-}
-
-static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
-{
-       struct drm_device *dev = dev_priv->dev;
-       struct mrst_vbt *vbt = &dev_priv->vbt_data;
-       u32 addr;
-       u16 new_size;
-       u8 *vbt_virtual;
-       u8 bpi;
-       u8 number_desc = 0;
-       struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
-       struct gct_r10_timing_info ti;
-       void *pGCT;
-       struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-       /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
-       pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
-       pci_dev_put(pci_gfx_root);
-
-       dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
-
-       /* check for platform config address == 0. */
-       /* this means fw doesn't support vbt */
-
-       if (addr == 0) {
-               vbt->size = 0;
-               return;
-       }
-
-       /* get the virtual address of the vbt */
-       vbt_virtual = ioremap(addr, sizeof(*vbt));
-
-       memcpy(vbt, vbt_virtual, sizeof(*vbt));
-       iounmap(vbt_virtual); /* Free virtual address space */
-
-       dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
-
-       switch (vbt->revision) {
-       case 0:
-               vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
-                                       vbt->size - sizeof(*vbt) + 4);
-               pGCT = vbt->mrst_gct;
-               bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
-               dev_priv->gct_data.bpi = bpi;
-               dev_priv->gct_data.pt =
-                       ((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
-               memcpy(&dev_priv->gct_data.DTD,
-                       &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
-                               sizeof(struct mrst_timing_info));
-               dev_priv->gct_data.Panel_Port_Control =
-                 ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-                       ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-               break;
-       case 1:
-               vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
-                                       vbt->size - sizeof(*vbt) + 4);
-               pGCT = vbt->mrst_gct;
-               bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
-               dev_priv->gct_data.bpi = bpi;
-               dev_priv->gct_data.pt =
-                       ((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
-               memcpy(&dev_priv->gct_data.DTD,
-                       &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
-                               sizeof(struct mrst_timing_info));
-               dev_priv->gct_data.Panel_Port_Control =
-                 ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-                       ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-               break;
-       case 0x10:
-               /*header definition changed from rev 01 (v2) to rev 10h. */
-               /*so, some values have changed location*/
-               new_size = vbt->checksum; /*checksum contains lo size byte*/
-               /*LSB of mrst_gct contains hi size byte*/
-               new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
-
-               vbt->checksum = vbt->size; /*size contains the checksum*/
-               if (new_size > 0xff)
-                       vbt->size = 0xff; /*restrict size to 255*/
-               else
-                       vbt->size = new_size;
-
-               /* number of descriptors defined in the GCT */
-               number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
-               bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
-               vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
-                               GCT_R10_DISPLAY_DESC_SIZE * number_desc);
-               pGCT = vbt->mrst_gct;
-               pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
-               dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
-
-               /*copy the GCT display timings into a temp structure*/
-               memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
-
-               /*now copy the temp struct into the dev_priv->gct_data*/
-               dp_ti->pixel_clock = ti.pixel_clock;
-               dp_ti->hactive_hi = ti.hactive_hi;
-               dp_ti->hactive_lo = ti.hactive_lo;
-               dp_ti->hblank_hi = ti.hblank_hi;
-               dp_ti->hblank_lo = ti.hblank_lo;
-               dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
-               dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
-               dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
-               dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
-               dp_ti->vactive_hi = ti.vactive_hi;
-               dp_ti->vactive_lo = ti.vactive_lo;
-               dp_ti->vblank_hi = ti.vblank_hi;
-               dp_ti->vblank_lo = ti.vblank_lo;
-               dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
-               dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
-               dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
-               dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
-
-               /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-                                                       *((u8 *)pGCT + 0x0d);
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
-                                               (*((u8 *)pGCT + 0x0e)) << 8;
-               break;
-       default:
-               dev_err(dev->dev, "Unknown revision of GCT!\n");
-               vbt->size = 0;
-       }
-       if (IS_MFLD(dev_priv->dev)) {
-               if (panel_id == GCT_DETECT) {
-                       if (dev_priv->gct_data.bpi == 2) {
-                               dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
-                               dev_priv->panel_id = PYR_CMD;
-                               panel_id = PYR_CMD;
-                       } else if (dev_priv->gct_data.bpi == 0) {
-                               dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
-                               dev_priv->panel_id = TMD_VID;
-                               panel_id = TMD_VID;
-                       } else {
-                               dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
-                               dev_priv->panel_id = TPO_CMD;
-                               panel_id = TPO_CMD;
-                       }
-               } else {
-                       dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
-                       dev_priv->panel_id = panel_id;
-               }
-       }
-}
-
-int mid_chip_setup(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       mid_get_fuse_settings(dev);
-       mid_get_vbt_data(dev_priv);
-       mid_get_pci_revID(dev_priv);
-       return 0;
-}
diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h
deleted file mode 100644 (file)
index 00e7d56..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-extern int mid_chip_setup(struct drm_device *dev);
-
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c
deleted file mode 100644 (file)
index c904d73..0000000
+++ /dev/null
@@ -1,858 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-
-/*
- * Code for the SGX MMU:
- */
-
-/*
- * clflush on one processor only:
- * clflush should apparently flush the cache line on all processors in an
- * SMP system.
- */
-
-/*
- * kmap atomic:
- * The usage of the slots must be completely encapsulated within a spinlock, and
- * no other functions that may be using the locks for other purposed may be
- * called from within the locked region.
- * Since the slots are per processor, this will guarantee that we are the only
- * user.
- */
-
-/*
- * TODO: Inserting ptes from an interrupt handler:
- * This may be desirable for some SGX functionality where the GPU can fault in
- * needed pages. For that, we need to make an atomic insert_pages function, that
- * may fail.
- * If it fails, the caller need to insert the page using a workqueue function,
- * but on average it should be fast.
- */
-
-struct psb_mmu_driver {
-       /* protects driver- and pd structures. Always take in read mode
-        * before taking the page table spinlock.
-        */
-       struct rw_semaphore sem;
-
-       /* protects page tables, directory tables and pt tables.
-        * and pt structures.
-        */
-       spinlock_t lock;
-
-       atomic_t needs_tlbflush;
-
-       uint8_t __iomem *register_map;
-       struct psb_mmu_pd *default_pd;
-       /*uint32_t bif_ctrl;*/
-       int has_clflush;
-       int clflush_add;
-       unsigned long clflush_mask;
-
-       struct drm_psb_private *dev_priv;
-};
-
-struct psb_mmu_pd;
-
-struct psb_mmu_pt {
-       struct psb_mmu_pd *pd;
-       uint32_t index;
-       uint32_t count;
-       struct page *p;
-       uint32_t *v;
-};
-
-struct psb_mmu_pd {
-       struct psb_mmu_driver *driver;
-       int hw_context;
-       struct psb_mmu_pt **tables;
-       struct page *p;
-       struct page *dummy_pt;
-       struct page *dummy_page;
-       uint32_t pd_mask;
-       uint32_t invalid_pde;
-       uint32_t invalid_pte;
-};
-
-static inline uint32_t psb_mmu_pt_index(uint32_t offset)
-{
-       return (offset >> PSB_PTE_SHIFT) & 0x3FF;
-}
-
-static inline uint32_t psb_mmu_pd_index(uint32_t offset)
-{
-       return offset >> PSB_PDE_SHIFT;
-}
-
-static inline void psb_clflush(void *addr)
-{
-       __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
-}
-
-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
-                                  void *addr)
-{
-       if (!driver->has_clflush)
-               return;
-
-       mb();
-       psb_clflush(addr);
-       mb();
-}
-
-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
-{
-       uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
-       uint32_t clflush_count = PAGE_SIZE / clflush_add;
-       int i;
-       uint8_t *clf;
-
-       clf = kmap_atomic(page, KM_USER0);
-       mb();
-       for (i = 0; i < clflush_count; ++i) {
-               psb_clflush(clf);
-               clf += clflush_add;
-       }
-       mb();
-       kunmap_atomic(clf, KM_USER0);
-}
-
-static void psb_pages_clflush(struct psb_mmu_driver *driver,
-                               struct page *page[], unsigned long num_pages)
-{
-       int i;
-
-       if (!driver->has_clflush)
-               return ;
-
-       for (i = 0; i < num_pages; i++)
-               psb_page_clflush(driver, *page++);
-}
-
-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
-                                   int force)
-{
-       atomic_set(&driver->needs_tlbflush, 0);
-}
-
-static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
-{
-       down_write(&driver->sem);
-       psb_mmu_flush_pd_locked(driver, force);
-       up_write(&driver->sem);
-}
-
-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
-{
-       if (rc_prot)
-               down_write(&driver->sem);
-       if (rc_prot)
-               up_write(&driver->sem);
-}
-
-void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
-{
-       /*ttm_tt_cache_flush(&pd->p, 1);*/
-       psb_pages_clflush(pd->driver, &pd->p, 1);
-       down_write(&pd->driver->sem);
-       wmb();
-       psb_mmu_flush_pd_locked(pd->driver, 1);
-       pd->hw_context = hw_context;
-       up_write(&pd->driver->sem);
-
-}
-
-static inline unsigned long psb_pd_addr_end(unsigned long addr,
-                                           unsigned long end)
-{
-
-       addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
-       return (addr < end) ? addr : end;
-}
-
-static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
-{
-       uint32_t mask = PSB_PTE_VALID;
-
-       if (type & PSB_MMU_CACHED_MEMORY)
-               mask |= PSB_PTE_CACHED;
-       if (type & PSB_MMU_RO_MEMORY)
-               mask |= PSB_PTE_RO;
-       if (type & PSB_MMU_WO_MEMORY)
-               mask |= PSB_PTE_WO;
-
-       return (pfn << PAGE_SHIFT) | mask;
-}
-
-struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
-                                   int trap_pagefaults, int invalid_type)
-{
-       struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
-       uint32_t *v;
-       int i;
-
-       if (!pd)
-               return NULL;
-
-       pd->p = alloc_page(GFP_DMA32);
-       if (!pd->p)
-               goto out_err1;
-       pd->dummy_pt = alloc_page(GFP_DMA32);
-       if (!pd->dummy_pt)
-               goto out_err2;
-       pd->dummy_page = alloc_page(GFP_DMA32);
-       if (!pd->dummy_page)
-               goto out_err3;
-
-       if (!trap_pagefaults) {
-               pd->invalid_pde =
-                   psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
-                                    invalid_type);
-               pd->invalid_pte =
-                   psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
-                                    invalid_type);
-       } else {
-               pd->invalid_pde = 0;
-               pd->invalid_pte = 0;
-       }
-
-       v = kmap(pd->dummy_pt);
-       for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-               v[i] = pd->invalid_pte;
-
-       kunmap(pd->dummy_pt);
-
-       v = kmap(pd->p);
-       for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-               v[i] = pd->invalid_pde;
-
-       kunmap(pd->p);
-
-       clear_page(kmap(pd->dummy_page));
-       kunmap(pd->dummy_page);
-
-       pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
-       if (!pd->tables)
-               goto out_err4;
-
-       pd->hw_context = -1;
-       pd->pd_mask = PSB_PTE_VALID;
-       pd->driver = driver;
-
-       return pd;
-
-out_err4:
-       __free_page(pd->dummy_page);
-out_err3:
-       __free_page(pd->dummy_pt);
-out_err2:
-       __free_page(pd->p);
-out_err1:
-       kfree(pd);
-       return NULL;
-}
-
-void psb_mmu_free_pt(struct psb_mmu_pt *pt)
-{
-       __free_page(pt->p);
-       kfree(pt);
-}
-
-void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
-{
-       struct psb_mmu_driver *driver = pd->driver;
-       struct psb_mmu_pt *pt;
-       int i;
-
-       down_write(&driver->sem);
-       if (pd->hw_context != -1)
-               psb_mmu_flush_pd_locked(driver, 1);
-
-       /* Should take the spinlock here, but we don't need to do that
-          since we have the semaphore in write mode. */
-
-       for (i = 0; i < 1024; ++i) {
-               pt = pd->tables[i];
-               if (pt)
-                       psb_mmu_free_pt(pt);
-       }
-
-       vfree(pd->tables);
-       __free_page(pd->dummy_page);
-       __free_page(pd->dummy_pt);
-       __free_page(pd->p);
-       kfree(pd);
-       up_write(&driver->sem);
-}
-
-static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
-{
-       struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
-       void *v;
-       uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
-       uint32_t clflush_count = PAGE_SIZE / clflush_add;
-       spinlock_t *lock = &pd->driver->lock;
-       uint8_t *clf;
-       uint32_t *ptes;
-       int i;
-
-       if (!pt)
-               return NULL;
-
-       pt->p = alloc_page(GFP_DMA32);
-       if (!pt->p) {
-               kfree(pt);
-               return NULL;
-       }
-
-       spin_lock(lock);
-
-       v = kmap_atomic(pt->p, KM_USER0);
-       clf = (uint8_t *) v;
-       ptes = (uint32_t *) v;
-       for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-               *ptes++ = pd->invalid_pte;
-
-
-       if (pd->driver->has_clflush && pd->hw_context != -1) {
-               mb();
-               for (i = 0; i < clflush_count; ++i) {
-                       psb_clflush(clf);
-                       clf += clflush_add;
-               }
-               mb();
-       }
-
-       kunmap_atomic(v, KM_USER0);
-       spin_unlock(lock);
-
-       pt->count = 0;
-       pt->pd = pd;
-       pt->index = 0;
-
-       return pt;
-}
-
-struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
-                                            unsigned long addr)
-{
-       uint32_t index = psb_mmu_pd_index(addr);
-       struct psb_mmu_pt *pt;
-       uint32_t *v;
-       spinlock_t *lock = &pd->driver->lock;
-
-       spin_lock(lock);
-       pt = pd->tables[index];
-       while (!pt) {
-               spin_unlock(lock);
-               pt = psb_mmu_alloc_pt(pd);
-               if (!pt)
-                       return NULL;
-               spin_lock(lock);
-
-               if (pd->tables[index]) {
-                       spin_unlock(lock);
-                       psb_mmu_free_pt(pt);
-                       spin_lock(lock);
-                       pt = pd->tables[index];
-                       continue;
-               }
-
-               v = kmap_atomic(pd->p, KM_USER0);
-               pd->tables[index] = pt;
-               v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
-               pt->index = index;
-               kunmap_atomic((void *) v, KM_USER0);
-
-               if (pd->hw_context != -1) {
-                       psb_mmu_clflush(pd->driver, (void *) &v[index]);
-                       atomic_set(&pd->driver->needs_tlbflush, 1);
-               }
-       }
-       pt->v = kmap_atomic(pt->p, KM_USER0);
-       return pt;
-}
-
-static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
-                                             unsigned long addr)
-{
-       uint32_t index = psb_mmu_pd_index(addr);
-       struct psb_mmu_pt *pt;
-       spinlock_t *lock = &pd->driver->lock;
-
-       spin_lock(lock);
-       pt = pd->tables[index];
-       if (!pt) {
-               spin_unlock(lock);
-               return NULL;
-       }
-       pt->v = kmap_atomic(pt->p, KM_USER0);
-       return pt;
-}
-
-static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
-{
-       struct psb_mmu_pd *pd = pt->pd;
-       uint32_t *v;
-
-       kunmap_atomic(pt->v, KM_USER0);
-       if (pt->count == 0) {
-               v = kmap_atomic(pd->p, KM_USER0);
-               v[pt->index] = pd->invalid_pde;
-               pd->tables[pt->index] = NULL;
-
-               if (pd->hw_context != -1) {
-                       psb_mmu_clflush(pd->driver,
-                                       (void *) &v[pt->index]);
-                       atomic_set(&pd->driver->needs_tlbflush, 1);
-               }
-               kunmap_atomic(pt->v, KM_USER0);
-               spin_unlock(&pd->driver->lock);
-               psb_mmu_free_pt(pt);
-               return;
-       }
-       spin_unlock(&pd->driver->lock);
-}
-
-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
-                                  unsigned long addr, uint32_t pte)
-{
-       pt->v[psb_mmu_pt_index(addr)] = pte;
-}
-
-static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
-                                         unsigned long addr)
-{
-       pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
-}
-
-
-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
-                       uint32_t mmu_offset, uint32_t gtt_start,
-                       uint32_t gtt_pages)
-{
-       uint32_t *v;
-       uint32_t start = psb_mmu_pd_index(mmu_offset);
-       struct psb_mmu_driver *driver = pd->driver;
-       int num_pages = gtt_pages;
-
-       down_read(&driver->sem);
-       spin_lock(&driver->lock);
-
-       v = kmap_atomic(pd->p, KM_USER0);
-       v += start;
-
-       while (gtt_pages--) {
-               *v++ = gtt_start | pd->pd_mask;
-               gtt_start += PAGE_SIZE;
-       }
-
-       /*ttm_tt_cache_flush(&pd->p, num_pages);*/
-       psb_pages_clflush(pd->driver, &pd->p, num_pages);
-       kunmap_atomic(v, KM_USER0);
-       spin_unlock(&driver->lock);
-
-       if (pd->hw_context != -1)
-               atomic_set(&pd->driver->needs_tlbflush, 1);
-
-       up_read(&pd->driver->sem);
-       psb_mmu_flush_pd(pd->driver, 0);
-}
-
-struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
-{
-       struct psb_mmu_pd *pd;
-
-       /* down_read(&driver->sem); */
-       pd = driver->default_pd;
-       /* up_read(&driver->sem); */
-
-       return pd;
-}
-
-/* Returns the physical address of the PD shared by sgx/msvdx */
-uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
-{
-       struct psb_mmu_pd *pd;
-
-       pd = psb_mmu_get_default_pd(driver);
-       return page_to_pfn(pd->p) << PAGE_SHIFT;
-}
-
-void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
-{
-       psb_mmu_free_pagedir(driver->default_pd);
-       kfree(driver);
-}
-
-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
-                                       int trap_pagefaults,
-                                       int invalid_type,
-                                       struct drm_psb_private *dev_priv)
-{
-       struct psb_mmu_driver *driver;
-
-       driver = kmalloc(sizeof(*driver), GFP_KERNEL);
-
-       if (!driver)
-               return NULL;
-       driver->dev_priv = dev_priv;
-
-       driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
-                                             invalid_type);
-       if (!driver->default_pd)
-               goto out_err1;
-
-       spin_lock_init(&driver->lock);
-       init_rwsem(&driver->sem);
-       down_write(&driver->sem);
-       driver->register_map = registers;
-       atomic_set(&driver->needs_tlbflush, 1);
-
-       driver->has_clflush = 0;
-
-       if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
-               uint32_t tfms, misc, cap0, cap4, clflush_size;
-
-               /*
-                * clflush size is determined at kernel setup for x86_64
-                *  but not for i386. We have to do it here.
-                */
-
-               cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
-               clflush_size = ((misc >> 8) & 0xff) * 8;
-               driver->has_clflush = 1;
-               driver->clflush_add =
-                   PAGE_SIZE * clflush_size / sizeof(uint32_t);
-               driver->clflush_mask = driver->clflush_add - 1;
-               driver->clflush_mask = ~driver->clflush_mask;
-       }
-
-       up_write(&driver->sem);
-       return driver;
-
-out_err1:
-       kfree(driver);
-       return NULL;
-}
-
-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
-                              unsigned long address, uint32_t num_pages,
-                              uint32_t desired_tile_stride,
-                              uint32_t hw_tile_stride)
-{
-       struct psb_mmu_pt *pt;
-       uint32_t rows = 1;
-       uint32_t i;
-       unsigned long addr;
-       unsigned long end;
-       unsigned long next;
-       unsigned long add;
-       unsigned long row_add;
-       unsigned long clflush_add = pd->driver->clflush_add;
-       unsigned long clflush_mask = pd->driver->clflush_mask;
-
-       if (!pd->driver->has_clflush) {
-               /*ttm_tt_cache_flush(&pd->p, num_pages);*/
-               psb_pages_clflush(pd->driver, &pd->p, num_pages);
-               return;
-       }
-
-       if (hw_tile_stride)
-               rows = num_pages / desired_tile_stride;
-       else
-               desired_tile_stride = num_pages;
-
-       add = desired_tile_stride << PAGE_SHIFT;
-       row_add = hw_tile_stride << PAGE_SHIFT;
-       mb();
-       for (i = 0; i < rows; ++i) {
-
-               addr = address;
-               end = addr + add;
-
-               do {
-                       next = psb_pd_addr_end(addr, end);
-                       pt = psb_mmu_pt_map_lock(pd, addr);
-                       if (!pt)
-                               continue;
-                       do {
-                               psb_clflush(&pt->v
-                                           [psb_mmu_pt_index(addr)]);
-                       } while (addr +=
-                                clflush_add,
-                                (addr & clflush_mask) < next);
-
-                       psb_mmu_pt_unmap_unlock(pt);
-               } while (addr = next, next != end);
-               address += row_add;
-       }
-       mb();
-}
-
-void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
-                                unsigned long address, uint32_t num_pages)
-{
-       struct psb_mmu_pt *pt;
-       unsigned long addr;
-       unsigned long end;
-       unsigned long next;
-       unsigned long f_address = address;
-
-       down_read(&pd->driver->sem);
-
-       addr = address;
-       end = addr + (num_pages << PAGE_SHIFT);
-
-       do {
-               next = psb_pd_addr_end(addr, end);
-               pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-               if (!pt)
-                       goto out;
-               do {
-                       psb_mmu_invalidate_pte(pt, addr);
-                       --pt->count;
-               } while (addr += PAGE_SIZE, addr < next);
-               psb_mmu_pt_unmap_unlock(pt);
-
-       } while (addr = next, next != end);
-
-out:
-       if (pd->hw_context != -1)
-               psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
-       up_read(&pd->driver->sem);
-
-       if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 0);
-
-       return;
-}
-
-void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
-                         uint32_t num_pages, uint32_t desired_tile_stride,
-                         uint32_t hw_tile_stride)
-{
-       struct psb_mmu_pt *pt;
-       uint32_t rows = 1;
-       uint32_t i;
-       unsigned long addr;
-       unsigned long end;
-       unsigned long next;
-       unsigned long add;
-       unsigned long row_add;
-       unsigned long f_address = address;
-
-       if (hw_tile_stride)
-               rows = num_pages / desired_tile_stride;
-       else
-               desired_tile_stride = num_pages;
-
-       add = desired_tile_stride << PAGE_SHIFT;
-       row_add = hw_tile_stride << PAGE_SHIFT;
-
-       /* down_read(&pd->driver->sem); */
-
-       /* Make sure we only need to flush this processor's cache */
-
-       for (i = 0; i < rows; ++i) {
-
-               addr = address;
-               end = addr + add;
-
-               do {
-                       next = psb_pd_addr_end(addr, end);
-                       pt = psb_mmu_pt_map_lock(pd, addr);
-                       if (!pt)
-                               continue;
-                       do {
-                               psb_mmu_invalidate_pte(pt, addr);
-                               --pt->count;
-
-                       } while (addr += PAGE_SIZE, addr < next);
-                       psb_mmu_pt_unmap_unlock(pt);
-
-               } while (addr = next, next != end);
-               address += row_add;
-       }
-       if (pd->hw_context != -1)
-               psb_mmu_flush_ptes(pd, f_address, num_pages,
-                                  desired_tile_stride, hw_tile_stride);
-
-       /* up_read(&pd->driver->sem); */
-
-       if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 0);
-}
-
-int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
-                               unsigned long address, uint32_t num_pages,
-                               int type)
-{
-       struct psb_mmu_pt *pt;
-       uint32_t pte;
-       unsigned long addr;
-       unsigned long end;
-       unsigned long next;
-       unsigned long f_address = address;
-       int ret = 0;
-
-       down_read(&pd->driver->sem);
-
-       addr = address;
-       end = addr + (num_pages << PAGE_SHIFT);
-
-       do {
-               next = psb_pd_addr_end(addr, end);
-               pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-               if (!pt) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               do {
-                       pte = psb_mmu_mask_pte(start_pfn++, type);
-                       psb_mmu_set_pte(pt, addr, pte);
-                       pt->count++;
-               } while (addr += PAGE_SIZE, addr < next);
-               psb_mmu_pt_unmap_unlock(pt);
-
-       } while (addr = next, next != end);
-
-out:
-       if (pd->hw_context != -1)
-               psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
-       up_read(&pd->driver->sem);
-
-       if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 1);
-
-       return ret;
-}
-
-int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
-                        unsigned long address, uint32_t num_pages,
-                        uint32_t desired_tile_stride,
-                        uint32_t hw_tile_stride, int type)
-{
-       struct psb_mmu_pt *pt;
-       uint32_t rows = 1;
-       uint32_t i;
-       uint32_t pte;
-       unsigned long addr;
-       unsigned long end;
-       unsigned long next;
-       unsigned long add;
-       unsigned long row_add;
-       unsigned long f_address = address;
-       int ret = 0;
-
-       if (hw_tile_stride) {
-               if (num_pages % desired_tile_stride != 0)
-                       return -EINVAL;
-               rows = num_pages / desired_tile_stride;
-       } else {
-               desired_tile_stride = num_pages;
-       }
-
-       add = desired_tile_stride << PAGE_SHIFT;
-       row_add = hw_tile_stride << PAGE_SHIFT;
-
-       down_read(&pd->driver->sem);
-
-       for (i = 0; i < rows; ++i) {
-
-               addr = address;
-               end = addr + add;
-
-               do {
-                       next = psb_pd_addr_end(addr, end);
-                       pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-                       if (!pt) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       do {
-                               pte =
-                                   psb_mmu_mask_pte(page_to_pfn(*pages++),
-                                                    type);
-                               psb_mmu_set_pte(pt, addr, pte);
-                               pt->count++;
-                       } while (addr += PAGE_SIZE, addr < next);
-                       psb_mmu_pt_unmap_unlock(pt);
-
-               } while (addr = next, next != end);
-
-               address += row_add;
-       }
-out:
-       if (pd->hw_context != -1)
-               psb_mmu_flush_ptes(pd, f_address, num_pages,
-                                  desired_tile_stride, hw_tile_stride);
-
-       up_read(&pd->driver->sem);
-
-       if (pd->hw_context != -1)
-               psb_mmu_flush(pd->driver, 1);
-
-       return ret;
-}
-
-int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
-                          unsigned long *pfn)
-{
-       int ret;
-       struct psb_mmu_pt *pt;
-       uint32_t tmp;
-       spinlock_t *lock = &pd->driver->lock;
-
-       down_read(&pd->driver->sem);
-       pt = psb_mmu_pt_map_lock(pd, virtual);
-       if (!pt) {
-               uint32_t *v;
-
-               spin_lock(lock);
-               v = kmap_atomic(pd->p, KM_USER0);
-               tmp = v[psb_mmu_pd_index(virtual)];
-               kunmap_atomic(v, KM_USER0);
-               spin_unlock(lock);
-
-               if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
-                   !(pd->invalid_pte & PSB_PTE_VALID)) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               ret = 0;
-               *pfn = pd->invalid_pte >> PAGE_SHIFT;
-               goto out;
-       }
-       tmp = pt->v[psb_mmu_pt_index(virtual)];
-       if (!(tmp & PSB_PTE_VALID)) {
-               ret = -EINVAL;
-       } else {
-               ret = 0;
-               *pfn = tmp >> PAGE_SHIFT;
-       }
-       psb_mmu_pt_unmap_unlock(pt);
-out:
-       up_read(&pd->driver->sem);
-       return ret;
-}
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
deleted file mode 100644 (file)
index b563dbc..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-/* MID device specific descriptors */
-
-struct mrst_vbt {
-       s8 signature[4];        /*4 bytes,"$GCT" */
-       u8 revision;
-       u8 size;
-       u8 checksum;
-       void *mrst_gct;
-} __packed;
-
-struct mrst_timing_info {
-       u16 pixel_clock;
-       u8 hactive_lo;
-       u8 hblank_lo;
-       u8 hblank_hi:4;
-       u8 hactive_hi:4;
-       u8 vactive_lo;
-       u8 vblank_lo;
-       u8 vblank_hi:4;
-       u8 vactive_hi:4;
-       u8 hsync_offset_lo;
-       u8 hsync_pulse_width_lo;
-       u8 vsync_pulse_width_lo:4;
-       u8 vsync_offset_lo:4;
-       u8 vsync_pulse_width_hi:2;
-       u8 vsync_offset_hi:2;
-       u8 hsync_pulse_width_hi:2;
-       u8 hsync_offset_hi:2;
-       u8 width_mm_lo;
-       u8 height_mm_lo;
-       u8 height_mm_hi:4;
-       u8 width_mm_hi:4;
-       u8 hborder;
-       u8 vborder;
-       u8 unknown0:1;
-       u8 hsync_positive:1;
-       u8 vsync_positive:1;
-       u8 separate_sync:2;
-       u8 stereo:1;
-       u8 unknown6:1;
-       u8 interlaced:1;
-} __packed;
-
-struct gct_r10_timing_info {
-       u16 pixel_clock;
-       u32 hactive_lo:8;
-       u32 hactive_hi:4;
-       u32 hblank_lo:8;
-       u32 hblank_hi:4;
-       u32 hsync_offset_lo:8;
-       u16 hsync_offset_hi:2;
-       u16 hsync_pulse_width_lo:8;
-       u16 hsync_pulse_width_hi:2;
-       u16 hsync_positive:1;
-       u16 rsvd_1:3;
-       u8  vactive_lo:8;
-       u16 vactive_hi:4;
-       u16 vblank_lo:8;
-       u16 vblank_hi:4;
-       u16 vsync_offset_lo:4;
-       u16 vsync_offset_hi:2;
-       u16 vsync_pulse_width_lo:4;
-       u16 vsync_pulse_width_hi:2;
-       u16 vsync_positive:1;
-       u16 rsvd_2:3;
-} __packed;
-
-struct mrst_panel_descriptor_v1 {
-       u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
-                               /* 0x61190 if MIPI */
-       u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
-       u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
-       u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */
-                                               /* Register 0x61210 */
-       struct mrst_timing_info DTD;/*18 bytes, Standard definition */
-       u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */
-                               /* Bit 0, Frequency, 15 bits,0 - 32767Hz */
-                       /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */
-       u16 Panel_MIPI_Display_Descriptor;
-                       /*16 bits, Defined as follows: */
-                       /* if MIPI, 0x0000 if LVDS */
-                       /* Bit 0, Type, 2 bits, */
-                       /* 0: Type-1, */
-                       /* 1: Type-2, */
-                       /* 2: Type-3, */
-                       /* 3: Type-4 */
-                       /* Bit 2, Pixel Format, 4 bits */
-                       /* Bit0: 16bpp (not supported in LNC), */
-                       /* Bit1: 18bpp loosely packed, */
-                       /* Bit2: 18bpp packed, */
-                       /* Bit3: 24bpp */
-                       /* Bit 6, Reserved, 2 bits, 00b */
-                       /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
-                       /* Bit 14, Reserved, 2 bits, 00b */
-} __packed;
-
-struct mrst_panel_descriptor_v2 {
-       u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
-                               /* 0x61190 if MIPI */
-       u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
-       u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
-       u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */
-                                               /* Register 0x61210 */
-       struct mrst_timing_info DTD;/*18 bytes, Standard definition */
-       u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/
-                               /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/
-       u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */
-                       /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/
-       u16 Panel_MIPI_Display_Descriptor;
-                       /*16 bits, Defined as follows: */
-                       /* if MIPI, 0x0000 if LVDS */
-                       /* Bit 0, Type, 2 bits, */
-                       /* 0: Type-1, */
-                       /* 1: Type-2, */
-                       /* 2: Type-3, */
-                       /* 3: Type-4 */
-                       /* Bit 2, Pixel Format, 4 bits */
-                       /* Bit0: 16bpp (not supported in LNC), */
-                       /* Bit1: 18bpp loosely packed, */
-                       /* Bit2: 18bpp packed, */
-                       /* Bit3: 24bpp */
-                       /* Bit 6, Reserved, 2 bits, 00b */
-                       /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
-                       /* Bit 14, Reserved, 2 bits, 00b */
-} __packed;
-
-union mrst_panel_rx {
-       struct {
-               u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/
-                       /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */
-               u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */
-               /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/
-               u16 SupportedVideoTransferMode:2; /*0: Non-burst only */
-                                       /* 1: Burst and non-burst */
-                                       /* 2/3: Reserved */
-               u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/
-               u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/
-               u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/
-               u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */
-               u16 Rsvd:5;/*5 bits,00000b */
-       } panelrx;
-       u16 panel_receiver;
-} __packed;
-
-struct mrst_gct_v1 {
-       union { /*8 bits,Defined as follows: */
-               struct {
-                       u8 PanelType:4; /*4 bits, Bit field for panels*/
-                                       /* 0 - 3: 0 = LVDS, 1 = MIPI*/
-                                       /*2 bits,Specifies which of the*/
-                       u8 BootPanelIndex:2;
-                                       /* 4 panels to use by default*/
-                       u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
-                                       /* the 4 MIPI DSI receivers to use*/
-               } PD;
-               u8 PanelDescriptor;
-       };
-       struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/
-       union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __packed;
-
-struct mrst_gct_v2 {
-       union { /*8 bits,Defined as follows: */
-               struct {
-                       u8 PanelType:4; /*4 bits, Bit field for panels*/
-                                       /* 0 - 3: 0 = LVDS, 1 = MIPI*/
-                                       /*2 bits,Specifies which of the*/
-                       u8 BootPanelIndex:2;
-                                       /* 4 panels to use by default*/
-                       u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
-                                       /* the 4 MIPI DSI receivers to use*/
-               } PD;
-               u8 PanelDescriptor;
-       };
-       struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/
-       union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __packed;
-
-struct mrst_gct_data {
-       u8 bpi; /* boot panel index, number of panel used during boot */
-       u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */
-       struct mrst_timing_info DTD; /* timing info for the selected panel */
-       u32 Panel_Port_Control;
-       u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/
-       u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/
-       u32 PP_Cycle_Delay;
-       u16 Panel_Backlight_Inverter_Descriptor;
-       u16 Panel_MIPI_Display_Descriptor;
-} __packed;
-
-#define MODE_SETTING_IN_CRTC           0x1
-#define MODE_SETTING_IN_ENCODER                0x2
-#define MODE_SETTING_ON_GOING          0x3
-#define MODE_SETTING_IN_DSR            0x4
-#define MODE_SETTING_ENCODER_DONE      0x8
-
-#define GCT_R10_HEADER_SIZE            16
-#define GCT_R10_DISPLAY_DESC_SIZE      28
-
-/*
- *     Moorestown HDMI interfaces
- */
-
-struct mrst_hdmi_dev {
-       struct pci_dev *dev;
-       void __iomem *regs;
-       unsigned int mmio, mmio_len;
-       int dpms_mode;
-       struct hdmi_i2c_dev *i2c_dev;
-
-       /* register state */
-       u32 saveDPLL_CTRL;
-       u32 saveDPLL_DIV_CTRL;
-       u32 saveDPLL_ADJUST;
-       u32 saveDPLL_UPDATE;
-       u32 saveDPLL_CLK_ENABLE;
-       u32 savePCH_HTOTAL_B;
-       u32 savePCH_HBLANK_B;
-       u32 savePCH_HSYNC_B;
-       u32 savePCH_VTOTAL_B;
-       u32 savePCH_VBLANK_B;
-       u32 savePCH_VSYNC_B;
-       u32 savePCH_PIPEBCONF;
-       u32 savePCH_PIPEBSRC;
-};
-
-extern void mrst_hdmi_setup(struct drm_device *dev);
-extern void mrst_hdmi_teardown(struct drm_device *dev);
-extern int  mrst_hdmi_i2c_init(struct pci_dev *dev);
-extern void mrst_hdmi_i2c_exit(struct pci_dev *dev);
-extern void mrst_hdmi_save(struct drm_device *dev);
-extern void mrst_hdmi_restore(struct drm_device *dev);
-extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
deleted file mode 100644 (file)
index 980837e..0000000
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Copyright Â© 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "framebuffer.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-
-struct psb_intel_range_t {
-       int min, max;
-};
-
-struct mrst_limit_t {
-       struct psb_intel_range_t dot, m, p1;
-};
-
-struct mrst_clock_t {
-       /* derived values */
-       int dot;
-       int m;
-       int p1;
-};
-
-#define MRST_LIMIT_LVDS_100L       0
-#define MRST_LIMIT_LVDS_83         1
-#define MRST_LIMIT_LVDS_100        2
-
-#define MRST_DOT_MIN             19750
-#define MRST_DOT_MAX             120000
-#define MRST_M_MIN_100L                    20
-#define MRST_M_MIN_100             10
-#define MRST_M_MIN_83              12
-#define MRST_M_MAX_100L                    34
-#define MRST_M_MAX_100             17
-#define MRST_M_MAX_83              20
-#define MRST_P1_MIN                2
-#define MRST_P1_MAX_0              7
-#define MRST_P1_MAX_1              8
-
-static const struct mrst_limit_t mrst_limits[] = {
-       {                       /* MRST_LIMIT_LVDS_100L */
-        .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
-        .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L},
-        .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},
-        },
-       {                       /* MRST_LIMIT_LVDS_83L */
-        .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
-        .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83},
-        .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0},
-        },
-       {                       /* MRST_LIMIT_LVDS_100 */
-        .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
-        .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100},
-        .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},
-        },
-};
-
-#define MRST_M_MIN         10
-static const u32 mrst_m_converts[] = {
-       0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C,
-       0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25,
-       0x12, 0x09, 0x24, 0x32, 0x39, 0x1c,
-};
-
-static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc)
-{
-       const struct mrst_limit_t *limit = NULL;
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
-           || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {
-               switch (dev_priv->core_freq) {
-               case 100:
-                       limit = &mrst_limits[MRST_LIMIT_LVDS_100L];
-                       break;
-               case 166:
-                       limit = &mrst_limits[MRST_LIMIT_LVDS_83];
-                       break;
-               case 200:
-                       limit = &mrst_limits[MRST_LIMIT_LVDS_100];
-                       break;
-               }
-       } else {
-               limit = NULL;
-               dev_err(dev->dev, "mrst_limit Wrong display type.\n");
-       }
-
-       return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-static void mrst_clock(int refclk, struct mrst_clock_t *clock)
-{
-       clock->dot = (refclk * clock->m) / (14 * clock->p1);
-}
-
-void mrstPrintPll(char *prefix, struct mrst_clock_t *clock)
-{
-       pr_debug("%s: dotclock = %d,  m = %d, p1 = %d.\n",
-            prefix, clock->dot, clock->m, clock->p1);
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given refclk,
- * or FALSE.  Divisor values are the actual divisors for
- */
-static bool
-mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
-               struct mrst_clock_t *best_clock)
-{
-       struct mrst_clock_t clock;
-       const struct mrst_limit_t *limit = mrst_limit(crtc);
-       int err = target;
-
-       memset(best_clock, 0, sizeof(*best_clock));
-
-       for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
-               for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
-                    clock.p1++) {
-                       int this_err;
-
-                       mrst_clock(refclk, &clock);
-
-                       this_err = abs(clock.dot - target);
-                       if (this_err < err) {
-                               *best_clock = clock;
-                               err = this_err;
-                       }
-               }
-       }
-       dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err);
-       return err != target;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       u32 temp;
-       bool enabled;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       /* XXX: When our outputs are all unaware of DPMS modes other than off
-        * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-        */
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-               /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-               }
-               /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) == 0)
-                       REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
-               /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp | DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-               }
-
-               psb_intel_crtc_load_lut(crtc);
-
-               /* Give the overlay scaler a chance to enable
-                  if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, true); TODO */
-               break;
-       case DRM_MODE_DPMS_OFF:
-               /* Give the overlay scaler a chance to disable
-                * if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-
-               /* Disable the VGA plane that we never use */
-               REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-               /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp & ~DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
-               }
-
-               /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(pipeconf_reg);
-               }
-               /* Wait for for the pipe disable to take effect. */
-               psb_intel_wait_for_vblank(dev);
-
-               temp = REG_READ(dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) != 0) {
-                       REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-               }
-
-               /* Wait for the clocks to turn off. */
-               udelay(150);
-               break;
-       }
-
-       enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
-       /*Set FIFO Watermarks*/
-       REG_WRITE(DSPARB, 0x3FFF);
-       REG_WRITE(DSPFW1, 0x3F88080A);
-       REG_WRITE(DSPFW2, 0x0b060808);
-       REG_WRITE(DSPFW3, 0x0);
-       REG_WRITE(DSPFW4, 0x08030404);
-       REG_WRITE(DSPFW5, 0x04040404);
-       REG_WRITE(DSPFW6, 0x78);
-       REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000);
-       /* Must write Bit 14 of the Chicken Bit Register */
-
-       gma_power_end(dev);
-}
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int mrst_panel_fitter_pipe(struct drm_device *dev)
-{
-       u32 pfit_control;
-
-       pfit_control = REG_READ(PFIT_CONTROL);
-
-       /* See if the panel fitter is in use */
-       if ((pfit_control & PFIT_ENABLE) == 0)
-               return -1;
-       return (pfit_control >> 29) & 3;
-}
-
-static int mrst_crtc_mode_set(struct drm_crtc *crtc,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode,
-                             int x, int y,
-                             struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int pipe = psb_intel_crtc->pipe;
-       int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0;
-       int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-       int refclk = 0;
-       struct mrst_clock_t clock;
-       u32 dpll = 0, fp = 0, dspcntr, pipeconf;
-       bool ok, is_sdvo = false;
-       bool is_crt = false, is_lvds = false, is_tv = false;
-       bool is_mipi = false;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct psb_intel_output *psb_intel_output = NULL;
-       uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
-       struct drm_encoder *encoder;
-
-       if (!gma_power_begin(dev, true))
-               return 0;
-
-       memcpy(&psb_intel_crtc->saved_mode,
-               mode,
-               sizeof(struct drm_display_mode));
-       memcpy(&psb_intel_crtc->saved_adjusted_mode,
-               adjusted_mode,
-               sizeof(struct drm_display_mode));
-
-       list_for_each_entry(encoder, &mode_config->encoder_list, head) {
-
-               if (encoder->crtc != crtc)
-                       continue;
-
-               psb_intel_output = enc_to_psb_intel_output(encoder);
-               switch (psb_intel_output->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_SDVO:
-                       is_sdvo = true;
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       is_tv = true;
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       is_crt = true;
-                       break;
-               case INTEL_OUTPUT_MIPI:
-                       is_mipi = true;
-                       break;
-               }
-       }
-
-       /* Disable the VGA plane that we never use */
-       REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
-       /* Disable the panel fitter if it was on our pipe */
-       if (mrst_panel_fitter_pipe(dev) == pipe)
-               REG_WRITE(PFIT_CONTROL, 0);
-
-       REG_WRITE(pipesrc_reg,
-                 ((mode->crtc_hdisplay - 1) << 16) |
-                 (mode->crtc_vdisplay - 1));
-
-       if (psb_intel_output)
-               drm_connector_property_get_value(&psb_intel_output->base,
-                       dev->mode_config.scaling_mode_property, &scalingType);
-
-       if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
-               /* Moorestown doesn't have register support for centering so
-                * we need to mess with the h/vblank and h/vsync start and
-                * ends to get centering */
-               int offsetX = 0, offsetY = 0;
-
-               offsetX = (adjusted_mode->crtc_hdisplay -
-                          mode->crtc_hdisplay) / 2;
-               offsetY = (adjusted_mode->crtc_vdisplay -
-                          mode->crtc_vdisplay) / 2;
-
-               REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
-                       ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
-                       ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg,
-                       (adjusted_mode->crtc_hblank_start - offsetX - 1) |
-                       ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
-               REG_WRITE(hsync_reg,
-                       (adjusted_mode->crtc_hsync_start - offsetX - 1) |
-                       ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
-               REG_WRITE(vblank_reg,
-                       (adjusted_mode->crtc_vblank_start - offsetY - 1) |
-                       ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
-               REG_WRITE(vsync_reg,
-                       (adjusted_mode->crtc_vsync_start - offsetY - 1) |
-                       ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
-       } else {
-               REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
-                       ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
-                       ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
-                       ((adjusted_mode->crtc_hblank_end - 1) << 16));
-               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
-                       ((adjusted_mode->crtc_hsync_end - 1) << 16));
-               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
-                       ((adjusted_mode->crtc_vblank_end - 1) << 16));
-               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
-                       ((adjusted_mode->crtc_vsync_end - 1) << 16));
-       }
-
-       /* Flush the plane changes */
-       {
-               struct drm_crtc_helper_funcs *crtc_funcs =
-                   crtc->helper_private;
-               crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-       }
-
-       /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
-
-       /* Set up the display plane register */
-       dspcntr = REG_READ(dspcntr_reg);
-       dspcntr |= DISPPLANE_GAMMA_ENABLE;
-
-       if (pipe == 0)
-               dspcntr |= DISPPLANE_SEL_PIPE_A;
-       else
-               dspcntr |= DISPPLANE_SEL_PIPE_B;
-
-       dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE;
-       dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE;
-
-       if (is_mipi)
-               goto mrst_crtc_mode_set_exit;
-
-       refclk = dev_priv->core_freq * 1000;
-
-       dpll = 0;               /*BIT16 = 0 for 100MHz reference */
-
-       ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock);
-
-       if (!ok) {
-               dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n");
-       } else {
-               dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d,"
-                        "m = %x, p1 = %x.\n", clock.dot, clock.m,
-                        clock.p1);
-       }
-
-       fp = mrst_m_converts[(clock.m - MRST_M_MIN)] << 8;
-
-       dpll |= DPLL_VGA_MODE_DIS;
-
-
-       dpll |= DPLL_VCO_ENABLE;
-
-       if (is_lvds)
-               dpll |= DPLLA_MODE_LVDS;
-       else
-               dpll |= DPLLB_MODE_DAC_SERIAL;
-
-       if (is_sdvo) {
-               int sdvo_pixel_multiply =
-                   adjusted_mode->clock / mode->clock;
-
-               dpll |= DPLL_DVO_HIGH_SPEED;
-               dpll |=
-                   (sdvo_pixel_multiply -
-                    1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-       }
-
-
-       /* compute bitmask from p1 value */
-       dpll |= (1 << (clock.p1 - 2)) << 17;
-
-       dpll |= DPLL_VCO_ENABLE;
-
-       mrstPrintPll("chosen", &clock);
-
-       if (dpll & DPLL_VCO_ENABLE) {
-               REG_WRITE(fp_reg, fp);
-               REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
-               REG_READ(dpll_reg);
-               /* Check the DPLLA lock bit PIPEACONF[29] */
-               udelay(150);
-       }
-
-       REG_WRITE(fp_reg, fp);
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150);
-
-       /* write it again -- the BIOS does, after all */
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150);
-
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
-       psb_intel_wait_for_vblank(dev);
-
-       REG_WRITE(dspcntr_reg, dspcntr);
-       psb_intel_wait_for_vblank(dev);
-
-mrst_crtc_mode_set_exit:
-       gma_power_end(dev);
-       return 0;
-}
-
-static bool mrst_crtc_mode_fixup(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-int mrst_pipe_set_base(struct drm_crtc *crtc,
-                           int x, int y, struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
-       int pipe = psb_intel_crtc->pipe;
-       unsigned long start, offset;
-
-       int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE);
-       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       u32 dspcntr;
-       int ret = 0;
-
-       /* no fb bound */
-       if (!crtc->fb) {
-               dev_dbg(dev->dev, "No FB bound\n");
-               return 0;
-       }
-
-       if (!gma_power_begin(dev, true))
-               return 0;
-
-       start = psbfb->gtt->offset;
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
-
-       dspcntr = REG_READ(dspcntr_reg);
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               dspcntr |= DISPPLANE_8BPP;
-               break;
-       case 16:
-               if (crtc->fb->depth == 15)
-                       dspcntr |= DISPPLANE_15_16BPP;
-               else
-                       dspcntr |= DISPPLANE_16BPP;
-               break;
-       case 24:
-       case 32:
-               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-               break;
-       default:
-               dev_err(dev->dev, "Unknown color depth\n");
-               ret = -EINVAL;
-               goto pipe_set_base_exit;
-       }
-       REG_WRITE(dspcntr_reg, dspcntr);
-
-       REG_WRITE(dspbase, offset);
-       REG_READ(dspbase);
-       REG_WRITE(dspsurf, start);
-       REG_READ(dspsurf);
-
-pipe_set_base_exit:
-       gma_power_end(dev);
-       return ret;
-}
-
-static void mrst_crtc_prepare(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void mrst_crtc_commit(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-const struct drm_crtc_helper_funcs mrst_helper_funcs = {
-       .dpms = mrst_crtc_dpms,
-       .mode_fixup = mrst_crtc_mode_fixup,
-       .mode_set = mrst_crtc_mode_set,
-       .mode_set_base = mrst_pipe_set_base,
-       .prepare = mrst_crtc_prepare,
-       .commit = mrst_crtc_commit,
-};
-
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
deleted file mode 100644 (file)
index 6707faf..0000000
+++ /dev/null
@@ -1,634 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <linux/backlight.h>
-#include <linux/module.h>
-#include <linux/dmi.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <asm/mrst.h>
-#include <asm/intel_scu_ipc.h>
-#include "mid_bios.h"
-
-static int devtype;
-
-module_param_named(type, devtype, int, 0600);
-MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type");
-
-#define DEVICE_MOORESTOWN              1
-#define DEVICE_OAKTRAIL                        2
-#define DEVICE_MOORESTOWN_MM           3
-
-static int mrst_device_ident(struct drm_device *dev)
-{
-       /* User forced */
-       if (devtype)
-               return devtype;
-       if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") ||
-               dmi_match(DMI_PRODUCT_NAME, "OakTrail platform"))
-               return DEVICE_OAKTRAIL;
-#if defined(CONFIG_X86_MRST)
-       if (dmi_match(DMI_PRODUCT_NAME, "MM") ||
-               dmi_match(DMI_PRODUCT_NAME, "MM 10"))
-               return DEVICE_MOORESTOWN_MM;
-       if (mrst_identify_cpu())
-               return DEVICE_MOORESTOWN;
-#endif
-       return DEVICE_OAKTRAIL;
-}
-
-
-/* IPC message and command defines used to enable/disable mipi panel voltages */
-#define IPC_MSG_PANEL_ON_OFF    0xE9
-#define IPC_CMD_PANEL_ON        1
-#define IPC_CMD_PANEL_OFF       0
-
-static int mrst_output_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       if (dev_priv->iLVDS_enable)
-               mrst_lvds_init(dev, &dev_priv->mode_dev);
-       else
-               dev_err(dev->dev, "DSI is not supported\n");
-       if (dev_priv->hdmi_priv)
-               mrst_hdmi_init(dev, &dev_priv->mode_dev);
-       return 0;
-}
-
-/*
- *     Provide the low level interfaces for the Moorestown backlight
- */
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-#define MRST_BLC_MAX_PWM_REG_FREQ          0xFFFF
-#define BLC_PWM_PRECISION_FACTOR 100   /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-#define BLC_ADJUSTMENT_MAX 100
-
-static struct backlight_device *mrst_backlight_device;
-static int mrst_brightness;
-
-static int mrst_set_brightness(struct backlight_device *bd)
-{
-       struct drm_device *dev = bl_get_data(mrst_backlight_device);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int level = bd->props.brightness;
-       u32 blc_pwm_ctl;
-       u32 max_pwm_blc;
-
-       /* Percentage 1-100% being valid */
-       if (level < 1)
-               level = 1;
-
-       if (gma_power_begin(dev, 0)) {
-               /* Calculate and set the brightness value */
-               max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
-               blc_pwm_ctl = level * max_pwm_blc / 100;
-
-               /* Adjust the backlight level with the percent in
-                * dev_priv->blc_adj1;
-                */
-               blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
-               blc_pwm_ctl = blc_pwm_ctl / 100;
-
-               /* Adjust the backlight level with the percent in
-                * dev_priv->blc_adj2;
-                */
-               blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
-               blc_pwm_ctl = blc_pwm_ctl / 100;
-
-               /* force PWM bit on */
-               REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
-               REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
-               gma_power_end(dev);
-       }
-       mrst_brightness = level;
-       return 0;
-}
-
-static int mrst_get_brightness(struct backlight_device *bd)
-{
-       /* return locally cached var instead of HW read (due to DPST etc.) */
-       /* FIXME: ideally return actual value in case firmware fiddled with
-          it */
-       return mrst_brightness;
-}
-
-static int device_backlight_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long core_clock;
-       u16 bl_max_freq;
-       uint32_t value;
-       uint32_t blc_pwm_precision_factor;
-
-       dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
-       dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
-       bl_max_freq = 256;
-       /* this needs to be set elsewhere */
-       blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
-
-       core_clock = dev_priv->core_freq;
-
-       value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
-       value *= blc_pwm_precision_factor;
-       value /= bl_max_freq;
-       value /= blc_pwm_precision_factor;
-
-       if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
-                       return -ERANGE;
-
-       if (gma_power_begin(dev, false)) {
-               REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
-               REG_WRITE(BLC_PWM_CTL, value | (value << 16));
-               gma_power_end(dev);
-       }
-       return 0;
-}
-
-static const struct backlight_ops mrst_ops = {
-       .get_brightness = mrst_get_brightness,
-       .update_status  = mrst_set_brightness,
-};
-
-int mrst_backlight_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int ret;
-       struct backlight_properties props;
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.max_brightness = 100;
-       props.type = BACKLIGHT_PLATFORM;
-
-       mrst_backlight_device = backlight_device_register("mrst-bl",
-                                       NULL, (void *)dev, &mrst_ops, &props);
-
-       if (IS_ERR(mrst_backlight_device))
-               return PTR_ERR(mrst_backlight_device);
-
-       ret = device_backlight_init(dev);
-       if (ret < 0) {
-               backlight_device_unregister(mrst_backlight_device);
-               return ret;
-       }
-       mrst_backlight_device->props.brightness = 100;
-       mrst_backlight_device->props.max_brightness = 100;
-       backlight_update_status(mrst_backlight_device);
-       dev_priv->backlight_device = mrst_backlight_device;
-       return 0;
-}
-
-#endif
-
-/*
- *     Provide the Moorestown specific chip logic and low level methods
- *     for power management
- */
-
-static void mrst_init_pm(struct drm_device *dev)
-{
-}
-
-/**
- *     mrst_save_display_registers     -       save registers lost on suspend
- *     @dev: our DRM device
- *
- *     Save the state we need in order to be able to restore the interface
- *     upon resume from suspend
- */
-static int mrst_save_display_registers(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int i;
-       u32 pp_stat;
-
-       /* Display arbitration control + watermarks */
-       dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
-       dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
-       dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
-       dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
-       dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
-       dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
-       dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
-       dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
-       /* Pipe & plane A info */
-       dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
-       dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
-       dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
-       dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
-       dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
-       dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
-       dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
-       dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
-       dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
-       dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
-       dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
-       dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
-       dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
-       dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
-       dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
-       dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
-       dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
-       dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
-
-       /* Save cursor regs */
-       dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
-       dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
-       dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
-
-       /* Save palette (gamma) */
-       for (i = 0; i < 256; i++)
-               dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
-
-       if (dev_priv->hdmi_priv)
-               mrst_hdmi_save(dev);
-
-       /* Save performance state */
-       dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
-
-       /* LVDS state */
-       dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
-       dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
-       dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
-       dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
-       dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
-       dev_priv->saveLVDS = PSB_RVDC32(LVDS);
-       dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
-       dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
-       dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
-       dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
-
-       /* HW overlay */
-       dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
-       dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
-       dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
-       dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
-       dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
-       dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
-       dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-
-       /* DPST registers */
-       dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
-                                       PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-       dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
-                                       PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
-       dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
-       if (dev_priv->iLVDS_enable) {
-               /* Shut down the panel */
-               PSB_WVDC32(0, PP_CONTROL);
-
-               do {
-                       pp_stat = PSB_RVDC32(PP_STATUS);
-               } while (pp_stat & 0x80000000);
-
-               /* Turn off the plane */
-               PSB_WVDC32(0x58000000, DSPACNTR);
-               /* Trigger the plane disable */
-               PSB_WVDC32(0, DSPASURF);
-
-               /* Wait ~4 ticks */
-               msleep(4);
-
-               /* Turn off pipe */
-               PSB_WVDC32(0x0, PIPEACONF);
-               /* Wait ~8 ticks */
-               msleep(8);
-
-               /* Turn off PLLs */
-               PSB_WVDC32(0, MRST_DPLL_A);
-       }
-       return 0;
-}
-
-/**
- *     mrst_restore_display_registers  -       restore lost register state
- *     @dev: our DRM device
- *
- *     Restore register state that was lost during suspend and resume.
- */
-static int mrst_restore_display_registers(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 pp_stat;
-       int i;
-
-       /* Display arbitration + watermarks */
-       PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
-       PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
-       PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
-       PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
-       PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
-       PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
-       PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
-       PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
-       /* Make sure VGA plane is off. it initializes to on after reset!*/
-       PSB_WVDC32(0x80000000, VGACNTRL);
-
-       /* set the plls */
-       PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
-       PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
-
-       /* Actually enable it */
-       PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
-       DRM_UDELAY(150);
-
-       /* Restore mode */
-       PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
-       PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
-       PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
-       PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
-       PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
-       PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
-       PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
-       PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
-
-       /* Restore performance mode*/
-       PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
-
-       /* Enable the pipe*/
-       if (dev_priv->iLVDS_enable)
-               PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
-
-       /* Set up the plane*/
-       PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
-       PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
-       PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
-
-       /* Enable the plane */
-       PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
-       PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
-
-       /* Enable Cursor A */
-       PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
-       PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
-       PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
-
-       /* Restore palette (gamma) */
-       for (i = 0; i < 256; i++)
-               PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
-
-       if (dev_priv->hdmi_priv)
-               mrst_hdmi_restore(dev);
-
-       if (dev_priv->iLVDS_enable) {
-               PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
-               PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
-               PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
-               PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
-               PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
-               PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
-               PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
-               PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
-               PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
-               PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
-       }
-
-       /* Wait for cycle delay */
-       do {
-               pp_stat = PSB_RVDC32(PP_STATUS);
-       } while (pp_stat & 0x08000000);
-
-       /* Wait for panel power up */
-       do {
-               pp_stat = PSB_RVDC32(PP_STATUS);
-       } while (pp_stat & 0x10000000);
-
-       /* Restore HW overlay */
-       PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
-       PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
-
-       /* DPST registers */
-       PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
-                                               HISTOGRAM_INT_CONTROL);
-       PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
-                                               HISTOGRAM_LOGIC_CONTROL);
-       PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
-
-       return 0;
-}
-
-/**
- *     mrst_power_down -       power down the display island
- *     @dev: our DRM device
- *
- *     Power down the display interface of our device
- */
-static int mrst_power_down(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 pwr_mask ;
-       u32 pwr_sts;
-
-       pwr_mask = PSB_PWRGT_DISPLAY_MASK;
-       outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
-
-       while (true) {
-               pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-               if ((pwr_sts & pwr_mask) == pwr_mask)
-                       break;
-               else
-                       udelay(10);
-       }
-       return 0;
-}
-
-/*
- * mrst_power_up
- *
- * Restore power to the specified island(s) (powergating)
- */
-static int mrst_power_up(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
-       u32 pwr_sts, pwr_cnt;
-
-       pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
-       pwr_cnt &= ~pwr_mask;
-       outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
-
-       while (true) {
-               pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-               if ((pwr_sts & pwr_mask) == 0)
-                       break;
-               else
-                       udelay(10);
-       }
-       return 0;
-}
-
-#if defined(CONFIG_X86_MRST)
-static void mrst_lvds_cache_bl(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT));
-       intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ));
-       intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL));
-}
-
-static void mrst_mm_bl_power(struct drm_device *dev, bool on)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (on) {
-               intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL);
-               intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT);
-               intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ);
-       } else {
-               intel_scu_ipc_iowrite8(0x2A, 0);
-               intel_scu_ipc_iowrite8(0x28, 0);
-               intel_scu_ipc_iowrite8(0x29, 0);
-       }
-}
-
-static const struct psb_ops mrst_mm_chip_ops = {
-       .name = "Moorestown MM ",
-       .accel_2d = 1,
-       .pipes = 1,
-       .crtcs = 1,
-       .sgx_offset = MRST_SGX_OFFSET,
-
-       .crtc_helper = &mrst_helper_funcs,
-       .crtc_funcs = &psb_intel_crtc_funcs,
-
-       .output_init = mrst_output_init,
-
-       .lvds_bl_power = mrst_mm_bl_power,
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       .backlight_init = mrst_backlight_init,
-#endif
-
-       .init_pm = mrst_init_pm,
-       .save_regs = mrst_save_display_registers,
-       .restore_regs = mrst_restore_display_registers,
-       .power_down = mrst_power_down,
-       .power_up = mrst_power_up,
-
-       .i2c_bus = 0,
-};
-
-#endif
-
-static void oaktrail_teardown(struct drm_device *dev)
-{
-       mrst_hdmi_teardown(dev);
-}
-
-static const struct psb_ops oaktrail_chip_ops = {
-       .name = "Oaktrail",
-       .accel_2d = 1,
-       .pipes = 2,
-       .crtcs = 2,
-       .sgx_offset = MRST_SGX_OFFSET,
-
-       .chip_setup = mid_chip_setup,
-       .chip_teardown = oaktrail_teardown,
-       .crtc_helper = &mrst_helper_funcs,
-       .crtc_funcs = &psb_intel_crtc_funcs,
-
-       .output_init = mrst_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       .backlight_init = mrst_backlight_init,
-#endif
-
-       .init_pm = mrst_init_pm,
-       .save_regs = mrst_save_display_registers,
-       .restore_regs = mrst_restore_display_registers,
-       .power_down = mrst_power_down,
-       .power_up = mrst_power_up,
-
-       .i2c_bus = 1,
-};
-
-/**
- *     mrst_chip_setup         -       perform the initial chip init
- *     @dev: Our drm_device
- *
- *     Figure out which incarnation we are and then scan the firmware for
- *     tables and information.
- */
-static int mrst_chip_setup(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       switch (mrst_device_ident(dev)) {
-       case DEVICE_OAKTRAIL:
-               /* Dual CRTC, PC compatible, HDMI, I2C #2 */
-               dev_priv->ops = &oaktrail_chip_ops;
-               mrst_hdmi_setup(dev);
-               return mid_chip_setup(dev);
-#if defined(CONFIG_X86_MRST)
-       case DEVICE_MOORESTOWN_MM:
-               /* Single CRTC, No HDMI, I2C #0, BL control */
-               mrst_lvds_cache_bl(dev);
-               dev_priv->ops = &mrst_mm_chip_ops;
-               return mid_chip_setup(dev);
-       case DEVICE_MOORESTOWN:
-               /* Dual CRTC, No HDMI(?), I2C #1 */
-               return mid_chip_setup(dev);
-#endif
-       default:
-               dev_err(dev->dev, "unsupported device type.\n");
-               return -ENODEV;
-       }
-}
-
-const struct psb_ops mrst_chip_ops = {
-       .name = "Moorestown",
-       .accel_2d = 1,
-       .pipes = 2,
-       .crtcs = 2,
-       .sgx_offset = MRST_SGX_OFFSET,
-
-       .chip_setup = mrst_chip_setup,
-       .crtc_helper = &mrst_helper_funcs,
-       .crtc_funcs = &psb_intel_crtc_funcs,
-
-       .output_init = mrst_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       .backlight_init = mrst_backlight_init,
-#endif
-
-       .init_pm = mrst_init_pm,
-       .save_regs = mrst_save_display_registers,
-       .restore_regs = mrst_restore_display_registers,
-       .power_down = mrst_power_down,
-       .power_up = mrst_power_up,
-
-       .i2c_bus = 2,
-};
-
diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c
deleted file mode 100644 (file)
index e66607e..0000000
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     Li Peng <peng.li@intel.com>
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_drv.h"
-
-#define HDMI_READ(reg)         readl(hdmi_dev->regs + (reg))
-#define HDMI_WRITE(reg, val)   writel(val, hdmi_dev->regs + (reg))
-
-#define HDMI_HCR       0x1000
-#define HCR_ENABLE_HDCP                (1 << 5)
-#define HCR_ENABLE_AUDIO       (1 << 2)
-#define HCR_ENABLE_PIXEL       (1 << 1)
-#define HCR_ENABLE_TMDS                (1 << 0)
-
-#define HDMI_HICR      0x1004
-#define HDMI_HSR       0x1008
-#define HDMI_HISR      0x100C
-#define HDMI_DETECT_HDP                (1 << 0)
-
-#define HDMI_VIDEO_REG 0x3000
-#define HDMI_UNIT_EN           (1 << 7)
-#define HDMI_MODE_OUTPUT       (1 << 0)
-#define HDMI_HBLANK_A  0x3100
-
-#define HDMI_AUDIO_CTRL        0x4000
-#define HDMI_ENABLE_AUDIO      (1 << 0)
-
-#define PCH_HTOTAL_B   0x3100
-#define PCH_HBLANK_B   0x3104
-#define PCH_HSYNC_B    0x3108
-#define PCH_VTOTAL_B   0x310C
-#define PCH_VBLANK_B   0x3110
-#define PCH_VSYNC_B    0x3114
-#define PCH_PIPEBSRC   0x311C
-
-#define PCH_PIPEB_DSL  0x3800
-#define PCH_PIPEB_SLC  0x3804
-#define PCH_PIPEBCONF  0x3808
-#define PCH_PIPEBSTAT  0x3824
-
-#define CDVO_DFT       0x5000
-#define CDVO_SLEWRATE  0x5004
-#define CDVO_STRENGTH  0x5008
-#define CDVO_RCOMP     0x500C
-
-#define DPLL_CTRL       0x6000
-#define DPLL_PDIV_SHIFT                16
-#define DPLL_PDIV_MASK         (0xf << 16)
-#define DPLL_PWRDN             (1 << 4)
-#define DPLL_RESET             (1 << 3)
-#define DPLL_FASTEN            (1 << 2)
-#define DPLL_ENSTAT            (1 << 1)
-#define DPLL_DITHEN            (1 << 0)
-
-#define DPLL_DIV_CTRL   0x6004
-#define DPLL_CLKF_MASK         0xffffffc0
-#define DPLL_CLKR_MASK         (0x3f)
-
-#define DPLL_CLK_ENABLE 0x6008
-#define DPLL_EN_DISP           (1 << 31)
-#define DPLL_SEL_HDMI          (1 << 8)
-#define DPLL_EN_HDMI           (1 << 1)
-#define DPLL_EN_VGA            (1 << 0)
-
-#define DPLL_ADJUST     0x600C
-#define DPLL_STATUS     0x6010
-#define DPLL_UPDATE     0x6014
-#define DPLL_DFT        0x6020
-
-struct intel_range {
-       int     min, max;
-};
-
-struct mrst_hdmi_limit {
-       struct intel_range vco, np, nr, nf;
-};
-
-struct mrst_hdmi_clock {
-       int np;
-       int nr;
-       int nf;
-       int dot;
-};
-
-#define VCO_MIN                320000
-#define VCO_MAX                1650000
-#define        NP_MIN          1
-#define        NP_MAX          15
-#define        NR_MIN          1
-#define        NR_MAX          64
-#define NF_MIN         2
-#define NF_MAX         4095
-
-static const struct mrst_hdmi_limit mrst_hdmi_limit = {
-       .vco = { .min = VCO_MIN,                .max = VCO_MAX },
-       .np  = { .min = NP_MIN,                 .max = NP_MAX  },
-       .nr  = { .min = NR_MIN,                 .max = NR_MAX  },
-       .nf  = { .min = NF_MIN,                 .max = NF_MAX  },
-};
-
-static void wait_for_vblank(struct drm_device *dev)
-{
-       /* FIXME: Can we do this as a sleep ? */
-       /* Wait for 20ms, i.e. one cycle at 50hz. */
-       mdelay(20);
-}
-
-static void scu_busy_loop(void *scu_base)
-{
-       u32 status = 0;
-       u32 loop_count = 0;
-
-       status = readl(scu_base + 0x04);
-       while (status & 1) {
-               udelay(1); /* scu processing time is in few u secods */
-               status = readl(scu_base + 0x04);
-               loop_count++;
-               /* break if scu doesn't reset busy bit after huge retry */
-               if (loop_count > 1000) {
-                       DRM_DEBUG_KMS("SCU IPC timed out");
-                       return;
-               }
-       }
-}
-
-static void mrst_hdmi_reset(struct drm_device *dev)
-{
-       void *base;
-       /* FIXME: at least make these defines */
-       unsigned int scu_ipc_mmio = 0xff11c000;
-       int scu_len = 1024;
-
-       base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
-       if (base == NULL) {
-               DRM_ERROR("failed to map SCU mmio\n");
-               return;
-       }
-
-       /* scu ipc: assert hdmi controller reset */
-       writel(0xff11d118, base + 0x0c);
-       writel(0x7fffffdf, base + 0x80);
-       writel(0x42005, base + 0x0);
-       scu_busy_loop(base);
-
-       /* scu ipc: de-assert hdmi controller reset */
-       writel(0xff11d118, base + 0x0c);
-       writel(0x7fffffff, base + 0x80);
-       writel(0x42005, base + 0x0);
-       scu_busy_loop(base);
-
-       iounmap(base);
-}
-
-static void mrst_hdmi_audio_enable(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-
-       HDMI_WRITE(HDMI_HCR, 0x67);
-       HDMI_READ(HDMI_HCR);
-
-       HDMI_WRITE(0x51a8, 0x10);
-       HDMI_READ(0x51a8);
-
-       HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1);
-       HDMI_READ(HDMI_AUDIO_CTRL);
-}
-
-static void mrst_hdmi_audio_disable(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-
-       HDMI_WRITE(0x51a8, 0x0);
-       HDMI_READ(0x51a8);
-
-       HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0);
-       HDMI_READ(HDMI_AUDIO_CTRL);
-
-       HDMI_WRITE(HDMI_HCR, 0x47);
-       HDMI_READ(HDMI_HCR);
-}
-
-void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct drm_device *dev = crtc->dev;
-       u32 temp;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_OFF:
-               /* Disable VGACNTRL */
-               REG_WRITE(VGACNTRL, 0x80000000);
-
-               /* Disable plane */
-               temp = REG_READ(DSPBCNTR);
-               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
-                       REG_READ(DSPBCNTR);
-                       /* Flush the plane changes */
-                       REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
-                       REG_READ(DSPBSURF);
-               }
-
-               /* Disable pipe B */
-               temp = REG_READ(PIPEBCONF);
-               if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(PIPEBCONF);
-               }
-
-               /* Disable LNW Pipes, etc */
-               temp = REG_READ(PCH_PIPEBCONF);
-               if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(PCH_PIPEBCONF);
-               }
-               /* wait for pipe off */
-               udelay(150);
-               /* Disable dpll */
-               temp = REG_READ(DPLL_CTRL);
-               if ((temp & DPLL_PWRDN) == 0) {
-                       REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
-                       REG_WRITE(DPLL_STATUS, 0x1);
-               }
-               /* wait for dpll off */
-               udelay(150);
-               break;
-       case DRM_MODE_DPMS_ON:
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-               /* Enable dpll */
-               temp = REG_READ(DPLL_CTRL);
-               if ((temp & DPLL_PWRDN) != 0) {
-                       REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
-                       temp = REG_READ(DPLL_CLK_ENABLE);
-                       REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
-                       REG_READ(DPLL_CLK_ENABLE);
-               }
-               /* wait for dpll warm up */
-               udelay(150);
-
-               /* Enable pipe B */
-               temp = REG_READ(PIPEBCONF);
-               if ((temp & PIPEACONF_ENABLE) == 0) {
-                       REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
-                       REG_READ(PIPEBCONF);
-               }
-
-               /* Enable LNW Pipe B */
-               temp = REG_READ(PCH_PIPEBCONF);
-               if ((temp & PIPEACONF_ENABLE) == 0) {
-                       REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
-                       REG_READ(PCH_PIPEBCONF);
-               }
-               wait_for_vblank(dev);
-
-               /* Enable plane */
-               temp = REG_READ(DSPBCNTR);
-               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
-                       REG_READ(DSPBSURF);
-               }
-               psb_intel_crtc_load_lut(crtc);
-       }
-       /* DSPARB */
-       REG_WRITE(DSPARB, 0x00003fbf);
-       /* FW1 */
-       REG_WRITE(0x70034, 0x3f880a0a);
-       /* FW2 */
-       REG_WRITE(0x70038, 0x0b060808);
-       /* FW4 */
-       REG_WRITE(0x70050, 0x08030404);
-       /* FW5 */
-       REG_WRITE(0x70054, 0x04040404);
-       /* LNC Chicken Bits */
-       REG_WRITE(0x70400, 0x4000);
-}
-
-
-static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode)
-{
-       static int dpms_mode = -1;
-
-       struct drm_device *dev = encoder->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-       u32 temp;
-
-       if (dpms_mode == mode)
-               return;
-
-       if (mode != DRM_MODE_DPMS_ON)
-               temp = 0x0;
-       else
-               temp = 0x99;
-
-       dpms_mode = mode;
-       HDMI_WRITE(HDMI_VIDEO_REG, temp);
-}
-
-static unsigned int htotal_calculate(struct drm_display_mode *mode)
-{
-       u32 htotal, new_crtc_htotal;
-
-       htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
-
-       /*
-        * 1024 x 768  new_crtc_htotal = 0x1024;
-        * 1280 x 1024 new_crtc_htotal = 0x0c34;
-        */
-       new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
-
-       return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
-}
-
-static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target,
-                               int refclk, struct mrst_hdmi_clock *best_clock)
-{
-       int np_min, np_max, nr_min, nr_max;
-       int np, nr, nf;
-
-       np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10);
-       np_max = mrst_hdmi_limit.vco.max / (target * 10);
-       if (np_min < mrst_hdmi_limit.np.min)
-               np_min = mrst_hdmi_limit.np.min;
-       if (np_max > mrst_hdmi_limit.np.max)
-               np_max = mrst_hdmi_limit.np.max;
-
-       nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
-       nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
-       if (nr_min < mrst_hdmi_limit.nr.min)
-               nr_min = mrst_hdmi_limit.nr.min;
-       if (nr_max > mrst_hdmi_limit.nr.max)
-               nr_max = mrst_hdmi_limit.nr.max;
-
-       np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
-       nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
-       nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
-       DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
-
-       /*
-        * 1024 x 768  np = 1; nr = 0x26; nf = 0x0fd8000;
-        * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
-        */
-       best_clock->np = np;
-       best_clock->nr = nr - 1;
-       best_clock->nf = (nf << 14);
-}
-
-int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc,
-                           struct drm_display_mode *mode,
-                           struct drm_display_mode *adjusted_mode,
-                           int x, int y,
-                           struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-       int pipe = 1;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
-       int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int refclk;
-       struct mrst_hdmi_clock clock;
-       u32 dspcntr, pipeconf, dpll, temp;
-       int dspcntr_reg = DSPBCNTR;
-
-       /* Disable the VGA plane that we never use */
-       REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
-       /* XXX: Disable the panel fitter if it was on our pipe */
-
-       /* Disable dpll if necessary */
-       dpll = REG_READ(DPLL_CTRL);
-       if ((dpll & DPLL_PWRDN) == 0) {
-               REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
-               REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
-               REG_WRITE(DPLL_STATUS, 0x1);
-       }
-       udelay(150);
-
-       /* reset controller: FIXME - can we sort out the ioremap mess ? */
-       iounmap(hdmi_dev->regs);
-       mrst_hdmi_reset(dev);
-
-       /* program and enable dpll */
-       refclk = 25000;
-       mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
-
-       /* Setting DPLL */
-       dpll = REG_READ(DPLL_CTRL);
-       dpll &= ~DPLL_PDIV_MASK;
-       dpll &= ~(DPLL_PWRDN | DPLL_RESET);
-       REG_WRITE(DPLL_CTRL, 0x00000008);
-       REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
-       REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
-       REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
-       REG_WRITE(DPLL_UPDATE, 0x80000000);
-       REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
-       udelay(150);
-
-       hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
-       if (hdmi_dev->regs == NULL) {
-               DRM_ERROR("failed to do hdmi mmio mapping\n");
-               return -ENOMEM;
-       }
-
-       /* configure HDMI */
-       HDMI_WRITE(0x1004, 0x1fd);
-       HDMI_WRITE(0x2000, 0x1);
-       HDMI_WRITE(0x2008, 0x0);
-       HDMI_WRITE(0x3130, 0x8);
-       HDMI_WRITE(0x101c, 0x1800810);
-
-       temp = htotal_calculate(adjusted_mode);
-       REG_WRITE(htot_reg, temp);
-       REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
-       REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
-       REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
-       REG_WRITE(pipesrc_reg,
-               ((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1));
-
-       REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
-       REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
-       REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
-       REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
-       REG_WRITE(PCH_PIPEBSRC,
-               ((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1));
-
-       temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
-       HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) |  temp);
-
-       REG_WRITE(dspsize_reg,
-                       ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-       REG_WRITE(dsppos_reg, 0);
-
-       /* Flush the plane changes */
-       {
-               struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-               crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-       }
-
-       /* Set up the display plane register */
-       dspcntr = REG_READ(dspcntr_reg);
-       dspcntr |= DISPPLANE_GAMMA_ENABLE;
-       dspcntr |= DISPPLANE_SEL_PIPE_B;
-       dspcntr |= DISPLAY_PLANE_ENABLE;
-
-       /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
-       pipeconf |= PIPEACONF_ENABLE;
-
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
-
-       REG_WRITE(PCH_PIPEBCONF, pipeconf);
-       REG_READ(PCH_PIPEBCONF);
-       wait_for_vblank(dev);
-
-       REG_WRITE(dspcntr_reg, dspcntr);
-       wait_for_vblank(dev);
-
-       return 0;
-}
-
-static int mrst_hdmi_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
-{
-       if (mode->clock > 165000)
-               return MODE_CLOCK_HIGH;
-       if (mode->clock < 20000)
-               return MODE_CLOCK_LOW;
-
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return MODE_NO_DBLESCAN;
-
-       return MODE_OK;
-}
-
-static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder,
-                                struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static enum drm_connector_status
-mrst_hdmi_detect(struct drm_connector *connector, bool force)
-{
-       enum drm_connector_status status;
-       struct drm_device *dev = connector->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-       u32 temp;
-
-       temp = HDMI_READ(HDMI_HSR);
-       DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
-
-       if ((temp & HDMI_DETECT_HDP) != 0)
-               status = connector_status_connected;
-       else
-               status = connector_status_disconnected;
-
-       return status;
-}
-
-static const unsigned char raw_edid[] = {
-       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
-       0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
-       0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
-       0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
-       0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
-       0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
-       0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
-       0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
-       0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
-       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
-};
-
-static int mrst_hdmi_get_modes(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct i2c_adapter *i2c_adap;
-       struct edid *edid;
-       struct drm_display_mode *mode, *t;
-       int i = 0, ret = 0;
-
-       i2c_adap = i2c_get_adapter(3);
-       if (i2c_adap == NULL) {
-               DRM_ERROR("No ddc adapter available!\n");
-               edid = (struct edid *)raw_edid;
-       } else {
-               edid = (struct edid *)raw_edid;
-               /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
-       }
-
-       if (edid) {
-               drm_mode_connector_update_edid_property(connector, edid);
-               ret = drm_add_edid_modes(connector, edid);
-               connector->display_info.raw_edid = NULL;
-       }
-
-       /*
-        * prune modes that require frame buffer bigger than stolen mem
-        */
-       list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
-               if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
-                       i++;
-                       drm_mode_remove(connector, mode);
-               }
-       }
-       return ret - i;
-}
-
-static void mrst_hdmi_mode_set(struct drm_encoder *encoder,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode)
-{
-       struct drm_device *dev = encoder->dev;
-
-       mrst_hdmi_audio_enable(dev);
-       return;
-}
-
-static void mrst_hdmi_destroy(struct drm_connector *connector)
-{
-       return;
-}
-
-static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = {
-       .dpms = mrst_hdmi_dpms,
-       .mode_fixup = mrst_hdmi_mode_fixup,
-       .prepare = psb_intel_encoder_prepare,
-       .mode_set = mrst_hdmi_mode_set,
-       .commit = psb_intel_encoder_commit,
-};
-
-static const struct drm_connector_helper_funcs
-                                       mrst_hdmi_connector_helper_funcs = {
-       .get_modes = mrst_hdmi_get_modes,
-       .mode_valid = mrst_hdmi_mode_valid,
-       .best_encoder = psb_intel_best_encoder,
-};
-
-static const struct drm_connector_funcs mrst_hdmi_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .detect = mrst_hdmi_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = mrst_hdmi_destroy,
-};
-
-static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = {
-       .destroy = mrst_hdmi_enc_destroy,
-};
-
-void mrst_hdmi_init(struct drm_device *dev,
-                                       struct psb_intel_mode_device *mode_dev)
-{
-       struct psb_intel_output *psb_intel_output;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-
-       psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       psb_intel_output->mode_dev = mode_dev;
-       connector = &psb_intel_output->base;
-       encoder = &psb_intel_output->enc;
-       drm_connector_init(dev, &psb_intel_output->base,
-                          &mrst_hdmi_connector_funcs,
-                          DRM_MODE_CONNECTOR_DVID);
-
-       drm_encoder_init(dev, &psb_intel_output->enc,
-                        &mrst_hdmi_enc_funcs,
-                        DRM_MODE_ENCODER_TMDS);
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-
-       psb_intel_output->type = INTEL_OUTPUT_HDMI;
-       drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs);
-       drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs);
-
-       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-       drm_sysfs_connector_add(connector);
-
-       return;
-}
-
-static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
-       {}
-};
-
-void mrst_hdmi_setup(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct pci_dev *pdev;
-       struct mrst_hdmi_dev *hdmi_dev;
-       int ret;
-
-       pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
-       if (!pdev)
-               return;
-
-       hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL);
-       if (!hdmi_dev) {
-               dev_err(dev->dev, "failed to allocate memory\n");
-               goto out;
-       }
-
-
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable hdmi controller\n");
-               goto free;
-       }
-
-       hdmi_dev->mmio = pci_resource_start(pdev, 0);
-       hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
-       hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
-       if (!hdmi_dev->regs) {
-               dev_err(dev->dev, "failed to map hdmi mmio\n");
-               goto free;
-       }
-
-       hdmi_dev->dev = pdev;
-       pci_set_drvdata(pdev, hdmi_dev);
-
-       /* Initialize i2c controller */
-       ret = mrst_hdmi_i2c_init(hdmi_dev->dev);
-       if (ret)
-               dev_err(dev->dev, "HDMI I2C initialization failed\n");
-
-       dev_priv->hdmi_priv = hdmi_dev;
-       mrst_hdmi_audio_disable(dev);
-       return;
-
-free:
-       kfree(hdmi_dev);
-out:
-       return;
-}
-
-void mrst_hdmi_teardown(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-       struct pci_dev *pdev;
-
-       if (hdmi_dev) {
-               pdev = hdmi_dev->dev;
-               pci_set_drvdata(pdev, NULL);
-               mrst_hdmi_i2c_exit(pdev);
-               iounmap(hdmi_dev->regs);
-               kfree(hdmi_dev);
-               pci_dev_put(pdev);
-       }
-}
-
-/* save HDMI register state */
-void mrst_hdmi_save(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-       int i;
-
-       /* dpll */
-       hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
-       hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
-       hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
-       hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
-       hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
-
-       /* pipe B */
-       dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
-       dev_priv->savePIPEBSRC  = PSB_RVDC32(PIPEBSRC);
-       dev_priv->saveHTOTAL_B  = PSB_RVDC32(HTOTAL_B);
-       dev_priv->saveHBLANK_B  = PSB_RVDC32(HBLANK_B);
-       dev_priv->saveHSYNC_B   = PSB_RVDC32(HSYNC_B);
-       dev_priv->saveVTOTAL_B  = PSB_RVDC32(VTOTAL_B);
-       dev_priv->saveVBLANK_B  = PSB_RVDC32(VBLANK_B);
-       dev_priv->saveVSYNC_B   = PSB_RVDC32(VSYNC_B);
-
-       hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
-       hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
-       hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
-       hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
-       hdmi_dev->savePCH_HSYNC_B  = PSB_RVDC32(PCH_HSYNC_B);
-       hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
-       hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
-       hdmi_dev->savePCH_VSYNC_B  = PSB_RVDC32(PCH_VSYNC_B);
-
-       /* plane */
-       dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
-       dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
-       dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
-       dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
-       dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
-       dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
-
-       /* cursor B */
-       dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
-       dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
-       dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
-
-       /* save palette */
-       for (i = 0; i < 256; i++)
-               dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
-}
-
-/* restore HDMI register state */
-void mrst_hdmi_restore(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-       int i;
-
-       /* dpll */
-       PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
-       PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
-       PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
-       PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
-       PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
-       DRM_UDELAY(150);
-
-       /* pipe */
-       PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC);
-       PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B);
-       PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B);
-       PSB_WVDC32(dev_priv->saveHSYNC_B,  HSYNC_B);
-       PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B);
-       PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B);
-       PSB_WVDC32(dev_priv->saveVSYNC_B,  VSYNC_B);
-
-       PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
-       PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
-       PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
-       PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B,  PCH_HSYNC_B);
-       PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
-       PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
-       PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B,  PCH_VSYNC_B);
-
-       PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF);
-       PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
-
-       /* plane */
-       PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF);
-       PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE);
-       PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF);
-       PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR);
-       PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF);
-
-       /* cursor B */
-       PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
-       PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
-       PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
-
-       /* restore palette */
-       for (i = 0; i < 256; i++)
-               PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2));
-}
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c
deleted file mode 100644 (file)
index 36e7edc..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     Li Peng <peng.li@intel.com>
- */
-
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-#include "psb_drv.h"
-
-#define HDMI_READ(reg)         readl(hdmi_dev->regs + (reg))
-#define HDMI_WRITE(reg, val)   writel(val, hdmi_dev->regs + (reg))
-
-#define HDMI_HCR       0x1000
-#define HCR_DETECT_HDP         (1 << 6)
-#define HCR_ENABLE_HDCP                (1 << 5)
-#define HCR_ENABLE_AUDIO       (1 << 2)
-#define HCR_ENABLE_PIXEL       (1 << 1)
-#define HCR_ENABLE_TMDS                (1 << 0)
-#define HDMI_HICR      0x1004
-#define HDMI_INTR_I2C_ERROR    (1 << 4)
-#define HDMI_INTR_I2C_FULL     (1 << 3)
-#define HDMI_INTR_I2C_DONE     (1 << 2)
-#define HDMI_INTR_HPD          (1 << 0)
-#define HDMI_HSR       0x1008
-#define HDMI_HISR      0x100C
-#define HDMI_HI2CRDB0  0x1200
-#define HDMI_HI2CHCR   0x1240
-#define HI2C_HDCP_WRITE                (0 << 2)
-#define HI2C_HDCP_RI_READ      (1 << 2)
-#define HI2C_HDCP_READ         (2 << 2)
-#define HI2C_EDID_READ         (3 << 2)
-#define HI2C_READ_CONTINUE     (1 << 1)
-#define HI2C_ENABLE_TRANSACTION        (1 << 0)
-
-#define HDMI_ICRH      0x1100
-#define HDMI_HI2CTDR0  0x1244
-#define HDMI_HI2CTDR1  0x1248
-
-#define I2C_STAT_INIT          0
-#define I2C_READ_DONE          1
-#define I2C_TRANSACTION_DONE   2
-
-struct hdmi_i2c_dev {
-       struct i2c_adapter *adap;
-       struct mutex i2c_lock;
-       struct completion complete;
-       int status;
-       struct i2c_msg *msg;
-       int buf_offset;
-};
-
-static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev)
-{
-       u32 temp;
-
-       temp = HDMI_READ(HDMI_HICR);
-       temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE);
-       HDMI_WRITE(HDMI_HICR, temp);
-       HDMI_READ(HDMI_HICR);
-}
-
-static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev)
-{
-       HDMI_WRITE(HDMI_HICR, 0x0);
-       HDMI_READ(HDMI_HICR);
-}
-
-static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
-{
-       struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
-       struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
-       u32 temp;
-
-       i2c_dev->status = I2C_STAT_INIT;
-       i2c_dev->msg = pmsg;
-       i2c_dev->buf_offset = 0;
-       INIT_COMPLETION(i2c_dev->complete);
-
-       /* Enable I2C transaction */
-       temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
-       HDMI_WRITE(HDMI_HI2CHCR, temp);
-       HDMI_READ(HDMI_HI2CHCR);
-
-       while (i2c_dev->status != I2C_TRANSACTION_DONE)
-               wait_for_completion_interruptible_timeout(&i2c_dev->complete,
-                                                               10 * HZ);
-
-       return 0;
-}
-
-static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg)
-{
-       /*
-        * XXX: i2c write seems isn't useful for EDID probe, don't do anything
-        */
-       return 0;
-}
-
-static int mrst_hdmi_i2c_access(struct i2c_adapter *adap,
-                               struct i2c_msg *pmsg,
-                               int num)
-{
-       struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
-       struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
-       int i, err = 0;
-
-       mutex_lock(&i2c_dev->i2c_lock);
-
-       /* Enable i2c unit */
-       HDMI_WRITE(HDMI_ICRH, 0x00008760);
-
-       /* Enable irq */
-       hdmi_i2c_irq_enable(hdmi_dev);
-       for (i = 0; i < num; i++) {
-               if (pmsg->len && pmsg->buf) {
-                       if (pmsg->flags & I2C_M_RD)
-                               err = xfer_read(adap, pmsg);
-                       else
-                               err = xfer_write(adap, pmsg);
-               }
-               pmsg++;         /* next message */
-       }
-
-       /* Disable irq */
-       hdmi_i2c_irq_disable(hdmi_dev);
-
-       mutex_unlock(&i2c_dev->i2c_lock);
-
-       return i;
-}
-
-static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
-}
-
-static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = {
-       .master_xfer    = mrst_hdmi_i2c_access,
-       .functionality  = mrst_hdmi_i2c_func,
-};
-
-static struct i2c_adapter mrst_hdmi_i2c_adapter = {
-       .name           = "mrst_hdmi_i2c",
-       .nr             = 3,
-       .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_DDC,
-       .algo           = &mrst_hdmi_i2c_algorithm,
-};
-
-static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev)
-{
-       struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
-       struct i2c_msg *msg = i2c_dev->msg;
-       u8 *buf = msg->buf;
-       u32 temp;
-       int i, offset;
-
-       offset = i2c_dev->buf_offset;
-       for (i = 0; i < 0x10; i++) {
-               temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4));
-               memcpy(buf + (offset + i * 4), &temp, 4);
-       }
-       i2c_dev->buf_offset += (0x10 * 4);
-
-       /* clearing read buffer full intr */
-       temp = HDMI_READ(HDMI_HISR);
-       HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL);
-       HDMI_READ(HDMI_HISR);
-
-       /* continue read transaction */
-       temp = HDMI_READ(HDMI_HI2CHCR);
-       HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE);
-       HDMI_READ(HDMI_HI2CHCR);
-
-       i2c_dev->status = I2C_READ_DONE;
-       return;
-}
-
-static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev)
-{
-       struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
-       u32 temp;
-
-       /* clear transaction done intr */
-       temp = HDMI_READ(HDMI_HISR);
-       HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE);
-       HDMI_READ(HDMI_HISR);
-
-
-       temp = HDMI_READ(HDMI_HI2CHCR);
-       HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION);
-       HDMI_READ(HDMI_HI2CHCR);
-
-       i2c_dev->status = I2C_TRANSACTION_DONE;
-       return;
-}
-
-static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev)
-{
-       struct mrst_hdmi_dev *hdmi_dev = dev;
-       struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
-       u32 stat;
-
-       stat = HDMI_READ(HDMI_HISR);
-
-       if (stat & HDMI_INTR_HPD) {
-               HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD);
-               HDMI_READ(HDMI_HISR);
-       }
-
-       if (stat & HDMI_INTR_I2C_FULL)
-               hdmi_i2c_read(hdmi_dev);
-
-       if (stat & HDMI_INTR_I2C_DONE)
-               hdmi_i2c_transaction_done(hdmi_dev);
-
-       complete(&i2c_dev->complete);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * choose alternate function 2 of GPIO pin 52, 53,
- * which is used by HDMI I2C logic
- */
-static void mrst_hdmi_i2c_gpio_fix(void)
-{
-       void *base;
-       unsigned int gpio_base = 0xff12c000;
-       int gpio_len = 0x1000;
-       u32 temp;
-
-       base = ioremap((resource_size_t)gpio_base, gpio_len);
-       if (base == NULL) {
-               DRM_ERROR("gpio ioremap fail\n");
-               return;
-       }
-
-       temp = readl(base + 0x44);
-       DRM_DEBUG_DRIVER("old gpio val %x\n", temp);
-       writel((temp | 0x00000a00), (base +  0x44));
-       temp = readl(base + 0x44);
-       DRM_DEBUG_DRIVER("new gpio val %x\n", temp);
-
-       iounmap(base);
-}
-
-int mrst_hdmi_i2c_init(struct pci_dev *dev)
-{
-       struct mrst_hdmi_dev *hdmi_dev;
-       struct hdmi_i2c_dev *i2c_dev;
-       int ret;
-
-       hdmi_dev = pci_get_drvdata(dev);
-
-       i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
-       if (i2c_dev == NULL) {
-               DRM_ERROR("Can't allocate interface\n");
-               ret = -ENOMEM;
-               goto exit;
-       }
-
-       i2c_dev->adap = &mrst_hdmi_i2c_adapter;
-       i2c_dev->status = I2C_STAT_INIT;
-       init_completion(&i2c_dev->complete);
-       mutex_init(&i2c_dev->i2c_lock);
-       i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev);
-       hdmi_dev->i2c_dev = i2c_dev;
-
-       /* Enable HDMI I2C function on gpio */
-       mrst_hdmi_i2c_gpio_fix();
-
-       /* request irq */
-       ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED,
-                         mrst_hdmi_i2c_adapter.name, hdmi_dev);
-       if (ret) {
-               DRM_ERROR("Failed to request IRQ for I2C controller\n");
-               goto err;
-       }
-
-       /* Adapter registration */
-       ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter);
-       return ret;
-
-err:
-       kfree(i2c_dev);
-exit:
-       return ret;
-}
-
-void mrst_hdmi_i2c_exit(struct pci_dev *dev)
-{
-       struct mrst_hdmi_dev *hdmi_dev;
-       struct hdmi_i2c_dev *i2c_dev;
-
-       hdmi_dev = pci_get_drvdata(dev);
-       if (i2c_del_adapter(&mrst_hdmi_i2c_adapter))
-               DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
-
-       i2c_dev = hdmi_dev->i2c_dev;
-       kfree(i2c_dev);
-       free_irq(dev->irq, hdmi_dev);
-}
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
deleted file mode 100644 (file)
index e7999a2..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright Â© 2006-2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- *     Dave Airlie <airlied@linux.ie>
- *     Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-#include <asm/mrst.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-/* The max/min PWM frequency in BPCR[31:17] - */
-/* The smallest number is 1 (not 0) that can fit in the
- * 15-bit field of the and then*/
-/* shifts to the left by one bit to get the actual 16-bit
- * value that the 15-bits correspond to.*/
-#define MRST_BLC_MAX_PWM_REG_FREQ          0xFFFF
-#define BRIGHTNESS_MAX_LEVEL 100
-
-/**
- * Sets the power state for the panel.
- */
-static void mrst_lvds_set_power(struct drm_device *dev,
-                               struct psb_intel_output *output, bool on)
-{
-       u32 pp_status;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       if (on) {
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
-                         POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
-               dev_priv->is_lvds_on = true;
-               if (dev_priv->ops->lvds_bl_power)
-                       dev_priv->ops->lvds_bl_power(dev, true);
-       } else {
-               if (dev_priv->ops->lvds_bl_power)
-                       dev_priv->ops->lvds_bl_power(dev, false);
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
-                         ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while (pp_status & PP_ON);
-               dev_priv->is_lvds_on = false;
-               pm_request_idle(&dev->pdev->dev);
-       }
-       gma_power_end(dev);
-}
-
-static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-
-       if (mode == DRM_MODE_DPMS_ON)
-               mrst_lvds_set_power(dev, output, true);
-       else
-               mrst_lvds_set_power(dev, output, false);
-
-       /* XXX: We never power down the LVDS pairs. */
-}
-
-static void mrst_lvds_mode_set(struct drm_encoder *encoder,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode)
-{
-       struct psb_intel_mode_device *mode_dev =
-                               enc_to_psb_intel_output(encoder)->mode_dev;
-       struct drm_device *dev = encoder->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 lvds_port;
-       uint64_t v = DRM_MODE_SCALE_FULLSCREEN;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       /*
-        * The LVDS pin pair will already have been turned on in the
-        * psb_intel_crtc_mode_set since it has a large impact on the DPLL
-        * settings.
-        */
-       lvds_port = (REG_READ(LVDS) &
-                   (~LVDS_PIPEB_SELECT)) |
-                   LVDS_PORT_EN |
-                   LVDS_BORDER_EN;
-
-       /* If the firmware says dither on Moorestown, or the BIOS does
-          on Oaktrail then enable dithering */
-       if (mode_dev->panel_wants_dither || dev_priv->lvds_dither)
-               lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE;
-
-       REG_WRITE(LVDS, lvds_port);
-
-       drm_connector_property_get_value(
-               &enc_to_psb_intel_output(encoder)->base,
-               dev->mode_config.scaling_mode_property,
-               &v);
-
-       if (v == DRM_MODE_SCALE_NO_SCALE)
-               REG_WRITE(PFIT_CONTROL, 0);
-       else if (v == DRM_MODE_SCALE_ASPECT) {
-               if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) ||
-                   (mode->hdisplay != adjusted_mode->crtc_hdisplay)) {
-                       if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) ==
-                           (mode->hdisplay * adjusted_mode->crtc_vdisplay))
-                               REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
-                       else if ((adjusted_mode->crtc_hdisplay *
-                               mode->vdisplay) > (mode->hdisplay *
-                               adjusted_mode->crtc_vdisplay))
-                               REG_WRITE(PFIT_CONTROL, PFIT_ENABLE |
-                                         PFIT_SCALING_MODE_PILLARBOX);
-                       else
-                               REG_WRITE(PFIT_CONTROL, PFIT_ENABLE |
-                                         PFIT_SCALING_MODE_LETTERBOX);
-               } else
-                       REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
-       } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/
-               REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
-
-       gma_power_end(dev);
-}
-
-static void mrst_lvds_prepare(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
-       mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
-                                         BACKLIGHT_DUTY_CYCLE_MASK);
-       mrst_lvds_set_power(dev, output, false);
-       gma_power_end(dev);
-}
-
-static u32 mrst_lvds_get_max_backlight(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 ret;
-
-       if (gma_power_begin(dev, false)) {
-               ret = ((REG_READ(BLC_PWM_CTL) &
-                         BACKLIGHT_MODULATION_FREQ_MASK) >>
-                         BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
-               gma_power_end(dev);
-       } else
-               ret = ((dev_priv->saveBLC_PWM_CTL &
-                         BACKLIGHT_MODULATION_FREQ_MASK) >>
-                         BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
-       return ret;
-}
-
-static void mrst_lvds_commit(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
-       if (mode_dev->backlight_duty_cycle == 0)
-               mode_dev->backlight_duty_cycle =
-                                       mrst_lvds_get_max_backlight(dev);
-       mrst_lvds_set_power(dev, output, true);
-}
-
-static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = {
-       .dpms = mrst_lvds_dpms,
-       .mode_fixup = psb_intel_lvds_mode_fixup,
-       .prepare = mrst_lvds_prepare,
-       .mode_set = mrst_lvds_mode_set,
-       .commit = mrst_lvds_commit,
-};
-
-static struct drm_display_mode lvds_configuration_modes[] = {
-       /* hard coded fixed mode for TPO LTPS LPJ040K001A */
-       { DRM_MODE("800x480",  DRM_MODE_TYPE_DRIVER, 33264, 800, 836,
-                  846, 1056, 0, 480, 489, 491, 525, 0, 0) },
-       /* hard coded fixed mode for LVDS 800x480 */
-       { DRM_MODE("800x480",  DRM_MODE_TYPE_DRIVER, 30994, 800, 801,
-                  802, 1024, 0, 480, 481, 482, 525, 0, 0) },
-       /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */
-       { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072,
-                  1104, 1184, 0, 600, 603, 604, 608, 0, 0) },
-       /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */
-       { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104,
-                  1136, 1184, 0, 600, 603, 604, 608, 0, 0) },
-       /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */
-       { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124,
-                  1204, 1312, 0, 600, 607, 610, 621, 0, 0) },
-       /* hard coded fixed mode for LVDS 1024x768 */
-       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
-                  1184, 1344, 0, 768, 771, 777, 806, 0, 0) },
-       /* hard coded fixed mode for LVDS 1366x768 */
-       { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430,
-                  1558, 1664, 0, 768, 769, 770, 776, 0, 0) },
-};
-
-/* Returns the panel fixed mode from configuration. */
-
-static struct drm_display_mode *
-mrst_lvds_get_configuration_mode(struct drm_device *dev)
-{
-       struct drm_display_mode *mode = NULL;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
-
-       if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/
-               mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-               if (!mode)
-                       return NULL;
-
-               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
-               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
-               mode->hsync_start = mode->hdisplay + \
-                               ((ti->hsync_offset_hi << 8) | \
-                               ti->hsync_offset_lo);
-               mode->hsync_end = mode->hsync_start + \
-                               ((ti->hsync_pulse_width_hi << 8) | \
-                               ti->hsync_pulse_width_lo);
-               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
-                                                       ti->hblank_lo);
-               mode->vsync_start = \
-                       mode->vdisplay + ((ti->vsync_offset_hi << 4) | \
-                                               ti->vsync_offset_lo);
-               mode->vsync_end = \
-                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \
-                                               ti->vsync_pulse_width_lo);
-               mode->vtotal = mode->vdisplay + \
-                               ((ti->vblank_hi << 8) | ti->vblank_lo);
-               mode->clock = ti->pixel_clock * 10;
-#if 0
-               printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay);
-               printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay);
-               printk(KERN_INFO "HSS is %d\n", mode->hsync_start);
-               printk(KERN_INFO "HSE is %d\n", mode->hsync_end);
-               printk(KERN_INFO "htotal is %d\n", mode->htotal);
-               printk(KERN_INFO "VSS is %d\n", mode->vsync_start);
-               printk(KERN_INFO "VSE is %d\n", mode->vsync_end);
-               printk(KERN_INFO "vtotal is %d\n", mode->vtotal);
-               printk(KERN_INFO "clock is %d\n", mode->clock);
-#endif
-       } else
-               mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]);
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       return mode;
-}
-
-/**
- * mrst_lvds_init - setup LVDS connectors on this device
- * @dev: drm device
- *
- * Create the connector, register the LVDS DDC bus, and try to figure out what
- * modes we can display on the LVDS panel (if present).
- */
-void mrst_lvds_init(struct drm_device *dev,
-                   struct psb_intel_mode_device *mode_dev)
-{
-       struct psb_intel_output *psb_intel_output;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-       struct drm_psb_private *dev_priv =
-                               (struct drm_psb_private *) dev->dev_private;
-       struct edid *edid;
-       int ret = 0;
-       struct i2c_adapter *i2c_adap;
-       struct drm_display_mode *scan;  /* *modes, *bios_mode; */
-
-       psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       psb_intel_output->mode_dev = mode_dev;
-       connector = &psb_intel_output->base;
-       encoder = &psb_intel_output->enc;
-       dev_priv->is_lvds_on = true;
-       drm_connector_init(dev, &psb_intel_output->base,
-                          &psb_intel_lvds_connector_funcs,
-                          DRM_MODE_CONNECTOR_LVDS);
-
-       drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
-                        DRM_MODE_ENCODER_LVDS);
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-       psb_intel_output->type = INTEL_OUTPUT_LVDS;
-
-       drm_encoder_helper_add(encoder, &mrst_lvds_helper_funcs);
-       drm_connector_helper_add(connector,
-                                &psb_intel_lvds_connector_helper_funcs);
-       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-
-       drm_connector_attach_property(connector,
-                                       dev->mode_config.scaling_mode_property,
-                                       DRM_MODE_SCALE_FULLSCREEN);
-       drm_connector_attach_property(connector,
-                                       dev_priv->backlight_property,
-                                       BRIGHTNESS_MAX_LEVEL);
-
-       mode_dev->panel_wants_dither = false;
-       if (dev_priv->vbt_data.size != 0x00)
-               mode_dev->panel_wants_dither = (dev_priv->gct_data.
-                       Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE);
-
-       /*
-        * LVDS discovery:
-        * 1) check for EDID on DDC
-        * 2) check for VBT data
-        * 3) check to see if LVDS is already on
-        *    if none of the above, no panel
-        * 4) make sure lid is open
-        *    if closed, act like it's not there for now
-        */
-
-       i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
-
-       if (i2c_adap == NULL)
-               dev_err(dev->dev, "No ddc adapter available!\n");
-       /*
-        * Attempt to get the fixed panel mode from DDC.  Assume that the
-        * preferred mode is the right one.
-        */
-       if (i2c_adap) {
-               edid = drm_get_edid(connector, i2c_adap);
-               if (edid) {
-                       drm_mode_connector_update_edid_property(connector,
-                                                                       edid);
-                       ret = drm_add_edid_modes(connector, edid);
-                       kfree(edid);
-               }
-
-               list_for_each_entry(scan, &connector->probed_modes, head) {
-                       if (scan->type & DRM_MODE_TYPE_PREFERRED) {
-                               mode_dev->panel_fixed_mode =
-                                   drm_mode_duplicate(dev, scan);
-                               goto out;       /* FIXME: check for quirks */
-                       }
-               }
-       }
-       /*
-        * If we didn't get EDID, try geting panel timing
-        * from configuration data
-        */
-       mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev);
-
-       if (mode_dev->panel_fixed_mode) {
-               mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
-               goto out;       /* FIXME: check for quirks */
-       }
-
-       /* If we still don't have a mode after all that, give up. */
-       if (!mode_dev->panel_fixed_mode) {
-               dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
-               goto failed_find;
-       }
-
-out:
-       drm_sysfs_connector_add(connector);
-       return;
-
-failed_find:
-       dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
-       if (psb_intel_output->ddc_bus)
-               psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-
-/* failed_ddc: */
-
-       drm_encoder_cleanup(encoder);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
deleted file mode 100644 (file)
index 4082570..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- *    Alan Cox <alan@linux.intel.com>
- */
-
-#include "power.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <linux/mutex.h>
-#include <linux/pm_runtime.h>
-
-static struct mutex power_mutex;       /* Serialize power ops */
-static spinlock_t power_ctrl_lock;     /* Serialize power claim */
-
-/**
- *     gma_power_init          -       initialise power manager
- *     @dev: our device
- *
- *     Set up for power management tracking of our hardware.
- */
-void gma_power_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       /* FIXME: Move APM/OSPM base into relevant device code */
-       dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
-       dev_priv->ospm_base &= 0xffff;
-
-       dev_priv->display_power = true; /* We start active */
-       dev_priv->display_count = 0;    /* Currently no users */
-       dev_priv->suspended = false;    /* And not suspended */
-       spin_lock_init(&power_ctrl_lock);
-       mutex_init(&power_mutex);
-
-       dev_priv->ops->init_pm(dev);
-}
-
-/**
- *     gma_power_uninit        -       end power manager
- *     @dev: device to end for
- *
- *     Undo the effects of gma_power_init
- */
-void gma_power_uninit(struct drm_device *dev)
-{
-       pm_runtime_disable(&dev->pdev->dev);
-       pm_runtime_set_suspended(&dev->pdev->dev);
-}
-
-/**
- *     gma_suspend_display     -       suspend the display logic
- *     @dev: our DRM device
- *
- *     Suspend the display logic of the graphics interface
- */
-static void gma_suspend_display(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (!dev_priv->display_power)
-               return;
-       dev_priv->ops->save_regs(dev);
-       dev_priv->ops->power_down(dev);
-       dev_priv->display_power = false;
-}
-
-/**
- *     gma_resume_display      -       resume display side logic
- *
- *     Resume the display hardware restoring state and enabling
- *     as necessary.
- */
-static void gma_resume_display(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (dev_priv->display_power)
-               return;
-
-       /* turn on the display power island */
-       dev_priv->ops->power_up(dev);
-       dev_priv->suspended = false;
-       dev_priv->display_power = true;
-
-       PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
-       pci_write_config_word(pdev, PSB_GMCH_CTRL,
-                       dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-       dev_priv->ops->restore_regs(dev);
-}
-
-/**
- *     gma_suspend_pci         -       suspend PCI side
- *     @pdev: PCI device
- *
- *     Perform the suspend processing on our PCI device state
- */
-static void gma_suspend_pci(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int bsm, vbt;
-
-       if (dev_priv->suspended)
-               return;
-
-       pci_save_state(pdev);
-       pci_read_config_dword(pdev, 0x5C, &bsm);
-       dev_priv->saveBSM = bsm;
-       pci_read_config_dword(pdev, 0xFC, &vbt);
-       dev_priv->saveVBT = vbt;
-       pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
-       pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
-
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-
-       dev_priv->suspended = true;
-}
-
-/**
- *     gma_resume_pci          -       resume helper
- *     @dev: our PCI device
- *
- *     Perform the resume processing on our PCI device state - rewrite
- *     register state and re-enable the PCI device
- */
-static bool gma_resume_pci(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int ret;
-
-       if (!dev_priv->suspended)
-               return true;
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
-       pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
-       /* restoring MSI address and data in PCIx space */
-       pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
-       pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
-       ret = pci_enable_device(pdev);
-
-       if (ret != 0)
-               dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
-       else
-               dev_priv->suspended = false;
-       return !dev_priv->suspended;
-}
-
-/**
- *     gma_power_suspend               -       bus callback for suspend
- *     @pdev: our PCI device
- *     @state: suspend type
- *
- *     Called back by the PCI layer during a suspend of the system. We
- *     perform the necessary shut down steps and save enough state that
- *     we can undo this when resume is called.
- */
-int gma_power_suspend(struct device *_dev)
-{
-       struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
-       struct drm_device *dev = pci_get_drvdata(pdev);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       mutex_lock(&power_mutex);
-       if (!dev_priv->suspended) {
-               if (dev_priv->display_count) {
-                       mutex_unlock(&power_mutex);
-                       return -EBUSY;
-               }
-               psb_irq_uninstall(dev);
-               gma_suspend_display(dev);
-               gma_suspend_pci(pdev);
-       }
-       mutex_unlock(&power_mutex);
-       return 0;
-}
-
-/**
- *     gma_power_resume                -       resume power
- *     @pdev: PCI device
- *
- *     Resume the PCI side of the graphics and then the displays
- */
-int gma_power_resume(struct device *_dev)
-{
-       struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
-       struct drm_device *dev = pci_get_drvdata(pdev);
-
-       mutex_lock(&power_mutex);
-       gma_resume_pci(pdev);
-       gma_resume_display(pdev);
-       psb_irq_preinstall(dev);
-       psb_irq_postinstall(dev);
-       mutex_unlock(&power_mutex);
-       return 0;
-}
-
-/**
- *     gma_power_is_on         -       returne true if power is on
- *     @dev: our DRM device
- *
- *     Returns true if the display island power is on at this moment
- */
-bool gma_power_is_on(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       return dev_priv->display_power;
-}
-
-/**
- *     gma_power_begin         -       begin requiring power
- *     @dev: our DRM device
- *     @force_on: true to force power on
- *
- *     Begin an action that requires the display power island is enabled.
- *     We refcount the islands.
- */
-bool gma_power_begin(struct drm_device *dev, bool force_on)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int ret;
-       unsigned long flags;
-
-       spin_lock_irqsave(&power_ctrl_lock, flags);
-       /* Power already on ? */
-       if (dev_priv->display_power) {
-               dev_priv->display_count++;
-               pm_runtime_get(&dev->pdev->dev);
-               spin_unlock_irqrestore(&power_ctrl_lock, flags);
-               return true;
-       }
-       if (force_on == false)
-               goto out_false;
-
-       /* Ok power up needed */
-       ret = gma_resume_pci(dev->pdev);
-       if (ret == 0) {
-               /* FIXME: we want to defer this for Medfield/Oaktrail */
-               gma_resume_display(dev->pdev);
-               psb_irq_preinstall(dev);
-               psb_irq_postinstall(dev);
-               pm_runtime_get(&dev->pdev->dev);
-               dev_priv->display_count++;
-               spin_unlock_irqrestore(&power_ctrl_lock, flags);
-               return true;
-       }
-out_false:
-       spin_unlock_irqrestore(&power_ctrl_lock, flags);
-       return false;
-}
-
-/**
- *     gma_power_end           -       end use of power
- *     @dev: Our DRM device
- *
- *     Indicate that one of our gma_power_begin() requested periods when
- *     the diplay island power is needed has completed.
- */
-void gma_power_end(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long flags;
-       spin_lock_irqsave(&power_ctrl_lock, flags);
-       dev_priv->display_count--;
-       WARN_ON(dev_priv->display_count < 0);
-       spin_unlock_irqrestore(&power_ctrl_lock, flags);
-       pm_runtime_put(&dev->pdev->dev);
-}
-
-int psb_runtime_suspend(struct device *dev)
-{
-       return gma_power_suspend(dev);
-}
-
-int psb_runtime_resume(struct device *dev)
-{
-       return gma_power_resume(dev);;
-}
-
-int psb_runtime_idle(struct device *dev)
-{
-       struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
-       struct drm_psb_private *dev_priv = drmdev->dev_private;
-       if (dev_priv->display_count)
-               return 0;
-       else
-               return 1;
-}
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h
deleted file mode 100644 (file)
index 1969d2e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
-
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- *    Alan Cox <alan@linux.intel.com>
- */
-#ifndef _PSB_POWERMGMT_H_
-#define _PSB_POWERMGMT_H_
-
-#include <linux/pci.h>
-#include <drm/drmP.h>
-
-void gma_power_init(struct drm_device *dev);
-void gma_power_uninit(struct drm_device *dev);
-
-/*
- * The kernel bus power management  will call these functions
- */
-int gma_power_suspend(struct device *dev);
-int gma_power_resume(struct device *dev);
-
-/*
- * These are the functions the driver should use to wrap all hw access
- * (i.e. register reads and writes)
- */
-bool gma_power_begin(struct drm_device *dev, bool force);
-void gma_power_end(struct drm_device *dev);
-
-/*
- * Use this function to do an instantaneous check for if the hw is on.
- * Only use this in cases where you know the mutex is already held such
- * as in irq install/uninstall and you need to
- * prevent a deadlock situation.  Otherwise use gma_power_begin().
- */
-bool gma_power_is_on(struct drm_device *dev);
-
-/*
- * GFX-Runtime PM callbacks
- */
-int psb_runtime_suspend(struct device *dev);
-int psb_runtime_resume(struct device *dev);
-int psb_runtime_idle(struct device *dev);
-
-#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
deleted file mode 100644 (file)
index b97aa78..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-
-
-static int psb_output_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       psb_intel_lvds_init(dev, &dev_priv->mode_dev);
-       psb_intel_sdvo_init(dev, SDVOB);
-       return 0;
-}
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-/*
- *     Poulsbo Backlight Interfaces
- */
-
-#define BLC_PWM_PRECISION_FACTOR 100   /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-
-#define PSB_BLC_PWM_PRECISION_FACTOR    10
-#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT    (16)
-
-static int psb_brightness;
-static struct backlight_device *psb_backlight_device;
-
-static int psb_get_brightness(struct backlight_device *bd)
-{
-       /* return locally cached var instead of HW read (due to DPST etc.) */
-       /* FIXME: ideally return actual value in case firmware fiddled with
-          it */
-       return psb_brightness;
-}
-
-
-static int psb_backlight_setup(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long core_clock;
-       /* u32 bl_max_freq; */
-       /* unsigned long value; */
-       u16 bl_max_freq;
-       uint32_t value;
-       uint32_t blc_pwm_precision_factor;
-
-       /* get bl_max_freq and pol from dev_priv*/
-       if (!dev_priv->lvds_bl) {
-               dev_err(dev->dev, "Has no valid LVDS backlight info\n");
-               return -ENOENT;
-       }
-       bl_max_freq = dev_priv->lvds_bl->freq;
-       blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
-
-       core_clock = dev_priv->core_freq;
-
-       value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
-       value *= blc_pwm_precision_factor;
-       value /= bl_max_freq;
-       value /= blc_pwm_precision_factor;
-
-       if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
-                value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
-                               return -ERANGE;
-       else {
-               value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
-               REG_WRITE(BLC_PWM_CTL,
-                       (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
-       }
-       return 0;
-}
-
-static int psb_set_brightness(struct backlight_device *bd)
-{
-       struct drm_device *dev = bl_get_data(psb_backlight_device);
-       int level = bd->props.brightness;
-
-       /* Percentage 1-100% being valid */
-       if (level < 1)
-               level = 1;
-
-       psb_intel_lvds_set_brightness(dev, level);
-       psb_brightness = level;
-       return 0;
-}
-
-static const struct backlight_ops psb_ops = {
-       .get_brightness = psb_get_brightness,
-       .update_status  = psb_set_brightness,
-};
-
-static int psb_backlight_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       int ret;
-       struct backlight_properties props;
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.max_brightness = 100;
-       props.type = BACKLIGHT_PLATFORM;
-
-       psb_backlight_device = backlight_device_register("psb-bl",
-                                       NULL, (void *)dev, &psb_ops, &props);
-       if (IS_ERR(psb_backlight_device))
-               return PTR_ERR(psb_backlight_device);
-
-       ret = psb_backlight_setup(dev);
-       if (ret < 0) {
-               backlight_device_unregister(psb_backlight_device);
-               psb_backlight_device = NULL;
-               return ret;
-       }
-       psb_backlight_device->props.brightness = 100;
-       psb_backlight_device->props.max_brightness = 100;
-       backlight_update_status(psb_backlight_device);
-       dev_priv->backlight_device = psb_backlight_device;
-       return 0;
-}
-
-#endif
-
-/*
- *     Provide the Poulsbo specific chip logic and low level methods
- *     for power management
- */
-
-static void psb_init_pm(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
-       gating &= ~3;   /* Disable 2D clock gating */
-       gating |= 1;
-       PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
-       PSB_RSGX32(PSB_CR_CLKGATECTL);
-}
-
-/**
- *     psb_save_display_registers      -       save registers lost on suspend
- *     @dev: our DRM device
- *
- *     Save the state we need in order to be able to restore the interface
- *     upon resume from suspend
- */
-static int psb_save_display_registers(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
-       struct drm_connector *connector;
-
-       /* Display arbitration control + watermarks */
-       dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
-       dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
-       dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
-       dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
-       dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
-       dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
-       dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
-       dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
-       /* Save crtc and output state */
-       mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (drm_helper_crtc_in_use(crtc))
-                       crtc->funcs->save(crtc);
-       }
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               connector->funcs->save(connector);
-
-       mutex_unlock(&dev->mode_config.mutex);
-       return 0;
-}
-
-/**
- *     psb_restore_display_registers   -       restore lost register state
- *     @dev: our DRM device
- *
- *     Restore register state that was lost during suspend and resume.
- */
-static int psb_restore_display_registers(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
-       struct drm_connector *connector;
-
-       /* Display arbitration + watermarks */
-       PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
-       PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
-       PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
-       PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
-       PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
-       PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
-       PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
-       PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
-       /*make sure VGA plane is off. it initializes to on after reset!*/
-       PSB_WVDC32(0x80000000, VGACNTRL);
-
-       mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-               if (drm_helper_crtc_in_use(crtc))
-                       crtc->funcs->restore(crtc);
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               connector->funcs->restore(connector);
-
-       mutex_unlock(&dev->mode_config.mutex);
-       return 0;
-}
-
-static int psb_power_down(struct drm_device *dev)
-{
-       return 0;
-}
-
-static int psb_power_up(struct drm_device *dev)
-{
-       return 0;
-}
-
-static void psb_get_core_freq(struct drm_device *dev)
-{
-       uint32_t clock;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
-       /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
-       pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
-       pci_read_config_dword(pci_root, 0xD4, &clock);
-       pci_dev_put(pci_root);
-
-       switch (clock & 0x07) {
-       case 0:
-               dev_priv->core_freq = 100;
-               break;
-       case 1:
-               dev_priv->core_freq = 133;
-               break;
-       case 2:
-               dev_priv->core_freq = 150;
-               break;
-       case 3:
-               dev_priv->core_freq = 178;
-               break;
-       case 4:
-               dev_priv->core_freq = 200;
-               break;
-       case 5:
-       case 6:
-       case 7:
-               dev_priv->core_freq = 266;
-       default:
-               dev_priv->core_freq = 0;
-       }
-}
-
-static int psb_chip_setup(struct drm_device *dev)
-{
-       psb_get_core_freq(dev);
-       gma_intel_opregion_init(dev);
-       psb_intel_init_bios(dev);
-       return 0;
-}
-
-const struct psb_ops psb_chip_ops = {
-       .name = "Poulsbo",
-       .accel_2d = 1,
-       .pipes = 2,
-       .crtcs = 2,
-       .sgx_offset = PSB_SGX_OFFSET,
-       .chip_setup = psb_chip_setup,
-
-       .crtc_helper = &psb_intel_helper_funcs,
-       .crtc_funcs = &psb_intel_crtc_funcs,
-
-       .output_init = psb_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       .backlight_init = psb_backlight_init,
-#endif
-
-       .init_pm = psb_init_pm,
-       .save_regs = psb_save_display_registers,
-       .restore_regs = psb_restore_display_registers,
-       .power_down = psb_power_down,
-       .power_up = psb_power_up,
-};
-
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
deleted file mode 100644 (file)
index 0da8468..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#ifndef _PSB_DRM_H_
-#define _PSB_DRM_H_
-
-#define PSB_NUM_PIPE 3
-
-#define PSB_GPU_ACCESS_READ         (1ULL << 32)
-#define PSB_GPU_ACCESS_WRITE        (1ULL << 33)
-#define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
-
-#define PSB_BO_FLAG_COMMAND         (1ULL << 52)
-
-/*
- * Feedback components:
- */
-
-struct drm_psb_sizes_arg {
-       u32 ta_mem_size;
-       u32 mmu_size;
-       u32 pds_size;
-       u32 rastgeom_size;
-       u32 tt_size;
-       u32 vram_size;
-};
-
-struct drm_psb_dpst_lut_arg {
-       uint8_t lut[256];
-       int output_id;
-};
-
-#define PSB_DC_CRTC_SAVE 0x01
-#define PSB_DC_CRTC_RESTORE 0x02
-#define PSB_DC_OUTPUT_SAVE 0x04
-#define PSB_DC_OUTPUT_RESTORE 0x08
-#define PSB_DC_CRTC_MASK 0x03
-#define PSB_DC_OUTPUT_MASK 0x0C
-
-struct drm_psb_dc_state_arg {
-       u32 flags;
-       u32 obj_id;
-};
-
-struct drm_psb_mode_operation_arg {
-       u32 obj_id;
-       u16 operation;
-       struct drm_mode_modeinfo mode;
-       void *data;
-};
-
-struct drm_psb_stolen_memory_arg {
-       u32 base;
-       u32 size;
-};
-
-/*Display Register Bits*/
-#define REGRWBITS_PFIT_CONTROLS                        (1 << 0)
-#define REGRWBITS_PFIT_AUTOSCALE_RATIOS                (1 << 1)
-#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2)
-#define REGRWBITS_PIPEASRC                     (1 << 3)
-#define REGRWBITS_PIPEBSRC                     (1 << 4)
-#define REGRWBITS_VTOTAL_A                     (1 << 5)
-#define REGRWBITS_VTOTAL_B                     (1 << 6)
-#define REGRWBITS_DSPACNTR     (1 << 8)
-#define REGRWBITS_DSPBCNTR     (1 << 9)
-#define REGRWBITS_DSPCCNTR     (1 << 10)
-
-/*Overlay Register Bits*/
-#define OV_REGRWBITS_OVADD                     (1 << 0)
-#define OV_REGRWBITS_OGAM_ALL                  (1 << 1)
-
-#define OVC_REGRWBITS_OVADD                  (1 << 2)
-#define OVC_REGRWBITS_OGAM_ALL                 (1 << 3)
-
-struct drm_psb_register_rw_arg {
-       u32 b_force_hw_on;
-
-       u32 display_read_mask;
-       u32 display_write_mask;
-
-       struct {
-               u32 pfit_controls;
-               u32 pfit_autoscale_ratios;
-               u32 pfit_programmed_scale_ratios;
-               u32 pipeasrc;
-               u32 pipebsrc;
-               u32 vtotal_a;
-               u32 vtotal_b;
-       } display;
-
-       u32 overlay_read_mask;
-       u32 overlay_write_mask;
-
-       struct {
-               u32 OVADD;
-               u32 OGAMC0;
-               u32 OGAMC1;
-               u32 OGAMC2;
-               u32 OGAMC3;
-               u32 OGAMC4;
-               u32 OGAMC5;
-               u32 IEP_ENABLED;
-               u32 IEP_BLE_MINMAX;
-               u32 IEP_BSSCC_CONTROL;
-               u32 b_wait_vblank;
-       } overlay;
-
-       u32 sprite_enable_mask;
-       u32 sprite_disable_mask;
-
-       struct {
-               u32 dspa_control;
-               u32 dspa_key_value;
-               u32 dspa_key_mask;
-               u32 dspc_control;
-               u32 dspc_stride;
-               u32 dspc_position;
-               u32 dspc_linear_offset;
-               u32 dspc_size;
-               u32 dspc_surface;
-       } sprite;
-
-       u32 subpicture_enable_mask;
-       u32 subpicture_disable_mask;
-};
-
-/* Controlling the kernel modesetting buffers */
-
-#define DRM_PSB_SIZES           0x07
-#define DRM_PSB_FUSE_REG       0x08
-#define DRM_PSB_DC_STATE       0x0A
-#define DRM_PSB_ADB            0x0B
-#define DRM_PSB_MODE_OPERATION 0x0C
-#define DRM_PSB_STOLEN_MEMORY  0x0D
-#define DRM_PSB_REGISTER_RW    0x0E
-
-/*
- * NOTE: Add new commands here, but increment
- * the values below and increment their
- * corresponding defines where they're
- * defined elsewhere.
- */
-
-#define DRM_PSB_GEM_CREATE     0x10
-#define DRM_PSB_2D_OP          0x11
-#define DRM_PSB_GEM_MMAP       0x12
-#define DRM_PSB_DPST           0x1B
-#define DRM_PSB_GAMMA          0x1C
-#define DRM_PSB_DPST_BL                0x1D
-#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
-
-#define PSB_MODE_OPERATION_MODE_VALID  0x01
-#define PSB_MODE_OPERATION_SET_DC_BASE  0x02
-
-struct drm_psb_get_pipe_from_crtc_id_arg {
-       /** ID of CRTC being requested **/
-       u32 crtc_id;
-
-       /** pipe of requested CRTC **/
-       u32 pipe;
-};
-
-/* FIXME: move this into a medfield header once we are sure it isn't needed for an
-   ioctl  */
-struct psb_drm_dpu_rect {  
-       int x, y;             
-       int width, height;    
-};  
-
-struct drm_psb_gem_create {
-       __u64 size;
-       __u32 handle;
-       __u32 flags;
-#define PSB_GEM_CREATE_STOLEN          1       /* Stolen memory can be used */
-};
-
-#define PSB_2D_OP_BUFLEN               16
-
-struct drm_psb_2d_op {
-       __u32 src;              /* Handles, only src supported right now */
-       __u32 dst;
-       __u32 mask;
-       __u32 pat;
-       __u32 size;             /* In dwords of command */
-       __u32 spare;            /* And bumps array to u64 align */
-       __u32 cmd[PSB_2D_OP_BUFLEN];
-};
-
-struct drm_psb_gem_mmap {
-       __u32 handle;
-       __u32 pad;
-       /**
-        * Fake offset to use for subsequent mmap call
-        *
-        * This is a fixed-size type for 32/64 compatibility.
-        */
-       __u64 offset;
-};
-
-#endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
deleted file mode 100644 (file)
index 9581680..0000000
+++ /dev/null
@@ -1,1230 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "framebuffer.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#include "mid_bios.h"
-#include "mdfld_dsi_dbi.h"
-#include <drm/drm_pciids.h>
-#include "power.h"
-#include <linux/cpu.h>
-#include <linux/notifier.h>
-#include <linux/spinlock.h>
-#include <linux/pm_runtime.h>
-#include <linux/module.h>
-#include <acpi/video.h>
-
-static int drm_psb_trap_pagefaults;
-
-int drm_psb_no_fb;
-
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-MODULE_PARM_DESC(no_fb, "Disable FBdev");
-MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
-module_param_named(no_fb, drm_psb_no_fb, int, 0600);
-module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
-
-
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
-       { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
-       { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
-#if defined(CONFIG_DRM_PSB_MRST)
-       { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-       { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-#endif
-#if defined(CONFIG_DRM_PSB_MFLD)
-       { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-       { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-#endif
-#if defined(CONFIG_DRM_PSB_CDV)
-       { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-       { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-#endif
-       { 0, 0, 0}
-};
-MODULE_DEVICE_TABLE(pci, pciidlist);
-
-/*
- * Standard IOCTLs.
- */
-
-#define DRM_IOCTL_PSB_SIZES    \
-               DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
-                       struct drm_psb_sizes_arg)
-#define DRM_IOCTL_PSB_FUSE_REG \
-               DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_PSB_DC_STATE \
-               DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
-                       struct drm_psb_dc_state_arg)
-#define DRM_IOCTL_PSB_ADB      \
-               DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_PSB_MODE_OPERATION   \
-               DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
-                        struct drm_psb_mode_operation_arg)
-#define DRM_IOCTL_PSB_STOLEN_MEMORY    \
-               DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
-                        struct drm_psb_stolen_memory_arg)
-#define DRM_IOCTL_PSB_REGISTER_RW      \
-               DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
-                        struct drm_psb_register_rw_arg)
-#define DRM_IOCTL_PSB_DPST     \
-               DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
-                        uint32_t)
-#define DRM_IOCTL_PSB_GAMMA    \
-               DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
-                        struct drm_psb_dpst_lut_arg)
-#define DRM_IOCTL_PSB_DPST_BL  \
-               DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
-                        uint32_t)
-#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID    \
-               DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
-                        struct drm_psb_get_pipe_from_crtc_id_arg)
-#define DRM_IOCTL_PSB_GEM_CREATE       \
-               DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
-                        struct drm_psb_gem_create)
-#define DRM_IOCTL_PSB_2D_OP    \
-               DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
-                        struct drm_psb_2d_op)
-#define DRM_IOCTL_PSB_GEM_MMAP \
-               DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
-                        struct drm_psb_gem_mmap)
-
-static int psb_sizes_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
-                             struct drm_file *file_priv);
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
-                                  struct drm_file *file_priv);
-static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv);
-static int psb_dpst_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv);
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
-                            struct drm_file *file_priv);
-
-#define PSB_IOCTL_DEF(ioctl, func, flags) \
-       [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
-
-static struct drm_ioctl_desc psb_ioctls[] = {
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
-                     DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
-                     DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
-                     DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
-                                       psb_intel_get_pipe_from_crtc_id, 0),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
-                                               DRM_UNLOCKED | DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl,
-                                               DRM_UNLOCKED| DRM_AUTH),
-       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
-                                               DRM_UNLOCKED | DRM_AUTH),
-};
-
-static void psb_lastclose(struct drm_device *dev)
-{
-       return;
-}
-
-static void psb_do_takedown(struct drm_device *dev)
-{
-}
-
-static int psb_do_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_gtt *pg = &dev_priv->gtt;
-
-       uint32_t stolen_gtt;
-
-       int ret = -ENOMEM;
-
-       if (pg->mmu_gatt_start & 0x0FFFFFFF) {
-               dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
-               ret = -EINVAL;
-               goto out_err;
-       }
-
-
-       stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
-       stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       stolen_gtt =
-           (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
-
-       dev_priv->gatt_free_offset = pg->mmu_gatt_start +
-           (stolen_gtt << PAGE_SHIFT) * 1024;
-
-       if (1 || drm_debug) {
-               uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
-               uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
-               DRM_INFO("SGX core id = 0x%08x\n", core_id);
-               DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
-                        (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
-                        _PSB_CC_REVISION_MAJOR_SHIFT,
-                        (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
-                        _PSB_CC_REVISION_MINOR_SHIFT);
-               DRM_INFO
-                   ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
-                    (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
-                    _PSB_CC_REVISION_MAINTENANCE_SHIFT,
-                    (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
-                    _PSB_CC_REVISION_DESIGNER_SHIFT);
-       }
-
-
-       spin_lock_init(&dev_priv->irqmask_lock);
-       spin_lock_init(&dev_priv->lock_2d);
-
-       PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
-       PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
-       PSB_RSGX32(PSB_CR_BIF_BANK1);
-       PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
-                                                       PSB_CR_BIF_CTRL);
-       psb_spank(dev_priv);
-
-       /* mmu_gatt ?? */
-       PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-       return 0;
-out_err:
-       psb_do_takedown(dev);
-       return ret;
-}
-
-static int psb_driver_unload(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       /* Kill vblank etc here */
-
-       gma_backlight_exit(dev);
-
-       if (drm_psb_no_fb == 0)
-               psb_modeset_cleanup(dev);
-
-       if (dev_priv) {
-               psb_lid_timer_takedown(dev_priv);
-               gma_intel_opregion_exit(dev);
-
-               if (dev_priv->ops->chip_teardown)
-                       dev_priv->ops->chip_teardown(dev);
-               psb_do_takedown(dev);
-
-
-               if (dev_priv->pf_pd) {
-                       psb_mmu_free_pagedir(dev_priv->pf_pd);
-                       dev_priv->pf_pd = NULL;
-               }
-               if (dev_priv->mmu) {
-                       struct psb_gtt *pg = &dev_priv->gtt;
-
-                       down_read(&pg->sem);
-                       psb_mmu_remove_pfn_sequence(
-                               psb_mmu_get_default_pd
-                               (dev_priv->mmu),
-                               pg->mmu_gatt_start,
-                               dev_priv->vram_stolen_size >> PAGE_SHIFT);
-                       up_read(&pg->sem);
-                       psb_mmu_driver_takedown(dev_priv->mmu);
-                       dev_priv->mmu = NULL;
-               }
-               psb_gtt_takedown(dev);
-               if (dev_priv->scratch_page) {
-                       __free_page(dev_priv->scratch_page);
-                       dev_priv->scratch_page = NULL;
-               }
-               if (dev_priv->vdc_reg) {
-                       iounmap(dev_priv->vdc_reg);
-                       dev_priv->vdc_reg = NULL;
-               }
-               if (dev_priv->sgx_reg) {
-                       iounmap(dev_priv->sgx_reg);
-                       dev_priv->sgx_reg = NULL;
-               }
-
-               kfree(dev_priv);
-               dev->dev_private = NULL;
-
-               /*destroy VBT data*/
-               psb_intel_destroy_bios(dev);
-       }
-
-       gma_power_uninit(dev);
-
-       return 0;
-}
-
-
-static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
-{
-       struct drm_psb_private *dev_priv;
-       unsigned long resource_start;
-       struct psb_gtt *pg;
-       unsigned long irqflags;
-       int ret = -ENOMEM;
-       uint32_t tt_pages;
-       struct drm_connector *connector;
-       struct psb_intel_output *psb_intel_output;
-
-       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       dev_priv->ops = (struct psb_ops *)chipset;
-       dev_priv->dev = dev;
-       dev->dev_private = (void *) dev_priv;
-
-       if (!IS_PSB(dev)) {
-               if (pci_enable_msi(dev->pdev))
-                       dev_warn(dev->dev, "Enabling MSI failed!\n");
-       }
-
-       dev_priv->num_pipe = dev_priv->ops->pipes;
-
-       resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
-
-       dev_priv->vdc_reg =
-           ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
-       if (!dev_priv->vdc_reg)
-               goto out_err;
-
-       dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset,
-                                                       PSB_SGX_SIZE);
-       if (!dev_priv->sgx_reg)
-               goto out_err;
-
-       ret = dev_priv->ops->chip_setup(dev);
-       if (ret)
-               goto out_err;
-
-       /* Init OSPM support */
-       gma_power_init(dev);
-
-       ret = -ENOMEM;
-
-       dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
-       if (!dev_priv->scratch_page)
-               goto out_err;
-
-       set_pages_uc(dev_priv->scratch_page, 1);
-
-       ret = psb_gtt_init(dev, 0);
-       if (ret)
-               goto out_err;
-
-       dev_priv->mmu = psb_mmu_driver_init((void *)0,
-                                       drm_psb_trap_pagefaults, 0,
-                                       dev_priv);
-       if (!dev_priv->mmu)
-               goto out_err;
-
-       pg = &dev_priv->gtt;
-
-       tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
-               (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
-
-
-       dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
-       if (!dev_priv->pf_pd)
-               goto out_err;
-
-       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
-       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
-
-       ret = psb_do_init(dev);
-       if (ret)
-               return ret;
-
-       PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
-       PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
-
-/*     igd_opregion_init(&dev_priv->opregion_dev); */
-       acpi_video_register();
-       if (dev_priv->lid_state)
-               psb_lid_timer_init(dev_priv);
-
-       ret = drm_vblank_init(dev, dev_priv->num_pipe);
-       if (ret)
-               goto out_err;
-
-       /*
-        * Install interrupt handlers prior to powering off SGX or else we will
-        * crash.
-        */
-       dev_priv->vdc_irq_mask = 0;
-       dev_priv->pipestat[0] = 0;
-       dev_priv->pipestat[1] = 0;
-       dev_priv->pipestat[2] = 0;
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-       PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
-       PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
-       PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-       if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET))
-               drm_irq_install(dev);
-
-       dev->vblank_disable_allowed = 1;
-
-       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-
-       dev->driver->get_vblank_counter = psb_get_vblank_counter;
-
-#if defined(CONFIG_DRM_PSB_MFLD)
-       /* FIXME: this is not the right place for this stuff ! */
-       mdfld_output_setup(dev);
-#endif
-       if (drm_psb_no_fb == 0) {
-               psb_modeset_init(dev);
-               psb_fbdev_init(dev);
-               drm_kms_helper_poll_init(dev);
-       }
-
-       /* Only add backlight support if we have LVDS output */
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
-               psb_intel_output = to_psb_intel_output(connector);
-
-               switch (psb_intel_output->type) {
-               case INTEL_OUTPUT_LVDS:
-               case INTEL_OUTPUT_MIPI:
-                       ret = gma_backlight_init(dev);
-                       break;
-               }
-       }
-
-       if (ret)
-               return ret;
-
-       /* Enable runtime pm at last */
-       pm_runtime_set_active(&dev->pdev->dev);
-       return 0;
-out_err:
-       psb_driver_unload(dev);
-       return ret;
-}
-
-int psb_driver_device_is_agp(struct drm_device *dev)
-{
-       return 0;
-}
-
-
-static int psb_sizes_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       struct drm_psb_sizes_arg *arg = data;
-
-       *arg = dev_priv->sizes;
-       return 0;
-}
-
-static int psb_dc_state_ioctl(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
-{
-       uint32_t flags;
-       uint32_t obj_id;
-       struct drm_mode_object *obj;
-       struct drm_connector *connector;
-       struct drm_crtc *crtc;
-       struct drm_psb_dc_state_arg *arg = data;
-
-
-       /* Double check MRST case */
-       if (IS_MRST(dev) || IS_MFLD(dev))
-               return -EOPNOTSUPP;
-
-       flags = arg->flags;
-       obj_id = arg->obj_id;
-
-       if (flags & PSB_DC_CRTC_MASK) {
-               obj = drm_mode_object_find(dev, obj_id,
-                               DRM_MODE_OBJECT_CRTC);
-               if (!obj) {
-                       dev_dbg(dev->dev, "Invalid CRTC object.\n");
-                       return -EINVAL;
-               }
-
-               crtc = obj_to_crtc(obj);
-
-               mutex_lock(&dev->mode_config.mutex);
-               if (drm_helper_crtc_in_use(crtc)) {
-                       if (flags & PSB_DC_CRTC_SAVE)
-                               crtc->funcs->save(crtc);
-                       else
-                               crtc->funcs->restore(crtc);
-               }
-               mutex_unlock(&dev->mode_config.mutex);
-
-               return 0;
-       } else if (flags & PSB_DC_OUTPUT_MASK) {
-               obj = drm_mode_object_find(dev, obj_id,
-                               DRM_MODE_OBJECT_CONNECTOR);
-               if (!obj) {
-                       dev_dbg(dev->dev, "Invalid connector id.\n");
-                       return -EINVAL;
-               }
-
-               connector = obj_to_connector(obj);
-               if (flags & PSB_DC_OUTPUT_SAVE)
-                       connector->funcs->save(connector);
-               else
-                       connector->funcs->restore(connector);
-
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static inline void get_brightness(struct backlight_device *bd)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       if (bd) {
-               bd->props.brightness = bd->ops->get_brightness(bd);
-               backlight_update_status(bd);
-       }
-#endif
-}
-
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       uint32_t *arg = data;
-
-       dev_priv->blc_adj2 = *arg;
-       get_brightness(dev_priv->backlight_device);
-       return 0;
-}
-
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       uint32_t *arg = data;
-
-       dev_priv->blc_adj1 = *arg;
-       get_brightness(dev_priv->backlight_device);
-       return 0;
-}
-
-/* return the current mode to the dpst module */
-static int psb_dpst_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       uint32_t *arg = data;
-       uint32_t x;
-       uint32_t y;
-       uint32_t reg;
-
-       if (!gma_power_begin(dev, 0))
-               return -EIO;
-
-       reg = PSB_RVDC32(PIPEASRC);
-
-       gma_power_end(dev);
-
-       /* horizontal is the left 16 bits */
-       x = reg >> 16;
-       /* vertical is the right 16 bits */
-       y = reg & 0x0000ffff;
-
-       /* the values are the image size minus one */
-       x++;
-       y++;
-
-       *arg = (x << 16) | y;
-
-       return 0;
-}
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       struct drm_psb_dpst_lut_arg *lut_arg = data;
-       struct drm_mode_object *obj;
-       struct drm_crtc *crtc;
-       struct drm_connector *connector;
-       struct psb_intel_crtc *psb_intel_crtc;
-       int i = 0;
-       int32_t obj_id;
-
-       obj_id = lut_arg->output_id;
-       obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
-       if (!obj) {
-               dev_dbg(dev->dev, "Invalid Connector object.\n");
-               return -EINVAL;
-       }
-
-       connector = obj_to_connector(obj);
-       crtc = connector->encoder->crtc;
-       psb_intel_crtc = to_psb_intel_crtc(crtc);
-
-       for (i = 0; i < 256; i++)
-               psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
-
-       psb_intel_crtc_load_lut(crtc);
-
-       return 0;
-}
-
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
-{
-       uint32_t obj_id;
-       uint16_t op;
-       struct drm_mode_modeinfo *umode;
-       struct drm_display_mode *mode = NULL;
-       struct drm_psb_mode_operation_arg *arg;
-       struct drm_mode_object *obj;
-       struct drm_connector *connector;
-       struct drm_framebuffer *drm_fb;
-       struct psb_framebuffer *psb_fb;
-       struct drm_connector_helper_funcs *connector_funcs;
-       int ret = 0;
-       int resp = MODE_OK;
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-
-       arg = (struct drm_psb_mode_operation_arg *)data;
-       obj_id = arg->obj_id;
-       op = arg->operation;
-
-       switch (op) {
-       case PSB_MODE_OPERATION_SET_DC_BASE:
-               obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
-               if (!obj) {
-                       dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
-                       return -EINVAL;
-               }
-
-               drm_fb = obj_to_fb(obj);
-               psb_fb = to_psb_fb(drm_fb);
-
-               if (gma_power_begin(dev, 0)) {
-                       REG_WRITE(DSPASURF, psb_fb->gtt->offset);
-                       REG_READ(DSPASURF);
-                       gma_power_end(dev);
-               } else {
-                       dev_priv->saveDSPASURF = psb_fb->gtt->offset;
-               }
-
-               return 0;
-       case PSB_MODE_OPERATION_MODE_VALID:
-               umode = &arg->mode;
-
-               mutex_lock(&dev->mode_config.mutex);
-
-               obj = drm_mode_object_find(dev, obj_id,
-                                       DRM_MODE_OBJECT_CONNECTOR);
-               if (!obj) {
-                       ret = -EINVAL;
-                       goto mode_op_out;
-               }
-
-               connector = obj_to_connector(obj);
-
-               mode = drm_mode_create(dev);
-               if (!mode) {
-                       ret = -ENOMEM;
-                       goto mode_op_out;
-               }
-
-               /* drm_crtc_convert_umode(mode, umode); */
-               {
-                       mode->clock = umode->clock;
-                       mode->hdisplay = umode->hdisplay;
-                       mode->hsync_start = umode->hsync_start;
-                       mode->hsync_end = umode->hsync_end;
-                       mode->htotal = umode->htotal;
-                       mode->hskew = umode->hskew;
-                       mode->vdisplay = umode->vdisplay;
-                       mode->vsync_start = umode->vsync_start;
-                       mode->vsync_end = umode->vsync_end;
-                       mode->vtotal = umode->vtotal;
-                       mode->vscan = umode->vscan;
-                       mode->vrefresh = umode->vrefresh;
-                       mode->flags = umode->flags;
-                       mode->type = umode->type;
-                       strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
-                       mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
-               }
-
-               connector_funcs = (struct drm_connector_helper_funcs *)
-                                  connector->helper_private;
-
-               if (connector_funcs->mode_valid) {
-                       resp = connector_funcs->mode_valid(connector, mode);
-                       arg->data = (void *)resp;
-               }
-
-               /*do some clean up work*/
-               if (mode)
-                       drm_mode_destroy(dev, mode);
-mode_op_out:
-               mutex_unlock(&dev->mode_config.mutex);
-               return ret;
-
-       default:
-               dev_dbg(dev->dev, "Unsupported psb mode operation\n");
-               return -EOPNOTSUPP;
-       }
-
-       return 0;
-}
-
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
-                                  struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       struct drm_psb_stolen_memory_arg *arg = data;
-
-       arg->base = dev_priv->stolen_base;
-       arg->size = dev_priv->vram_stolen_size;
-
-       return 0;
-}
-
-/* FIXME: needs Medfield changes */
-static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       struct drm_psb_register_rw_arg *arg = data;
-       bool usage = arg->b_force_hw_on ? true : false;
-
-       if (arg->display_write_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
-                               PSB_WVDC32(arg->display.pfit_controls,
-                                          PFIT_CONTROL);
-                       if (arg->display_write_mask &
-                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-                               PSB_WVDC32(arg->display.pfit_autoscale_ratios,
-                                          PFIT_AUTO_RATIOS);
-                       if (arg->display_write_mask &
-                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-                               PSB_WVDC32(
-                                  arg->display.pfit_programmed_scale_ratios,
-                                  PFIT_PGM_RATIOS);
-                       if (arg->display_write_mask & REGRWBITS_PIPEASRC)
-                               PSB_WVDC32(arg->display.pipeasrc,
-                                          PIPEASRC);
-                       if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
-                               PSB_WVDC32(arg->display.pipebsrc,
-                                          PIPEBSRC);
-                       if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
-                               PSB_WVDC32(arg->display.vtotal_a,
-                                          VTOTAL_A);
-                       if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
-                               PSB_WVDC32(arg->display.vtotal_b,
-                                          VTOTAL_B);
-                       gma_power_end(dev);
-               } else {
-                       if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
-                               dev_priv->savePFIT_CONTROL =
-                                               arg->display.pfit_controls;
-                       if (arg->display_write_mask &
-                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-                               dev_priv->savePFIT_AUTO_RATIOS =
-                                       arg->display.pfit_autoscale_ratios;
-                       if (arg->display_write_mask &
-                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-                               dev_priv->savePFIT_PGM_RATIOS =
-                                  arg->display.pfit_programmed_scale_ratios;
-                       if (arg->display_write_mask & REGRWBITS_PIPEASRC)
-                               dev_priv->savePIPEASRC = arg->display.pipeasrc;
-                       if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
-                               dev_priv->savePIPEBSRC = arg->display.pipebsrc;
-                       if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
-                               dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
-                       if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
-                               dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
-               }
-       }
-
-       if (arg->display_read_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       if (arg->display_read_mask &
-                           REGRWBITS_PFIT_CONTROLS)
-                               arg->display.pfit_controls =
-                                               PSB_RVDC32(PFIT_CONTROL);
-                       if (arg->display_read_mask &
-                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-                               arg->display.pfit_autoscale_ratios =
-                                               PSB_RVDC32(PFIT_AUTO_RATIOS);
-                       if (arg->display_read_mask &
-                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-                               arg->display.pfit_programmed_scale_ratios =
-                                               PSB_RVDC32(PFIT_PGM_RATIOS);
-                       if (arg->display_read_mask & REGRWBITS_PIPEASRC)
-                               arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
-                       if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
-                               arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
-                       if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
-                               arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
-                       if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
-                               arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
-                       gma_power_end(dev);
-               } else {
-                       if (arg->display_read_mask &
-                           REGRWBITS_PFIT_CONTROLS)
-                               arg->display.pfit_controls =
-                                               dev_priv->savePFIT_CONTROL;
-                       if (arg->display_read_mask &
-                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-                               arg->display.pfit_autoscale_ratios =
-                                               dev_priv->savePFIT_AUTO_RATIOS;
-                       if (arg->display_read_mask &
-                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-                               arg->display.pfit_programmed_scale_ratios =
-                                               dev_priv->savePFIT_PGM_RATIOS;
-                       if (arg->display_read_mask & REGRWBITS_PIPEASRC)
-                               arg->display.pipeasrc = dev_priv->savePIPEASRC;
-                       if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
-                               arg->display.pipebsrc = dev_priv->savePIPEBSRC;
-                       if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
-                               arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
-                       if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
-                               arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
-               }
-       }
-
-       if (arg->overlay_write_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
-                               PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
-                               PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
-                               PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
-                               PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
-                               PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
-                               PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
-                       }
-                       if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
-                               PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
-                               PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
-                               PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
-                               PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
-                               PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
-                               PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
-                       }
-
-                       if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
-                               PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
-
-                               if (arg->overlay.b_wait_vblank) {
-                                       /* Wait for 20ms.*/
-                                       unsigned long vblank_timeout = jiffies
-                                                               + HZ/50;
-                                       uint32_t temp;
-                                       while (time_before_eq(jiffies,
-                                                       vblank_timeout)) {
-                                               temp = PSB_RVDC32(OV_DOVASTA);
-                                               if ((temp & (0x1 << 31)) != 0)
-                                                       break;
-                                               cpu_relax();
-                                       }
-                               }
-                       }
-                       if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
-                               PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
-                               if (arg->overlay.b_wait_vblank) {
-                                       /* Wait for 20ms.*/
-                                       unsigned long vblank_timeout =
-                                                       jiffies + HZ/50;
-                                       uint32_t temp;
-                                       while (time_before_eq(jiffies,
-                                                       vblank_timeout)) {
-                                               temp = PSB_RVDC32(OVC_DOVCSTA);
-                                               if ((temp & (0x1 << 31)) != 0)
-                                                       break;
-                                               cpu_relax();
-                                       }
-                               }
-                       }
-                       gma_power_end(dev);
-               } else {
-                       if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
-                               dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
-                               dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
-                               dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
-                               dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
-                               dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
-                               dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
-                       }
-                       if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
-                               dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
-                               dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
-                               dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
-                               dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
-                               dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
-                               dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
-                       }
-                       if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
-                               dev_priv->saveOV_OVADD = arg->overlay.OVADD;
-                       if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
-                               dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
-               }
-       }
-
-       if (arg->overlay_read_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
-                               arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-                               arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
-                               arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
-                               arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
-                               arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
-                               arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
-                       }
-                       if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
-                               arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
-                               arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
-                               arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
-                               arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
-                               arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
-                               arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
-                       }
-                       if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
-                               arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
-                       if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
-                               arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
-                       gma_power_end(dev);
-               } else {
-                       if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
-                               arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
-                               arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
-                               arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
-                               arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
-                               arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
-                               arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
-                       }
-                       if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
-                               arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
-                               arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
-                               arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
-                               arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
-                               arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
-                               arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
-                       }
-                       if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
-                               arg->overlay.OVADD = dev_priv->saveOV_OVADD;
-                       if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
-                               arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
-               }
-       }
-
-       if (arg->sprite_enable_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       PSB_WVDC32(0x1F3E, DSPARB);
-                       PSB_WVDC32(arg->sprite.dspa_control
-                                       | PSB_RVDC32(DSPACNTR), DSPACNTR);
-                       PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
-                       PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
-                       PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
-                       PSB_RVDC32(DSPASURF);
-                       PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
-                       PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
-                       PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
-                       PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
-                       PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
-                       PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
-                       PSB_RVDC32(DSPCSURF);
-                       gma_power_end(dev);
-               }
-       }
-
-       if (arg->sprite_disable_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       PSB_WVDC32(0x3F3E, DSPARB);
-                       PSB_WVDC32(0x0, DSPCCNTR);
-                       PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
-                       PSB_RVDC32(DSPCSURF);
-                       gma_power_end(dev);
-               }
-       }
-
-       if (arg->subpicture_enable_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       uint32_t temp;
-                       if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
-                               temp =  PSB_RVDC32(DSPACNTR);
-                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
-                               temp &= ~DISPPLANE_BOTTOM;
-                               temp |= DISPPLANE_32BPP;
-                               PSB_WVDC32(temp, DSPACNTR);
-
-                               temp =  PSB_RVDC32(DSPABASE);
-                               PSB_WVDC32(temp, DSPABASE);
-                               PSB_RVDC32(DSPABASE);
-                               temp =  PSB_RVDC32(DSPASURF);
-                               PSB_WVDC32(temp, DSPASURF);
-                               PSB_RVDC32(DSPASURF);
-                       }
-                       if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
-                               temp =  PSB_RVDC32(DSPBCNTR);
-                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
-                               temp &= ~DISPPLANE_BOTTOM;
-                               temp |= DISPPLANE_32BPP;
-                               PSB_WVDC32(temp, DSPBCNTR);
-
-                               temp =  PSB_RVDC32(DSPBBASE);
-                               PSB_WVDC32(temp, DSPBBASE);
-                               PSB_RVDC32(DSPBBASE);
-                               temp =  PSB_RVDC32(DSPBSURF);
-                               PSB_WVDC32(temp, DSPBSURF);
-                               PSB_RVDC32(DSPBSURF);
-                       }
-                       if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
-                               temp =  PSB_RVDC32(DSPCCNTR);
-                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
-                               temp &= ~DISPPLANE_BOTTOM;
-                               temp |= DISPPLANE_32BPP;
-                               PSB_WVDC32(temp, DSPCCNTR);
-
-                               temp =  PSB_RVDC32(DSPCBASE);
-                               PSB_WVDC32(temp, DSPCBASE);
-                               PSB_RVDC32(DSPCBASE);
-                               temp =  PSB_RVDC32(DSPCSURF);
-                               PSB_WVDC32(temp, DSPCSURF);
-                               PSB_RVDC32(DSPCSURF);
-                       }
-                       gma_power_end(dev);
-               }
-       }
-
-       if (arg->subpicture_disable_mask != 0) {
-               if (gma_power_begin(dev, usage)) {
-                       uint32_t temp;
-                       if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
-                               temp =  PSB_RVDC32(DSPACNTR);
-                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
-                               temp |= DISPPLANE_32BPP_NO_ALPHA;
-                               PSB_WVDC32(temp, DSPACNTR);
-
-                               temp =  PSB_RVDC32(DSPABASE);
-                               PSB_WVDC32(temp, DSPABASE);
-                               PSB_RVDC32(DSPABASE);
-                               temp =  PSB_RVDC32(DSPASURF);
-                               PSB_WVDC32(temp, DSPASURF);
-                               PSB_RVDC32(DSPASURF);
-                       }
-                       if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
-                               temp =  PSB_RVDC32(DSPBCNTR);
-                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
-                               temp |= DISPPLANE_32BPP_NO_ALPHA;
-                               PSB_WVDC32(temp, DSPBCNTR);
-
-                               temp =  PSB_RVDC32(DSPBBASE);
-                               PSB_WVDC32(temp, DSPBBASE);
-                               PSB_RVDC32(DSPBBASE);
-                               temp =  PSB_RVDC32(DSPBSURF);
-                               PSB_WVDC32(temp, DSPBSURF);
-                               PSB_RVDC32(DSPBSURF);
-                       }
-                       if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
-                               temp =  PSB_RVDC32(DSPCCNTR);
-                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
-                               temp |= DISPPLANE_32BPP_NO_ALPHA;
-                               PSB_WVDC32(temp, DSPCCNTR);
-
-                               temp =  PSB_RVDC32(DSPCBASE);
-                               PSB_WVDC32(temp, DSPCBASE);
-                               PSB_RVDC32(DSPCBASE);
-                               temp =  PSB_RVDC32(DSPCSURF);
-                               PSB_WVDC32(temp, DSPCSURF);
-                               PSB_RVDC32(DSPCSURF);
-                       }
-                       gma_power_end(dev);
-               }
-       }
-
-       return 0;
-}
-
-static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
-{
-       return 0;
-}
-
-static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
-static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
-                              unsigned long arg)
-{
-       struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-       int ret;
-       
-       pm_runtime_forbid(dev->dev);
-       ret = drm_ioctl(filp, cmd, arg);
-       pm_runtime_allow(dev->dev);
-       return ret;
-       /* FIXME: do we need to wrap the other side of this */
-}
-
-
-/* When a client dies:
- *    - Check for and clean up flipped page state
- */
-void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
-static void psb_remove(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-       drm_put_dev(dev);
-}
-
-static const struct dev_pm_ops psb_pm_ops = {
-       .suspend = gma_power_suspend,
-       .resume = gma_power_resume,
-       .freeze = gma_power_suspend,
-       .thaw = gma_power_resume,
-       .poweroff = gma_power_suspend,
-       .restore = gma_power_resume,
-       .runtime_suspend = psb_runtime_suspend,
-       .runtime_resume = psb_runtime_resume,
-       .runtime_idle = psb_runtime_idle,
-};
-
-static struct vm_operations_struct psb_gem_vm_ops = {
-       .fault = psb_gem_fault,
-       .open = drm_gem_vm_open,
-       .close = drm_gem_vm_close,
-};
-
-static const struct file_operations gma500_driver_fops = {
-       .owner = THIS_MODULE,
-       .open = drm_open,
-       .release = drm_release,
-       .unlocked_ioctl = psb_unlocked_ioctl,
-       .mmap = drm_gem_mmap,
-       .poll = drm_poll,
-       .fasync = drm_fasync,
-       .read = drm_read,
-};
-
-static struct drm_driver driver = {
-       .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
-                          DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
-       .load = psb_driver_load,
-       .unload = psb_driver_unload,
-
-       .ioctls = psb_ioctls,
-       .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
-       .device_is_agp = psb_driver_device_is_agp,
-       .irq_preinstall = psb_irq_preinstall,
-       .irq_postinstall = psb_irq_postinstall,
-       .irq_uninstall = psb_irq_uninstall,
-       .irq_handler = psb_irq_handler,
-       .enable_vblank = psb_enable_vblank,
-       .disable_vblank = psb_disable_vblank,
-       .get_vblank_counter = psb_get_vblank_counter,
-       .lastclose = psb_lastclose,
-       .open = psb_driver_open,
-       .preclose = psb_driver_preclose,
-       .postclose = psb_driver_close,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-
-       .gem_init_object = psb_gem_init_object,
-       .gem_free_object = psb_gem_free_object,
-       .gem_vm_ops = &psb_gem_vm_ops,
-       .dumb_create = psb_gem_dumb_create,
-       .dumb_map_offset = psb_gem_dumb_map_gtt,
-       .dumb_destroy = psb_gem_dumb_destroy,
-       .fops = &gma500_driver_fops,
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = PSB_DRM_DRIVER_DATE,
-       .major = PSB_DRM_DRIVER_MAJOR,
-       .minor = PSB_DRM_DRIVER_MINOR,
-       .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
-};
-
-static struct pci_driver psb_pci_driver = {
-       .name = DRIVER_NAME,
-       .id_table = pciidlist,
-       .probe = psb_probe,
-       .remove = psb_remove,
-       .driver.pm = &psb_pm_ops,
-};
-
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       return drm_get_pci_dev(pdev, ent, &driver);
-}
-
-static int __init psb_init(void)
-{
-       return drm_pci_init(&driver, &psb_pci_driver);
-}
-
-static void __exit psb_exit(void)
-{
-       drm_pci_exit(&driver, &psb_pci_driver);
-}
-
-late_initcall(psb_init);
-module_exit(psb_exit);
-
-MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
deleted file mode 100644 (file)
index 11d963a..0000000
+++ /dev/null
@@ -1,952 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#ifndef _PSB_DRV_H_
-#define _PSB_DRV_H_
-
-#include <linux/kref.h>
-
-#include <drm/drmP.h>
-#include "drm_global.h"
-#include "gem_glue.h"
-#include "psb_drm.h"
-#include "psb_reg.h"
-#include "psb_intel_drv.h"
-#include "gtt.h"
-#include "power.h"
-#include "mrst.h"
-#include "medfield.h"
-
-/* Append new drm mode definition here, align with libdrm definition */
-#define DRM_MODE_SCALE_NO_SCALE        2
-
-enum {
-       CHIP_PSB_8108 = 0,              /* Poulsbo */
-       CHIP_PSB_8109 = 1,              /* Poulsbo */
-       CHIP_MRST_4100 = 2,             /* Moorestown/Oaktrail */
-       CHIP_MFLD_0130 = 3,             /* Medfield */
-};
-
-#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108)
-#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
-#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
-
-/*
- * Driver definitions
- */
-
-#define DRIVER_NAME "gma500"
-#define DRIVER_DESC "DRM driver for the Intel GMA500"
-
-#define PSB_DRM_DRIVER_DATE "2011-06-06"
-#define PSB_DRM_DRIVER_MAJOR 1
-#define PSB_DRM_DRIVER_MINOR 0
-#define PSB_DRM_DRIVER_PATCHLEVEL 0
-
-/*
- *     Hardware offsets
- */
-#define PSB_VDC_OFFSET          0x00000000
-#define PSB_VDC_SIZE            0x000080000
-#define MRST_MMIO_SIZE          0x0000C0000
-#define MDFLD_MMIO_SIZE          0x000100000
-#define PSB_SGX_SIZE            0x8000
-#define PSB_SGX_OFFSET          0x00040000
-#define MRST_SGX_OFFSET                 0x00080000
-/*
- *     PCI resource identifiers
- */
-#define PSB_MMIO_RESOURCE       0
-#define PSB_GATT_RESOURCE       2
-#define PSB_GTT_RESOURCE        3
-/*
- *     PCI configuration
- */
-#define PSB_GMCH_CTRL           0x52
-#define PSB_BSM                         0x5C
-#define _PSB_GMCH_ENABLED       0x4
-#define PSB_PGETBL_CTL          0x2020
-#define _PSB_PGETBL_ENABLED     0x00000001
-#define PSB_SGX_2D_SLAVE_PORT   0x4000
-
-/* To get rid of */
-#define PSB_TT_PRIV0_LIMIT      (256*1024*1024)
-#define PSB_TT_PRIV0_PLIMIT     (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
-
-/*
- *     SGX side MMU definitions (these can probably go)
- */
-
-/*
- *     Flags for external memory type field.
- */
-#define PSB_MMU_CACHED_MEMORY    0x0001        /* Bind to MMU only */
-#define PSB_MMU_RO_MEMORY        0x0002        /* MMU RO memory */
-#define PSB_MMU_WO_MEMORY        0x0004        /* MMU WO memory */
-/*
- *     PTE's and PDE's
- */
-#define PSB_PDE_MASK             0x003FFFFF
-#define PSB_PDE_SHIFT            22
-#define PSB_PTE_SHIFT            12
-/*
- *     Cache control
- */
-#define PSB_PTE_VALID            0x0001        /* PTE / PDE valid */
-#define PSB_PTE_WO               0x0002        /* Write only */
-#define PSB_PTE_RO               0x0004        /* Read only */
-#define PSB_PTE_CACHED           0x0008        /* CPU cache coherent */
-
-/*
- *     VDC registers and bits
- */
-#define PSB_MSVDX_CLOCKGATING    0x2064
-#define PSB_TOPAZ_CLOCKGATING    0x2068
-#define PSB_HWSTAM               0x2098
-#define PSB_INSTPM               0x20C0
-#define PSB_INT_IDENTITY_R        0x20A4
-#define _MDFLD_PIPEC_EVENT_FLAG   (1<<2)
-#define _MDFLD_PIPEC_VBLANK_FLAG  (1<<3)
-#define _PSB_DPST_PIPEB_FLAG      (1<<4)
-#define _MDFLD_PIPEB_EVENT_FLAG   (1<<4)
-#define _PSB_VSYNC_PIPEB_FLAG    (1<<5)
-#define _PSB_DPST_PIPEA_FLAG      (1<<6)
-#define _PSB_PIPEA_EVENT_FLAG     (1<<6)
-#define _PSB_VSYNC_PIPEA_FLAG    (1<<7)
-#define _MDFLD_MIPIA_FLAG        (1<<16)
-#define _MDFLD_MIPIC_FLAG        (1<<17)
-#define _PSB_IRQ_SGX_FLAG        (1<<18)
-#define _PSB_IRQ_MSVDX_FLAG      (1<<19)
-#define _LNC_IRQ_TOPAZ_FLAG      (1<<20)
-
-#define _PSB_PIPE_EVENT_FLAG   (_PSB_VSYNC_PIPEA_FLAG | \
-                                _PSB_VSYNC_PIPEB_FLAG)
-
-/* This flag includes all the display IRQ bits excepts the vblank irqs. */
-#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
-                                 _MDFLD_PIPEB_EVENT_FLAG | \
-                                 _PSB_PIPEA_EVENT_FLAG | \
-                                 _PSB_VSYNC_PIPEA_FLAG | \
-                                 _MDFLD_MIPIA_FLAG | \
-                                 _MDFLD_MIPIC_FLAG)
-#define PSB_INT_IDENTITY_R       0x20A4
-#define PSB_INT_MASK_R           0x20A8
-#define PSB_INT_ENABLE_R         0x20A0
-
-#define _PSB_MMU_ER_MASK      0x0001FF00
-#define _PSB_MMU_ER_HOST      (1 << 16)
-#define GPIOA                  0x5010
-#define GPIOB                  0x5014
-#define GPIOC                  0x5018
-#define GPIOD                  0x501c
-#define GPIOE                  0x5020
-#define GPIOF                  0x5024
-#define GPIOG                  0x5028
-#define GPIOH                  0x502c
-#define GPIO_CLOCK_DIR_MASK            (1 << 0)
-#define GPIO_CLOCK_DIR_IN              (0 << 1)
-#define GPIO_CLOCK_DIR_OUT             (1 << 1)
-#define GPIO_CLOCK_VAL_MASK            (1 << 2)
-#define GPIO_CLOCK_VAL_OUT             (1 << 3)
-#define GPIO_CLOCK_VAL_IN              (1 << 4)
-#define GPIO_CLOCK_PULLUP_DISABLE      (1 << 5)
-#define GPIO_DATA_DIR_MASK             (1 << 8)
-#define GPIO_DATA_DIR_IN               (0 << 9)
-#define GPIO_DATA_DIR_OUT              (1 << 9)
-#define GPIO_DATA_VAL_MASK             (1 << 10)
-#define GPIO_DATA_VAL_OUT              (1 << 11)
-#define GPIO_DATA_VAL_IN               (1 << 12)
-#define GPIO_DATA_PULLUP_DISABLE       (1 << 13)
-
-#define VCLK_DIVISOR_VGA0   0x6000
-#define VCLK_DIVISOR_VGA1   0x6004
-#define VCLK_POST_DIV      0x6010
-
-#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
-#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
-#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
-#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
-#define PSB_COMM_USER_IRQ (1024 >> 2)
-#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
-#define PSB_COMM_FW (2048 >> 2)
-
-#define PSB_UIRQ_VISTEST              1
-#define PSB_UIRQ_OOM_REPLY            2
-#define PSB_UIRQ_FIRE_TA_REPLY        3
-#define PSB_UIRQ_FIRE_RASTER_REPLY     4
-
-#define PSB_2D_SIZE (256*1024*1024)
-#define PSB_MAX_RELOC_PAGES 1024
-
-#define PSB_LOW_REG_OFFS 0x0204
-#define PSB_HIGH_REG_OFFS 0x0600
-
-#define PSB_NUM_VBLANKS 2
-
-
-#define PSB_2D_SIZE (256*1024*1024)
-#define PSB_MAX_RELOC_PAGES 1024
-
-#define PSB_LOW_REG_OFFS 0x0204
-#define PSB_HIGH_REG_OFFS 0x0600
-
-#define PSB_NUM_VBLANKS 2
-#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
-#define PSB_LID_DELAY (DRM_HZ / 10)
-
-#define MDFLD_PNW_B0 0x04
-#define MDFLD_PNW_C0 0x08
-
-#define MDFLD_DSR_2D_3D_0      (1 << 0)
-#define MDFLD_DSR_2D_3D_2      (1 << 1)
-#define MDFLD_DSR_CURSOR_0     (1 << 2)
-#define MDFLD_DSR_CURSOR_2     (1 << 3)
-#define MDFLD_DSR_OVERLAY_0    (1 << 4)
-#define MDFLD_DSR_OVERLAY_2    (1 << 5)
-#define MDFLD_DSR_MIPI_CONTROL (1 << 6)
-#define MDFLD_DSR_DAMAGE_MASK_0        ((1 << 0) | (1 << 2) | (1 << 4))
-#define MDFLD_DSR_DAMAGE_MASK_2        ((1 << 1) | (1 << 3) | (1 << 5))
-#define MDFLD_DSR_2D_3D        (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
-
-#define MDFLD_DSR_RR           45
-#define MDFLD_DPU_ENABLE       (1 << 31)
-#define MDFLD_DSR_FULLSCREEN   (1 << 30)
-#define MDFLD_DSR_DELAY                (DRM_HZ / MDFLD_DSR_RR)
-
-#define PSB_PWR_STATE_ON               1
-#define PSB_PWR_STATE_OFF              2
-
-#define PSB_PMPOLICY_NOPM              0
-#define PSB_PMPOLICY_CLOCKGATING       1
-#define PSB_PMPOLICY_POWERDOWN         2
-
-#define PSB_PMSTATE_POWERUP            0
-#define PSB_PMSTATE_CLOCKGATED         1
-#define PSB_PMSTATE_POWERDOWN          2
-#define PSB_PCIx_MSI_ADDR_LOC          0x94
-#define PSB_PCIx_MSI_DATA_LOC          0x98
-
-/* Medfield crystal settings */
-#define KSEL_CRYSTAL_19 1
-#define KSEL_BYPASS_19 5
-#define KSEL_BYPASS_25 6
-#define KSEL_BYPASS_83_100 7
-
-struct opregion_header;
-struct opregion_acpi;
-struct opregion_swsci;
-struct opregion_asle;
-
-struct psb_intel_opregion {
-       struct opregion_header *header;
-       struct opregion_acpi *acpi;
-       struct opregion_swsci *swsci;
-       struct opregion_asle *asle;
-       int enabled;
-};
-
-struct psb_ops;
-
-struct drm_psb_private {
-       struct drm_device *dev;
-       const struct psb_ops *ops;
-
-       struct psb_gtt gtt;
-
-       /* GTT Memory manager */
-       struct psb_gtt_mm *gtt_mm;
-       struct page *scratch_page;
-       u32 *gtt_map;
-       uint32_t stolen_base;
-       void *vram_addr;
-       unsigned long vram_stolen_size;
-       int gtt_initialized;
-       u16 gmch_ctrl;          /* Saved GTT setup */
-       u32 pge_ctl;
-
-       struct mutex gtt_mutex;
-       struct resource *gtt_mem;       /* Our PCI resource */
-
-       struct psb_mmu_driver *mmu;
-       struct psb_mmu_pd *pf_pd;
-
-       /*
-        * Register base
-        */
-
-       uint8_t *sgx_reg;
-       uint8_t *vdc_reg;
-       uint32_t gatt_free_offset;
-
-       /*
-        * Fencing / irq.
-        */
-
-       uint32_t vdc_irq_mask;
-       uint32_t pipestat[PSB_NUM_PIPE];
-
-       spinlock_t irqmask_lock;
-
-       /*
-        * Power
-        */
-
-       bool suspended;
-       bool display_power;
-       int display_count;
-
-       /*
-        * Modesetting
-        */
-       struct psb_intel_mode_device mode_dev;
-
-       struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
-       struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
-       uint32_t num_pipe;
-
-       /*
-        * OSPM info (Power management base) (can go ?)
-        */
-       uint32_t ospm_base;
-
-       /*
-        * Sizes info
-        */
-
-       struct drm_psb_sizes_arg sizes;
-
-       u32 fuse_reg_value;
-       u32 video_device_fuse;
-
-       /* PCI revision ID for B0:D2:F0 */
-       uint8_t platform_rev_id;
-
-       /*
-        * LVDS info
-        */
-       int backlight_duty_cycle;       /* restore backlight to this value */
-       bool panel_wants_dither;
-       struct drm_display_mode *panel_fixed_mode;
-       struct drm_display_mode *lfp_lvds_vbt_mode;
-       struct drm_display_mode *sdvo_lvds_vbt_mode;
-
-       struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
-       struct psb_intel_i2c_chan *lvds_i2c_bus;
-
-       /* Feature bits from the VBIOS */
-       unsigned int int_tv_support:1;
-       unsigned int lvds_dither:1;
-       unsigned int lvds_vbt:1;
-       unsigned int int_crt_support:1;
-       unsigned int lvds_use_ssc:1;
-       int lvds_ssc_freq;
-       bool is_lvds_on;
-       bool is_mipi_on;
-       u32 mipi_ctrl_display;
-
-       unsigned int core_freq;
-       uint32_t iLVDS_enable;
-
-       /* Runtime PM state */
-       int rpm_enabled;
-
-       /* MID specific */
-       struct mrst_vbt vbt_data;
-       struct mrst_gct_data gct_data;
-
-       /* MIPI Panel type etc */
-       int panel_id;
-       bool dual_mipi;         /* dual display - DPI & DBI */
-       bool dpi_panel_on;      /* The DPI panel power is on */
-       bool dpi_panel_on2;     /* The DPI panel power is on */
-       bool dbi_panel_on;      /* The DBI panel power is on */
-       bool dbi_panel_on2;     /* The DBI panel power is on */
-       u32 dsr_fb_update;      /* DSR FB update counter */
-
-       /* Moorestown HDMI state */
-       struct mrst_hdmi_dev *hdmi_priv;
-
-       /* Moorestown pipe config register value cache */
-       uint32_t pipeconf;
-       uint32_t pipeconf1;
-       uint32_t pipeconf2;
-
-       /* Moorestown plane control register value cache */
-       uint32_t dspcntr;
-       uint32_t dspcntr1;
-       uint32_t dspcntr2;
-
-       /* Moorestown MM backlight cache */
-       uint8_t saveBKLTCNT;
-       uint8_t saveBKLTREQ;
-       uint8_t saveBKLTBRTL;
-
-       /*
-        * Register state
-        */
-       uint32_t saveDSPACNTR;
-       uint32_t saveDSPBCNTR;
-       uint32_t savePIPEACONF;
-       uint32_t savePIPEBCONF;
-       uint32_t savePIPEASRC;
-       uint32_t savePIPEBSRC;
-       uint32_t saveFPA0;
-       uint32_t saveFPA1;
-       uint32_t saveDPLL_A;
-       uint32_t saveDPLL_A_MD;
-       uint32_t saveHTOTAL_A;
-       uint32_t saveHBLANK_A;
-       uint32_t saveHSYNC_A;
-       uint32_t saveVTOTAL_A;
-       uint32_t saveVBLANK_A;
-       uint32_t saveVSYNC_A;
-       uint32_t saveDSPASTRIDE;
-       uint32_t saveDSPASIZE;
-       uint32_t saveDSPAPOS;
-       uint32_t saveDSPABASE;
-       uint32_t saveDSPASURF;
-       uint32_t saveDSPASTATUS;
-       uint32_t saveFPB0;
-       uint32_t saveFPB1;
-       uint32_t saveDPLL_B;
-       uint32_t saveDPLL_B_MD;
-       uint32_t saveHTOTAL_B;
-       uint32_t saveHBLANK_B;
-       uint32_t saveHSYNC_B;
-       uint32_t saveVTOTAL_B;
-       uint32_t saveVBLANK_B;
-       uint32_t saveVSYNC_B;
-       uint32_t saveDSPBSTRIDE;
-       uint32_t saveDSPBSIZE;
-       uint32_t saveDSPBPOS;
-       uint32_t saveDSPBBASE;
-       uint32_t saveDSPBSURF;
-       uint32_t saveDSPBSTATUS;
-       uint32_t saveVCLK_DIVISOR_VGA0;
-       uint32_t saveVCLK_DIVISOR_VGA1;
-       uint32_t saveVCLK_POST_DIV;
-       uint32_t saveVGACNTRL;
-       uint32_t saveADPA;
-       uint32_t saveLVDS;
-       uint32_t saveDVOA;
-       uint32_t saveDVOB;
-       uint32_t saveDVOC;
-       uint32_t savePP_ON;
-       uint32_t savePP_OFF;
-       uint32_t savePP_CONTROL;
-       uint32_t savePP_CYCLE;
-       uint32_t savePFIT_CONTROL;
-       uint32_t savePaletteA[256];
-       uint32_t savePaletteB[256];
-       uint32_t saveBLC_PWM_CTL2;
-       uint32_t saveBLC_PWM_CTL;
-       uint32_t saveCLOCKGATING;
-       uint32_t saveDSPARB;
-       uint32_t saveDSPATILEOFF;
-       uint32_t saveDSPBTILEOFF;
-       uint32_t saveDSPAADDR;
-       uint32_t saveDSPBADDR;
-       uint32_t savePFIT_AUTO_RATIOS;
-       uint32_t savePFIT_PGM_RATIOS;
-       uint32_t savePP_ON_DELAYS;
-       uint32_t savePP_OFF_DELAYS;
-       uint32_t savePP_DIVISOR;
-       uint32_t saveBSM;
-       uint32_t saveVBT;
-       uint32_t saveBCLRPAT_A;
-       uint32_t saveBCLRPAT_B;
-       uint32_t saveDSPALINOFF;
-       uint32_t saveDSPBLINOFF;
-       uint32_t savePERF_MODE;
-       uint32_t saveDSPFW1;
-       uint32_t saveDSPFW2;
-       uint32_t saveDSPFW3;
-       uint32_t saveDSPFW4;
-       uint32_t saveDSPFW5;
-       uint32_t saveDSPFW6;
-       uint32_t saveCHICKENBIT;
-       uint32_t saveDSPACURSOR_CTRL;
-       uint32_t saveDSPBCURSOR_CTRL;
-       uint32_t saveDSPACURSOR_BASE;
-       uint32_t saveDSPBCURSOR_BASE;
-       uint32_t saveDSPACURSOR_POS;
-       uint32_t saveDSPBCURSOR_POS;
-       uint32_t save_palette_a[256];
-       uint32_t save_palette_b[256];
-       uint32_t saveOV_OVADD;
-       uint32_t saveOV_OGAMC0;
-       uint32_t saveOV_OGAMC1;
-       uint32_t saveOV_OGAMC2;
-       uint32_t saveOV_OGAMC3;
-       uint32_t saveOV_OGAMC4;
-       uint32_t saveOV_OGAMC5;
-       uint32_t saveOVC_OVADD;
-       uint32_t saveOVC_OGAMC0;
-       uint32_t saveOVC_OGAMC1;
-       uint32_t saveOVC_OGAMC2;
-       uint32_t saveOVC_OGAMC3;
-       uint32_t saveOVC_OGAMC4;
-       uint32_t saveOVC_OGAMC5;
-
-       /* MSI reg save */
-       uint32_t msi_addr;
-       uint32_t msi_data;
-
-       /* Medfield specific register save state */
-       uint32_t saveHDMIPHYMISCCTL;
-       uint32_t saveHDMIB_CONTROL;
-       uint32_t saveDSPCCNTR;
-       uint32_t savePIPECCONF;
-       uint32_t savePIPECSRC;
-       uint32_t saveHTOTAL_C;
-       uint32_t saveHBLANK_C;
-       uint32_t saveHSYNC_C;
-       uint32_t saveVTOTAL_C;
-       uint32_t saveVBLANK_C;
-       uint32_t saveVSYNC_C;
-       uint32_t saveDSPCSTRIDE;
-       uint32_t saveDSPCSIZE;
-       uint32_t saveDSPCPOS;
-       uint32_t saveDSPCSURF;
-       uint32_t saveDSPCSTATUS;
-       uint32_t saveDSPCLINOFF;
-       uint32_t saveDSPCTILEOFF;
-       uint32_t saveDSPCCURSOR_CTRL;
-       uint32_t saveDSPCCURSOR_BASE;
-       uint32_t saveDSPCCURSOR_POS;
-       uint32_t save_palette_c[256];
-       uint32_t saveOV_OVADD_C;
-       uint32_t saveOV_OGAMC0_C;
-       uint32_t saveOV_OGAMC1_C;
-       uint32_t saveOV_OGAMC2_C;
-       uint32_t saveOV_OGAMC3_C;
-       uint32_t saveOV_OGAMC4_C;
-       uint32_t saveOV_OGAMC5_C;
-
-       /* DSI register save */
-       uint32_t saveDEVICE_READY_REG;
-       uint32_t saveINTR_EN_REG;
-       uint32_t saveDSI_FUNC_PRG_REG;
-       uint32_t saveHS_TX_TIMEOUT_REG;
-       uint32_t saveLP_RX_TIMEOUT_REG;
-       uint32_t saveTURN_AROUND_TIMEOUT_REG;
-       uint32_t saveDEVICE_RESET_REG;
-       uint32_t saveDPI_RESOLUTION_REG;
-       uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
-       uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
-       uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
-       uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
-       uint32_t saveVERT_SYNC_PAD_COUNT_REG;
-       uint32_t saveVERT_BACK_PORCH_COUNT_REG;
-       uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
-       uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
-       uint32_t saveINIT_COUNT_REG;
-       uint32_t saveMAX_RET_PAK_REG;
-       uint32_t saveVIDEO_FMT_REG;
-       uint32_t saveEOT_DISABLE_REG;
-       uint32_t saveLP_BYTECLK_REG;
-       uint32_t saveHS_LS_DBI_ENABLE_REG;
-       uint32_t saveTXCLKESC_REG;
-       uint32_t saveDPHY_PARAM_REG;
-       uint32_t saveMIPI_CONTROL_REG;
-       uint32_t saveMIPI;
-       uint32_t saveMIPI_C;
-
-       /* DPST register save */
-       uint32_t saveHISTOGRAM_INT_CONTROL_REG;
-       uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
-       uint32_t savePWM_CONTROL_LOGIC;
-
-       /*
-        * DSI info. 
-        */
-       void * dbi_dsr_info;    
-       void * dbi_dpu_info;
-       void * dsi_configs[2];
-       /*
-        * LID-Switch
-        */
-       spinlock_t lid_lock;
-       struct timer_list lid_timer;
-       struct psb_intel_opregion opregion;
-       u32 *lid_state;
-       u32 lid_last_state;
-
-       /*
-        * Watchdog
-        */
-
-       uint32_t apm_reg;
-       uint16_t apm_base;
-
-       /*
-        * Used for modifying backlight from
-        * xrandr -- consider removing and using HAL instead
-        */
-       struct backlight_device *backlight_device;
-       struct drm_property *backlight_property;
-       uint32_t blc_adj1;
-       uint32_t blc_adj2;
-
-       void *fbdev;
-       /* DPST state */
-       uint32_t dsr_idle_count;
-       bool is_in_idle;
-       bool dsr_enable;
-       void (*exit_idle)(struct drm_device *dev, u32 update_src);
-
-       /* 2D acceleration */
-       spinlock_t lock_2d;
-
-       /* FIXME: Arrays anyone ? */
-       struct mdfld_dsi_encoder *encoder0;     
-       struct mdfld_dsi_encoder *encoder2;     
-       struct mdfld_dsi_dbi_output * dbi_output;
-       struct mdfld_dsi_dbi_output * dbi_output2;
-       u32 bpp;
-       u32 bpp2;
-       
-       bool dispstatus;
-};
-
-
-/*
- *     Operations for each board type
- */
-struct psb_ops {
-       const char *name;
-       unsigned int accel_2d:1;
-       int pipes;              /* Number of output pipes */
-       int crtcs;              /* Number of CRTCs */
-       int sgx_offset;         /* Base offset of SGX device */
-
-       /* Sub functions */
-       struct drm_crtc_helper_funcs const *crtc_helper;
-       struct drm_crtc_funcs const *crtc_funcs;
-
-       /* Setup hooks */
-       int (*chip_setup)(struct drm_device *dev);
-       void (*chip_teardown)(struct drm_device *dev);
-
-       /* Display management hooks */
-       int (*output_init)(struct drm_device *dev);
-       /* Power management hooks */
-       void (*init_pm)(struct drm_device *dev);
-       int (*save_regs)(struct drm_device *dev);
-       int (*restore_regs)(struct drm_device *dev);
-       int (*power_up)(struct drm_device *dev);
-       int (*power_down)(struct drm_device *dev);
-
-       void (*lvds_bl_power)(struct drm_device *dev, bool on);
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-       /* Backlight */
-       int (*backlight_init)(struct drm_device *dev);
-#endif
-       int i2c_bus;            /* I2C bus identifier for Moorestown */
-};
-
-
-
-struct psb_mmu_driver;
-
-extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
-extern int drm_pick_crtcs(struct drm_device *dev);
-
-static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
-{
-       return (struct drm_psb_private *) dev->dev_private;
-}
-
-/*
- * MMU stuff.
- */
-
-extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
-                                       int trap_pagefaults,
-                                       int invalid_type,
-                                       struct drm_psb_private *dev_priv);
-extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
-extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
-                                                *driver);
-extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
-                              uint32_t gtt_start, uint32_t gtt_pages);
-extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
-                                          int trap_pagefaults,
-                                          int invalid_type);
-extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
-extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
-extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
-                                       unsigned long address,
-                                       uint32_t num_pages);
-extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
-                                      uint32_t start_pfn,
-                                      unsigned long address,
-                                      uint32_t num_pages, int type);
-extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
-                                 unsigned long *pfn);
-
-/*
- * Enable / disable MMU for different requestors.
- */
-
-
-extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
-extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
-                               unsigned long address, uint32_t num_pages,
-                               uint32_t desired_tile_stride,
-                               uint32_t hw_tile_stride, int type);
-extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
-                                unsigned long address, uint32_t num_pages,
-                                uint32_t desired_tile_stride,
-                                uint32_t hw_tile_stride);
-/*
- *psb_irq.c
- */
-
-extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
-extern int psb_irq_enable_dpst(struct drm_device *dev);
-extern int psb_irq_disable_dpst(struct drm_device *dev);
-extern void psb_irq_preinstall(struct drm_device *dev);
-extern int psb_irq_postinstall(struct drm_device *dev);
-extern void psb_irq_uninstall(struct drm_device *dev);
-extern void psb_irq_turn_on_dpst(struct drm_device *dev);
-extern void psb_irq_turn_off_dpst(struct drm_device *dev);
-
-extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
-extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
-extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int psb_enable_vblank(struct drm_device *dev, int crtc);
-extern void psb_disable_vblank(struct drm_device *dev, int crtc);
-void
-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-
-void
-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-
-extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
-
-extern int mdfld_enable_te(struct drm_device *dev, int pipe);
-extern void mdfld_disable_te(struct drm_device *dev, int pipe);
-
-/*
- * intel_opregion.c
- */
-extern int gma_intel_opregion_init(struct drm_device *dev);
-extern int gma_intel_opregion_exit(struct drm_device *dev);
-
-/*
- * framebuffer.c
- */
-extern int psbfb_probed(struct drm_device *dev);
-extern int psbfb_remove(struct drm_device *dev,
-                       struct drm_framebuffer *fb);
-/*
- * accel_2d.c
- */
-extern void psbfb_copyarea(struct fb_info *info,
-                                       const struct fb_copyarea *region);
-extern int psbfb_sync(struct fb_info *info);
-extern void psb_spank(struct drm_psb_private *dev_priv);
-extern int psb_accel_ioctl(struct drm_device *dev, void *data,
-                                                       struct drm_file *file);
-
-/*
- * psb_reset.c
- */
-
-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
-extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
-
-/* modesetting */
-extern void psb_modeset_init(struct drm_device *dev);
-extern void psb_modeset_cleanup(struct drm_device *dev);
-extern int psb_fbdev_init(struct drm_device *dev);
-
-/* backlight.c */
-int gma_backlight_init(struct drm_device *dev);
-void gma_backlight_exit(struct drm_device *dev);
-
-/* mrst_crtc.c */
-extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
-
-/* mrst_lvds.c */
-extern void mrst_lvds_init(struct drm_device *dev,
-                   struct psb_intel_mode_device *mode_dev);
-
-/* psb_intel_display.c */
-extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs;
-extern const struct drm_crtc_funcs psb_intel_crtc_funcs;
-
-/* psb_intel_lvds.c */
-extern const struct drm_connector_helper_funcs
-                                       psb_intel_lvds_connector_helper_funcs;
-extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
-
-/* gem.c */
-extern int psb_gem_init_object(struct drm_gem_object *obj);
-extern void psb_gem_free_object(struct drm_gem_object *obj);
-extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
-                       struct drm_file *file);
-extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
-                       struct drm_mode_create_dumb *args);
-extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-                       uint32_t handle);
-extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
-                       uint32_t handle, uint64_t *offset);
-extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file);
-extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
-                                       struct drm_file *file);
-
-/* psb_device.c */
-extern const struct psb_ops psb_chip_ops;
-
-/* mrst_device.c */
-extern const struct psb_ops mrst_chip_ops;
-
-/* mdfld_device.c */
-extern const struct psb_ops mdfld_chip_ops;
-
-/* cdv_device.c */
-extern const struct psb_ops cdv_chip_ops;
-
-/*
- * Debug print bits setting
- */
-#define PSB_D_GENERAL (1 << 0)
-#define PSB_D_INIT    (1 << 1)
-#define PSB_D_IRQ     (1 << 2)
-#define PSB_D_ENTRY   (1 << 3)
-/* debug the get H/V BP/FP count */
-#define PSB_D_HV      (1 << 4)
-#define PSB_D_DBI_BF  (1 << 5)
-#define PSB_D_PM      (1 << 6)
-#define PSB_D_RENDER  (1 << 7)
-#define PSB_D_REG     (1 << 8)
-#define PSB_D_MSVDX   (1 << 9)
-#define PSB_D_TOPAZ   (1 << 10)
-
-extern int drm_psb_no_fb;
-extern int drm_idle_check_interval;
-
-/*
- *     Utilities
- */
-
-static inline u32 MRST_MSG_READ32(uint port, uint offset)
-{
-       int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
-       uint32_t ret_val = 0;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       pci_write_config_dword(pci_root, 0xD0, mcr);
-       pci_read_config_dword(pci_root, 0xD4, &ret_val);
-       pci_dev_put(pci_root);
-       return ret_val;
-}
-static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
-{
-       int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       pci_write_config_dword(pci_root, 0xD4, value);
-       pci_write_config_dword(pci_root, 0xD0, mcr);
-       pci_dev_put(pci_root);
-}
-static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
-{
-       int mcr = (0x10<<24) | (port << 16) | (offset << 8);
-       uint32_t ret_val = 0;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       pci_write_config_dword(pci_root, 0xD0, mcr);
-       pci_read_config_dword(pci_root, 0xD4, &ret_val);
-       pci_dev_put(pci_root);
-       return ret_val;
-}
-static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
-{
-       int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
-       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-       pci_write_config_dword(pci_root, 0xD4, value);
-       pci_write_config_dword(pci_root, 0xD0, mcr);
-       pci_dev_put(pci_root);
-}
-
-static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       return ioread32(dev_priv->vdc_reg + reg);
-}
-
-#define REG_READ(reg)         REGISTER_READ(dev, (reg))
-
-static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
-                                     uint32_t val)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       iowrite32((val), dev_priv->vdc_reg + (reg));
-}
-
-#define REG_WRITE(reg, val)    REGISTER_WRITE(dev, (reg), (val))
-
-static inline void REGISTER_WRITE16(struct drm_device *dev,
-                                       uint32_t reg, uint32_t val)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       iowrite16((val), dev_priv->vdc_reg + (reg));
-}
-
-#define REG_WRITE16(reg, val)    REGISTER_WRITE16(dev, (reg), (val))
-
-static inline void REGISTER_WRITE8(struct drm_device *dev,
-                                      uint32_t reg, uint32_t val)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       iowrite8((val), dev_priv->vdc_reg + (reg));
-}
-
-#define REG_WRITE8(reg, val)           REGISTER_WRITE8(dev, (reg), (val))
-
-#define PSB_WVDC32(_val, _offs)                iowrite32(_val, dev_priv->vdc_reg + (_offs))
-#define PSB_RVDC32(_offs)              ioread32(dev_priv->vdc_reg + (_offs))
-
-/* #define TRAP_SGX_PM_FAULT 1 */
-#ifdef TRAP_SGX_PM_FAULT
-#define PSB_RSGX32(_offs)                                              \
-({                                                                     \
-       if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {              \
-               printk(KERN_ERR                                         \
-                       "access sgx when it's off!! (READ) %s, %d\n",   \
-              __FILE__, __LINE__);                                     \
-               melay(1000);                                            \
-       }                                                               \
-       ioread32(dev_priv->sgx_reg + (_offs));                          \
-})
-#else
-#define PSB_RSGX32(_offs)              ioread32(dev_priv->sgx_reg + (_offs))
-#endif
-#define PSB_WSGX32(_val, _offs)                iowrite32(_val, dev_priv->sgx_reg + (_offs))
-
-#define MSVDX_REG_DUMP 0
-
-#define PSB_WMSVDX32(_val, _offs)      iowrite32(_val, dev_priv->msvdx_reg + (_offs))
-#define PSB_RMSVDX32(_offs)            ioread32(dev_priv->msvdx_reg + (_offs))
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
deleted file mode 100644 (file)
index 8565961..0000000
+++ /dev/null
@@ -1,1429 +0,0 @@
-/*
- * Copyright Ã‚© 2006-2011 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "framebuffer.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-
-#include "mdfld_output.h"
-
-struct psb_intel_clock_t {
-       /* given values */
-       int n;
-       int m1, m2;
-       int p1, p2;
-       /* derived values */
-       int dot;
-       int vco;
-       int m;
-       int p;
-};
-
-struct psb_intel_range_t {
-       int min, max;
-};
-
-struct psb_intel_p2_t {
-       int dot_limit;
-       int p2_slow, p2_fast;
-};
-
-#define INTEL_P2_NUM                 2
-
-struct psb_intel_limit_t {
-       struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1;
-       struct psb_intel_p2_t p2;
-};
-
-#define I8XX_DOT_MIN             25000
-#define I8XX_DOT_MAX            350000
-#define I8XX_VCO_MIN            930000
-#define I8XX_VCO_MAX           1400000
-#define I8XX_N_MIN                   3
-#define I8XX_N_MAX                  16
-#define I8XX_M_MIN                  96
-#define I8XX_M_MAX                 140
-#define I8XX_M1_MIN                 18
-#define I8XX_M1_MAX                 26
-#define I8XX_M2_MIN                  6
-#define I8XX_M2_MAX                 16
-#define I8XX_P_MIN                   4
-#define I8XX_P_MAX                 128
-#define I8XX_P1_MIN                  2
-#define I8XX_P1_MAX                 33
-#define I8XX_P1_LVDS_MIN             1
-#define I8XX_P1_LVDS_MAX             6
-#define I8XX_P2_SLOW                 4
-#define I8XX_P2_FAST                 2
-#define I8XX_P2_LVDS_SLOW            14
-#define I8XX_P2_LVDS_FAST            14        /* No fast option */
-#define I8XX_P2_SLOW_LIMIT      165000
-
-#define I9XX_DOT_MIN             20000
-#define I9XX_DOT_MAX            400000
-#define I9XX_VCO_MIN           1400000
-#define I9XX_VCO_MAX           2800000
-#define I9XX_N_MIN                   3
-#define I9XX_N_MAX                   8
-#define I9XX_M_MIN                  70
-#define I9XX_M_MAX                 120
-#define I9XX_M1_MIN                 10
-#define I9XX_M1_MAX                 20
-#define I9XX_M2_MIN                  5
-#define I9XX_M2_MAX                  9
-#define I9XX_P_SDVO_DAC_MIN          5
-#define I9XX_P_SDVO_DAC_MAX         80
-#define I9XX_P_LVDS_MIN                      7
-#define I9XX_P_LVDS_MAX                     98
-#define I9XX_P1_MIN                  1
-#define I9XX_P1_MAX                  8
-#define I9XX_P2_SDVO_DAC_SLOW               10
-#define I9XX_P2_SDVO_DAC_FAST                5
-#define I9XX_P2_SDVO_DAC_SLOW_LIMIT     200000
-#define I9XX_P2_LVDS_SLOW                   14
-#define I9XX_P2_LVDS_FAST                    7
-#define I9XX_P2_LVDS_SLOW_LIMIT                 112000
-
-#define INTEL_LIMIT_I8XX_DVO_DAC    0
-#define INTEL_LIMIT_I8XX_LVDS      1
-#define INTEL_LIMIT_I9XX_SDVO_DAC   2
-#define INTEL_LIMIT_I9XX_LVDS      3
-
-static const struct psb_intel_limit_t psb_intel_limits[] = {
-       {                       /* INTEL_LIMIT_I8XX_DVO_DAC */
-        .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
-        .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
-        .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
-        .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
-        .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
-        .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
-        .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
-        .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX},
-        .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
-               .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST},
-        },
-       {                       /* INTEL_LIMIT_I8XX_LVDS */
-        .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
-        .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
-        .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
-        .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
-        .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
-        .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
-        .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
-        .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX},
-        .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
-               .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST},
-        },
-       {                       /* INTEL_LIMIT_I9XX_SDVO_DAC */
-        .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
-        .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
-        .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
-        .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
-        .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
-        .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
-        .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX},
-        .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
-        .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
-               .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast =
-               I9XX_P2_SDVO_DAC_FAST},
-        },
-       {                       /* INTEL_LIMIT_I9XX_LVDS */
-        .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
-        .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
-        .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
-        .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
-        .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
-        .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
-        .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX},
-        .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
-        /* The single-channel range is 25-112Mhz, and dual-channel
-         * is 80-224Mhz.  Prefer single channel as much as possible.
-         */
-        .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
-               .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST},
-        },
-};
-
-static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc)
-{
-       const struct psb_intel_limit_t *limit;
-
-       if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-               limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS];
-       else
-               limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
-       return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-
-static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock)
-{
-       clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
-       clock->p = clock->p1 * clock->p2;
-       clock->vco = refclk * clock->m / (clock->n + 2);
-       clock->dot = clock->vco / clock->p;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
-
-static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock)
-{
-       clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
-       clock->p = clock->p1 * clock->p2;
-       clock->vco = refclk * clock->m / (clock->n + 2);
-       clock->dot = clock->vco / clock->p;
-}
-
-static void psb_intel_clock(struct drm_device *dev, int refclk,
-                       struct psb_intel_clock_t *clock)
-{
-       return i9xx_clock(refclk, clock);
-}
-
-/**
- * Returns whether any output on the specified pipe is of the specified type
- */
-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *l_entry;
-
-       list_for_each_entry(l_entry, &mode_config->connector_list, head) {
-               if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
-                       struct psb_intel_output *psb_intel_output =
-                           to_psb_intel_output(l_entry);
-                       if (psb_intel_output->type == type)
-                               return true;
-               }
-       }
-       return false;
-}
-
-#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
-/**
- * Returns whether the given set of divisors are valid for a given refclk with
- * the given connectors.
- */
-
-static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc,
-                              struct psb_intel_clock_t *clock)
-{
-       const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
-
-       if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
-               INTELPllInvalid("p1 out of range\n");
-       if (clock->p < limit->p.min || limit->p.max < clock->p)
-               INTELPllInvalid("p out of range\n");
-       if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
-               INTELPllInvalid("m2 out of range\n");
-       if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
-               INTELPllInvalid("m1 out of range\n");
-       if (clock->m1 <= clock->m2)
-               INTELPllInvalid("m1 <= m2\n");
-       if (clock->m < limit->m.min || limit->m.max < clock->m)
-               INTELPllInvalid("m out of range\n");
-       if (clock->n < limit->n.min || limit->n.max < clock->n)
-               INTELPllInvalid("n out of range\n");
-       if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
-               INTELPllInvalid("vco out of range\n");
-       /* XXX: We may need to be checking "Dot clock"
-        * depending on the multiplier, connector, etc.,
-        * rather than just a single range.
-        */
-       if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
-               INTELPllInvalid("dot out of range\n");
-
-       return true;
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
-static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target,
-                               int refclk,
-                               struct psb_intel_clock_t *best_clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_clock_t clock;
-       const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
-       int err = target;
-
-       if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-           (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
-               /*
-                * For LVDS, if the panel is on, just rely on its current
-                * settings for dual-channel.  We haven't figured out how to
-                * reliably set up different single/dual channel state, if we
-                * even can.
-                */
-               if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
-                       clock.p2 = limit->p2.p2_fast;
-               else
-                       clock.p2 = limit->p2.p2_slow;
-       } else {
-               if (target < limit->p2.dot_limit)
-                       clock.p2 = limit->p2.p2_slow;
-               else
-                       clock.p2 = limit->p2.p2_fast;
-       }
-
-       memset(best_clock, 0, sizeof(*best_clock));
-
-       for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
-            clock.m1++) {
-               for (clock.m2 = limit->m2.min;
-                    clock.m2 < clock.m1 && clock.m2 <= limit->m2.max;
-                    clock.m2++) {
-                       for (clock.n = limit->n.min;
-                            clock.n <= limit->n.max; clock.n++) {
-                               for (clock.p1 = limit->p1.min;
-                                    clock.p1 <= limit->p1.max;
-                                    clock.p1++) {
-                                       int this_err;
-
-                                       psb_intel_clock(dev, refclk, &clock);
-
-                                       if (!psb_intel_PLL_is_valid
-                                           (crtc, &clock))
-                                               continue;
-
-                                       this_err = abs(clock.dot - target);
-                                       if (this_err < err) {
-                                               *best_clock = clock;
-                                               err = this_err;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       return err != target;
-}
-
-void psb_intel_wait_for_vblank(struct drm_device *dev)
-{
-       /* Wait for 20ms, i.e. one cycle at 50hz. */
-       mdelay(20);
-}
-
-int psb_intel_pipe_set_base(struct drm_crtc *crtc,
-                           int x, int y, struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_i915_master_private *master_priv; */
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
-       int pipe = psb_intel_crtc->pipe;
-       unsigned long start, offset;
-       int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
-       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       u32 dspcntr;
-       int ret = 0;
-
-       if (!gma_power_begin(dev, true))
-               return 0;
-
-       /* no fb bound */
-       if (!crtc->fb) {
-               dev_dbg(dev->dev, "No FB bound\n");
-               goto psb_intel_pipe_cleaner;
-       }
-
-       /* We are displaying this buffer, make sure it is actually loaded
-          into the GTT */
-       ret = psb_gtt_pin(psbfb->gtt);
-       if (ret < 0)
-               goto psb_intel_pipe_set_base_exit;
-       start = psbfb->gtt->offset;
-
-       offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
-
-       dspcntr = REG_READ(dspcntr_reg);
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               dspcntr |= DISPPLANE_8BPP;
-               break;
-       case 16:
-               if (crtc->fb->depth == 15)
-                       dspcntr |= DISPPLANE_15_16BPP;
-               else
-                       dspcntr |= DISPPLANE_16BPP;
-               break;
-       case 24:
-       case 32:
-               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-               break;
-       default:
-               dev_err(dev->dev, "Unknown color depth\n");
-               ret = -EINVAL;
-               psb_gtt_unpin(psbfb->gtt);
-               goto psb_intel_pipe_set_base_exit;
-       }
-       REG_WRITE(dspcntr_reg, dspcntr);
-
-
-       if (0 /* FIXMEAC - check what PSB needs */) {
-               REG_WRITE(dspbase, offset);
-               REG_READ(dspbase);
-               REG_WRITE(dspsurf, start);
-               REG_READ(dspsurf);
-       } else {
-               REG_WRITE(dspbase, start + offset);
-               REG_READ(dspbase);
-       }
-
-psb_intel_pipe_cleaner:
-       /* If there was a previous display we can now unpin it */
-       if (old_fb)
-               psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
-       gma_power_end(dev);
-       return ret;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_i915_master_private *master_priv; */
-       /* struct drm_i915_private *dev_priv = dev->dev_private; */
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       u32 temp;
-       bool enabled;
-
-       /* XXX: When our outputs are all unaware of DPMS modes other than off
-        * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-        */
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-               /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-                       /* Wait for the clocks to stabilize. */
-                       udelay(150);
-               }
-
-               /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) == 0)
-                       REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
-
-               /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp | DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-               }
-
-               psb_intel_crtc_load_lut(crtc);
-
-               /* Give the overlay scaler a chance to enable
-                * if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, true); TODO */
-               break;
-       case DRM_MODE_DPMS_OFF:
-               /* Give the overlay scaler a chance to disable
-                * if it's on this pipe */
-               /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-
-               /* Disable the VGA plane that we never use */
-               REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
-               /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
-               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
-                                 temp & ~DISPLAY_PLANE_ENABLE);
-                       /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
-               }
-
-               /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
-               if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(pipeconf_reg);
-               }
-
-               /* Wait for vblank for the disable to take effect. */
-               psb_intel_wait_for_vblank(dev);
-
-               temp = REG_READ(dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) != 0) {
-                       REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
-               }
-
-               /* Wait for the clocks to turn off. */
-               udelay(150);
-               break;
-       }
-
-       enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
-       /*Set FIFO Watermarks*/
-       REG_WRITE(DSPARB, 0x3F3E);
-}
-
-static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void psb_intel_crtc_commit(struct drm_crtc *crtc)
-{
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-void psb_intel_encoder_prepare(struct drm_encoder *encoder)
-{
-       struct drm_encoder_helper_funcs *encoder_funcs =
-           encoder->helper_private;
-       /* lvds has its own version of prepare see psb_intel_lvds_prepare */
-       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-void psb_intel_encoder_commit(struct drm_encoder *encoder)
-{
-       struct drm_encoder_helper_funcs *encoder_funcs =
-           encoder->helper_private;
-       /* lvds has its own version of commit see psb_intel_lvds_commit */
-       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
-{
-       u32 pfit_control;
-
-       pfit_control = REG_READ(PFIT_CONTROL);
-
-       /* See if the panel fitter is in use */
-       if ((pfit_control & PFIT_ENABLE) == 0)
-               return -1;
-       /* Must be on PIPE 1 for PSB */
-       return 1;
-}
-
-static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y,
-                              struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-       int pipe = psb_intel_crtc->pipe;
-       int fp_reg = (pipe == 0) ? FPA0 : FPB0;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
-       int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-       int refclk;
-       struct psb_intel_clock_t clock;
-       u32 dpll = 0, fp = 0, dspcntr, pipeconf;
-       bool ok, is_sdvo = false, is_dvo = false;
-       bool is_crt = false, is_lvds = false, is_tv = false;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *connector;
-
-       /* No scan out no play */
-       if (crtc->fb == NULL) {
-               crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-               return 0;
-       }
-
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               struct psb_intel_output *psb_intel_output =
-                   to_psb_intel_output(connector);
-
-               if (!connector->encoder
-                   || connector->encoder->crtc != crtc)
-                       continue;
-
-               switch (psb_intel_output->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_SDVO:
-                       is_sdvo = true;
-                       break;
-               case INTEL_OUTPUT_DVO:
-                       is_dvo = true;
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       is_tv = true;
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       is_crt = true;
-                       break;
-               }
-       }
-
-       refclk = 96000;
-
-       ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
-                                &clock);
-       if (!ok) {
-               dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
-               return 0;
-       }
-
-       fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-
-       dpll = DPLL_VGA_MODE_DIS;
-       if (is_lvds) {
-               dpll |= DPLLB_MODE_LVDS;
-               dpll |= DPLL_DVO_HIGH_SPEED;
-       } else
-               dpll |= DPLLB_MODE_DAC_SERIAL;
-       if (is_sdvo) {
-               int sdvo_pixel_multiply =
-                           adjusted_mode->clock / mode->clock;
-               dpll |= DPLL_DVO_HIGH_SPEED;
-               dpll |=
-                   (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-       }
-
-       /* compute bitmask from p1 value */
-       dpll |= (1 << (clock.p1 - 1)) << 16;
-       switch (clock.p2) {
-       case 5:
-               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-               break;
-       case 7:
-               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-               break;
-       case 10:
-               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-               break;
-       case 14:
-               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-               break;
-       }
-
-       if (is_tv) {
-               /* XXX: just matching BIOS for now */
-/*     dpll |= PLL_REF_INPUT_TVCLKINBC; */
-               dpll |= 3;
-       }
-       dpll |= PLL_REF_INPUT_DREFCLK;
-
-       /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
-
-       /* Set up the display plane register */
-       dspcntr = DISPPLANE_GAMMA_ENABLE;
-
-       if (pipe == 0)
-               dspcntr |= DISPPLANE_SEL_PIPE_A;
-       else
-               dspcntr |= DISPPLANE_SEL_PIPE_B;
-
-       dspcntr |= DISPLAY_PLANE_ENABLE;
-       pipeconf |= PIPEACONF_ENABLE;
-       dpll |= DPLL_VCO_ENABLE;
-
-
-       /* Disable the panel fitter if it was on our pipe */
-       if (psb_intel_panel_fitter_pipe(dev) == pipe)
-               REG_WRITE(PFIT_CONTROL, 0);
-
-       drm_mode_debug_printmodeline(mode);
-
-       if (dpll & DPLL_VCO_ENABLE) {
-               REG_WRITE(fp_reg, fp);
-               REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
-               REG_READ(dpll_reg);
-               udelay(150);
-       }
-
-       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
-        * This is an exception to the general rule that mode_set doesn't turn
-        * things on.
-        */
-       if (is_lvds) {
-               u32 lvds = REG_READ(LVDS);
-
-               lvds &= ~LVDS_PIPEB_SELECT;
-               if (pipe == 1)
-                       lvds |= LVDS_PIPEB_SELECT;
-
-               lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-               /* Set the B0-B3 data pairs corresponding to
-                * whether we're going to
-                * set the DPLLs for dual-channel mode or not.
-                */
-               lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-               if (clock.p2 == 7)
-                       lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-
-               /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-                * appropriately here, but we need to look more
-                * thoroughly into how panels behave in the two modes.
-                */
-
-               REG_WRITE(LVDS, lvds);
-               REG_READ(LVDS);
-       }
-
-       REG_WRITE(fp_reg, fp);
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150);
-
-       /* write it again -- the BIOS does, after all */
-       REG_WRITE(dpll_reg, dpll);
-
-       REG_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150);
-
-       REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
-                 ((adjusted_mode->crtc_htotal - 1) << 16));
-       REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
-                 ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
-                 ((adjusted_mode->crtc_hsync_end - 1) << 16));
-       REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
-                 ((adjusted_mode->crtc_vtotal - 1) << 16));
-       REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
-                 ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
-                 ((adjusted_mode->crtc_vsync_end - 1) << 16));
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
-       REG_WRITE(dspsize_reg,
-                 ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-       REG_WRITE(dsppos_reg, 0);
-       REG_WRITE(pipesrc_reg,
-                 ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
-
-       psb_intel_wait_for_vblank(dev);
-
-       REG_WRITE(dspcntr_reg, dspcntr);
-
-       /* Flush the plane changes */
-       crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-
-       psb_intel_wait_for_vblank(dev);
-
-       return 0;
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv =
-                               (struct drm_psb_private *)dev->dev_private;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int palreg = PALETTE_A;
-       int i;
-
-       /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled)
-               return;
-
-       switch (psb_intel_crtc->pipe) {
-       case 0:
-               break;
-       case 1:
-               palreg = PALETTE_B;
-               break;
-       case 2:
-               palreg = PALETTE_C;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number.\n");
-               return;
-       }
-
-       if (gma_power_begin(dev, false)) {
-               for (i = 0; i < 256; i++) {
-                       REG_WRITE(palreg + 4 * i,
-                                 ((psb_intel_crtc->lut_r[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 16) |
-                                 ((psb_intel_crtc->lut_g[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 8) |
-                                 (psb_intel_crtc->lut_b[i] +
-                                 psb_intel_crtc->lut_adj[i]));
-               }
-               gma_power_end(dev);
-       } else {
-               for (i = 0; i < 256; i++) {
-                       dev_priv->save_palette_a[i] =
-                                 ((psb_intel_crtc->lut_r[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 16) |
-                                 ((psb_intel_crtc->lut_g[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 8) |
-                                 (psb_intel_crtc->lut_b[i] +
-                                 psb_intel_crtc->lut_adj[i]);
-               }
-
-       }
-}
-
-/**
- * Save HW states of giving crtc
- */
-static void psb_intel_crtc_save(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private *dev_priv =
-                       (struct drm_psb_private *)dev->dev_private; */
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       int pipeA = (psb_intel_crtc->pipe == 0);
-       uint32_t paletteReg;
-       int i;
-
-       if (!crtc_state) {
-               dev_err(dev->dev, "No CRTC state found\n");
-               return;
-       }
-
-       crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
-       crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
-       crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
-       crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
-       crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
-       crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
-       crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
-       crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
-       crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
-       crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
-       crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
-       crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
-       crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
-
-       /*NOTE: DSPSIZE DSPPOS only for psb*/
-       crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
-       crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
-
-       crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
-
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
-       for (i = 0; i < 256; ++i)
-               crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
-}
-
-/**
- * Restore HW states of giving crtc
- */
-static void psb_intel_crtc_restore(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private * dev_priv =
-                               (struct drm_psb_private *)dev->dev_private; */
-       struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
-       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
-       int pipeA = (psb_intel_crtc->pipe == 0);
-       uint32_t paletteReg;
-       int i;
-
-       if (!crtc_state) {
-               dev_err(dev->dev, "No crtc state\n");
-               return;
-       }
-
-       if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
-               REG_WRITE(pipeA ? DPLL_A : DPLL_B,
-                       crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
-               REG_READ(pipeA ? DPLL_A : DPLL_B);
-               udelay(150);
-       }
-
-       REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
-       REG_READ(pipeA ? FPA0 : FPB0);
-
-       REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
-       REG_READ(pipeA ? FPA1 : FPB1);
-
-       REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
-       REG_READ(pipeA ? DPLL_A : DPLL_B);
-       udelay(150);
-
-       REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
-       REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
-       REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
-       REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
-       REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
-       REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
-       REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
-
-       REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
-       REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
-
-       REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-       REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
-
-       psb_intel_wait_for_vblank(dev);
-
-       REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-
-       psb_intel_wait_for_vblank(dev);
-
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
-       for (i = 0; i < 256; ++i)
-               REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
-}
-
-static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
-                                struct drm_file *file_priv,
-                                uint32_t handle,
-                                uint32_t width, uint32_t height)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
-       uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
-       uint32_t temp;
-       size_t addr = 0;
-       struct gtt_range *gt;
-       struct drm_gem_object *obj;
-       int ret;
-
-       /* if we want to turn of the cursor ignore width and height */
-       if (!handle) {
-               /* turn off the cursor */
-               temp = CURSOR_MODE_DISABLE;
-
-               if (gma_power_begin(dev, false)) {
-                       REG_WRITE(control, temp);
-                       REG_WRITE(base, 0);
-                       gma_power_end(dev);
-               }
-
-               /* Unpin the old GEM object */
-               if (psb_intel_crtc->cursor_obj) {
-                       gt = container_of(psb_intel_crtc->cursor_obj,
-                                                       struct gtt_range, gem);
-                       psb_gtt_unpin(gt);
-                       drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-                       psb_intel_crtc->cursor_obj = NULL;
-               }
-
-               return 0;
-       }
-
-       /* Currently we only support 64x64 cursors */
-       if (width != 64 || height != 64) {
-               dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
-               return -EINVAL;
-       }
-
-       obj = drm_gem_object_lookup(dev, file_priv, handle);
-       if (!obj)
-               return -ENOENT;
-
-       if (obj->size < width * height * 4) {
-               dev_dbg(dev->dev, "buffer is to small\n");
-               return -ENOMEM;
-       }
-
-       gt = container_of(obj, struct gtt_range, gem);
-
-       /* Pin the memory into the GTT */
-       ret = psb_gtt_pin(gt);
-       if (ret) {
-               dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
-               return ret;
-       }
-
-
-       addr = gt->offset;      /* Or resource.start ??? */
-
-       psb_intel_crtc->cursor_addr = addr;
-
-       temp = 0;
-       /* set the pipe for the cursor */
-       temp |= (pipe << 28);
-       temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
-       if (gma_power_begin(dev, false)) {
-               REG_WRITE(control, temp);
-               REG_WRITE(base, addr);
-               gma_power_end(dev);
-       }
-
-       /* unpin the old bo */
-       if (psb_intel_crtc->cursor_obj) {
-               gt = container_of(psb_intel_crtc->cursor_obj,
-                                                       struct gtt_range, gem);
-               psb_gtt_unpin(gt);
-               drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-               psb_intel_crtc->cursor_obj = obj;
-       }
-       return 0;
-}
-
-static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-       struct drm_device *dev = crtc->dev;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       uint32_t temp = 0;
-       uint32_t addr;
-
-
-       if (x < 0) {
-               temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
-               x = -x;
-       }
-       if (y < 0) {
-               temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
-               y = -y;
-       }
-
-       temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
-       temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
-       addr = psb_intel_crtc->cursor_addr;
-
-       if (gma_power_begin(dev, false)) {
-               REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
-               REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
-               gma_power_end(dev);
-       }
-       return 0;
-}
-
-void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
-                        u16 *green, u16 *blue, uint32_t type, uint32_t size)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int i;
-
-       if (size != 256)
-               return;
-
-       for (i = 0; i < 256; i++) {
-               psb_intel_crtc->lut_r[i] = red[i] >> 8;
-               psb_intel_crtc->lut_g[i] = green[i] >> 8;
-               psb_intel_crtc->lut_b[i] = blue[i] >> 8;
-       }
-
-       psb_intel_crtc_load_lut(crtc);
-}
-
-static int psb_crtc_set_config(struct drm_mode_set *set)
-{
-       int ret;
-       struct drm_device *dev = set->crtc->dev;
-
-       pm_runtime_forbid(&dev->pdev->dev);
-       ret = drm_crtc_helper_set_config(set);
-       pm_runtime_allow(&dev->pdev->dev);
-       return ret;
-}
-
-/* Returns the clock of the currently programmed mode of the given pipe. */
-static int psb_intel_crtc_clock_get(struct drm_device *dev,
-                               struct drm_crtc *crtc)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       u32 dpll;
-       u32 fp;
-       struct psb_intel_clock_t clock;
-       bool is_lvds;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (gma_power_begin(dev, false)) {
-               dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
-               if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
-               else
-                       fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
-               is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
-               gma_power_end(dev);
-       } else {
-               dpll = (pipe == 0) ?
-                       dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
-
-               if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = (pipe == 0) ?
-                               dev_priv->saveFPA0 :
-                               dev_priv->saveFPB0;
-               else
-                       fp = (pipe == 0) ?
-                               dev_priv->saveFPA1 :
-                               dev_priv->saveFPB1;
-
-               is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
-       }
-
-       clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
-       clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
-       clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
-
-       if (is_lvds) {
-               clock.p1 =
-                   ffs((dpll &
-                        DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
-                       DPLL_FPA01_P1_POST_DIV_SHIFT);
-               clock.p2 = 14;
-
-               if ((dpll & PLL_REF_INPUT_MASK) ==
-                   PLLB_REF_INPUT_SPREADSPECTRUMIN) {
-                       /* XXX: might not be 66MHz */
-                       i8xx_clock(66000, &clock);
-               } else
-                       i8xx_clock(48000, &clock);
-       } else {
-               if (dpll & PLL_P1_DIVIDE_BY_TWO)
-                       clock.p1 = 2;
-               else {
-                       clock.p1 =
-                           ((dpll &
-                             DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
-                            DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
-               }
-               if (dpll & PLL_P2_DIVIDE_BY_4)
-                       clock.p2 = 4;
-               else
-                       clock.p2 = 2;
-
-               i8xx_clock(48000, &clock);
-       }
-
-       /* XXX: It would be nice to validate the clocks, but we can't reuse
-        * i830PllIsValid() because it relies on the xf86_config connector
-        * configuration being accurate, which it isn't necessarily.
-        */
-
-       return clock.dot;
-}
-
-/** Returns the currently programmed mode of the given pipe. */
-struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
-                                            struct drm_crtc *crtc)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int pipe = psb_intel_crtc->pipe;
-       struct drm_display_mode *mode;
-       int htot;
-       int hsync;
-       int vtot;
-       int vsync;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       if (gma_power_begin(dev, false)) {
-               htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
-               hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
-               vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
-               vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
-               gma_power_end(dev);
-       } else {
-               htot = (pipe == 0) ?
-                       dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
-               hsync = (pipe == 0) ?
-                       dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
-               vtot = (pipe == 0) ?
-                       dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
-               vsync = (pipe == 0) ?
-                       dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
-       }
-
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode)
-               return NULL;
-
-       mode->clock = psb_intel_crtc_clock_get(dev, crtc);
-       mode->hdisplay = (htot & 0xffff) + 1;
-       mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
-       mode->hsync_start = (hsync & 0xffff) + 1;
-       mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
-       mode->vdisplay = (vtot & 0xffff) + 1;
-       mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
-       mode->vsync_start = (vsync & 0xffff) + 1;
-       mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
-
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
-
-       return mode;
-}
-
-void psb_intel_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct gtt_range *gt;
-
-       /* Unpin the old GEM object */
-       if (psb_intel_crtc->cursor_obj) {
-               gt = container_of(psb_intel_crtc->cursor_obj,
-                                               struct gtt_range, gem);
-               psb_gtt_unpin(gt);
-               drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-               psb_intel_crtc->cursor_obj = NULL;
-       }
-       kfree(psb_intel_crtc->crtc_state);
-       drm_crtc_cleanup(crtc);
-       kfree(psb_intel_crtc);
-}
-
-const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
-       .dpms = psb_intel_crtc_dpms,
-       .mode_fixup = psb_intel_crtc_mode_fixup,
-       .mode_set = psb_intel_crtc_mode_set,
-       .mode_set_base = psb_intel_pipe_set_base,
-       .prepare = psb_intel_crtc_prepare,
-       .commit = psb_intel_crtc_commit,
-};
-
-const struct drm_crtc_funcs psb_intel_crtc_funcs = {
-       .save = psb_intel_crtc_save,
-       .restore = psb_intel_crtc_restore,
-       .cursor_set = psb_intel_crtc_cursor_set,
-       .cursor_move = psb_intel_crtc_cursor_move,
-       .gamma_set = psb_intel_crtc_gamma_set,
-       .set_config = psb_crtc_set_config,
-       .destroy = psb_intel_crtc_destroy,
-};
-
-/*
- * Set the default value of cursor control and base register
- * to zero. This is a workaround for h/w defect on Oaktrail
- */
-static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
-{
-       u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
-       u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
-
-       REG_WRITE(control[pipe], 0);
-       REG_WRITE(base[pipe], 0);
-}
-
-void psb_intel_crtc_init(struct drm_device *dev, int pipe,
-                    struct psb_intel_mode_device *mode_dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct psb_intel_crtc *psb_intel_crtc;
-       int i;
-       uint16_t *r_base, *g_base, *b_base;
-
-       /* We allocate a extra array of drm_connector pointers
-        * for fbdev after the crtc */
-       psb_intel_crtc =
-           kzalloc(sizeof(struct psb_intel_crtc) +
-                   (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
-                   GFP_KERNEL);
-       if (psb_intel_crtc == NULL)
-               return;
-
-       psb_intel_crtc->crtc_state =
-               kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
-       if (!psb_intel_crtc->crtc_state) {
-               dev_err(dev->dev, "Crtc state error: No memory\n");
-               kfree(psb_intel_crtc);
-               return;
-       }
-
-       /* Set the CRTC operations from the chip specific data */
-       drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
-
-       drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
-       psb_intel_crtc->pipe = pipe;
-       psb_intel_crtc->plane = pipe;
-
-       r_base = psb_intel_crtc->base.gamma_store;
-       g_base = r_base + 256;
-       b_base = g_base + 256;
-       for (i = 0; i < 256; i++) {
-               psb_intel_crtc->lut_r[i] = i;
-               psb_intel_crtc->lut_g[i] = i;
-               psb_intel_crtc->lut_b[i] = i;
-               r_base[i] = i << 8;
-               g_base[i] = i << 8;
-               b_base[i] = i << 8;
-
-               psb_intel_crtc->lut_adj[i] = 0;
-       }
-
-       psb_intel_crtc->mode_dev = mode_dev;
-       psb_intel_crtc->cursor_addr = 0;
-
-       drm_crtc_helper_add(&psb_intel_crtc->base,
-                                               dev_priv->ops->crtc_helper);
-
-       /* Setup the array of drm_connector pointer array */
-       psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
-       BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
-              dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
-       dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] =
-                                                       &psb_intel_crtc->base;
-       dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] =
-                                                       &psb_intel_crtc->base;
-       psb_intel_crtc->mode_set.connectors =
-           (struct drm_connector **) (psb_intel_crtc + 1);
-       psb_intel_crtc->mode_set.num_connectors = 0;
-       psb_intel_cursor_init(dev, pipe);
-}
-
-int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
-       struct drm_mode_object *drmmode_obj;
-       struct psb_intel_crtc *crtc;
-
-       if (!dev_priv) {
-               dev_err(dev->dev, "called with no initialization\n");
-               return -EINVAL;
-       }
-
-       drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
-                       DRM_MODE_OBJECT_CRTC);
-
-       if (!drmmode_obj) {
-               dev_err(dev->dev, "no such CRTC id\n");
-               return -EINVAL;
-       }
-
-       crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
-       pipe_from_crtc_id->pipe = crtc->pipe;
-
-       return 0;
-}
-
-struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
-{
-       struct drm_crtc *crtc = NULL;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-               if (psb_intel_crtc->pipe == pipe)
-                       break;
-       }
-       return crtc;
-}
-
-int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
-{
-       int index_mask = 0;
-       struct drm_connector *connector;
-       int entry = 0;
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
-               struct psb_intel_output *psb_intel_output =
-                   to_psb_intel_output(connector);
-               if (type_mask & (1 << psb_intel_output->type))
-                       index_mask |= (1 << entry);
-               entry++;
-       }
-       return index_mask;
-}
-
-
-void psb_intel_modeset_cleanup(struct drm_device *dev)
-{
-       drm_mode_config_cleanup(dev);
-}
-
-
-/* current intel driver doesn't take advantage of encoders
-   always give back the encoder for the connector
-*/
-struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       return &psb_intel_output->enc;
-}
-
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h
deleted file mode 100644 (file)
index 535b49a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* copyright (c) 2008, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#ifndef _INTEL_DISPLAY_H_
-#define _INTEL_DISPLAY_H_
-
-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
-void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
-                        u16 *green, u16 *blue, uint32_t type, uint32_t size);
-void psb_intel_crtc_destroy(struct drm_crtc *crtc);
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
deleted file mode 100644 (file)
index 36b554b..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __INTEL_DRV_H__
-#define __INTEL_DRV_H__
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <linux/gpio.h>
-
-/*
- * Display related stuff
- */
-
-/* store information about an Ixxx DVO */
-/* The i830->i865 use multiple DVOs with multiple i2cs */
-/* the i915, i945 have a single sDVO i2c bus - which is different */
-#define MAX_OUTPUTS 6
-/* maximum connectors per crtcs in the mode set */
-#define INTELFB_CONN_LIMIT 4
-
-#define INTEL_I2C_BUS_DVO 1
-#define INTEL_I2C_BUS_SDVO 2
-
-/* these are outputs from the chip - integrated only
- * external chips are via DVO or SDVO output */
-#define INTEL_OUTPUT_UNUSED 0
-#define INTEL_OUTPUT_ANALOG 1
-#define INTEL_OUTPUT_DVO 2
-#define INTEL_OUTPUT_SDVO 3
-#define INTEL_OUTPUT_LVDS 4
-#define INTEL_OUTPUT_TVOUT 5
-#define INTEL_OUTPUT_HDMI 6
-#define INTEL_OUTPUT_MIPI 7
-#define INTEL_OUTPUT_MIPI2 8
-
-#define INTEL_DVO_CHIP_NONE 0
-#define INTEL_DVO_CHIP_LVDS 1
-#define INTEL_DVO_CHIP_TMDS 2
-#define INTEL_DVO_CHIP_TVOUT 4
-
-/*
- * Hold information useally put on the device driver privates here,
- * since it needs to be shared across multiple of devices drivers privates.
- */
-struct psb_intel_mode_device {
-
-       /*
-        * Abstracted memory manager operations
-        */
-        size_t(*bo_offset) (struct drm_device *dev, void *bo);
-
-       /*
-        * Cursor (Can go ?)
-        */
-       int cursor_needs_physical;
-
-       /*
-        * LVDS info
-        */
-       int backlight_duty_cycle;       /* restore backlight to this value */
-       bool panel_wants_dither;
-       struct drm_display_mode *panel_fixed_mode;
-       struct drm_display_mode *panel_fixed_mode2;
-       struct drm_display_mode *vbt_mode;      /* if any */
-
-       uint32_t saveBLC_PWM_CTL;
-};
-
-struct psb_intel_i2c_chan {
-       /* for getting at dev. private (mmio etc.) */
-       struct drm_device *drm_dev;
-       u32 reg;                /* GPIO reg */
-       struct i2c_adapter adapter;
-       struct i2c_algo_bit_data algo;
-       u8 slave_addr;
-};
-
-struct psb_intel_output {
-       struct drm_connector base;
-
-       struct drm_encoder enc;
-       int type;
-
-       struct psb_intel_i2c_chan *i2c_bus;     /* for control functions */
-       struct psb_intel_i2c_chan *ddc_bus;     /* for DDC only stuff */
-       bool load_detect_temp;
-       void *dev_priv;
-
-       struct psb_intel_mode_device *mode_dev;
-       struct i2c_adapter *hdmi_i2c_adapter;   /* for control functions */
-};
-
-struct psb_intel_crtc_state {
-       uint32_t saveDSPCNTR;
-       uint32_t savePIPECONF;
-       uint32_t savePIPESRC;
-       uint32_t saveDPLL;
-       uint32_t saveFP0;
-       uint32_t saveFP1;
-       uint32_t saveHTOTAL;
-       uint32_t saveHBLANK;
-       uint32_t saveHSYNC;
-       uint32_t saveVTOTAL;
-       uint32_t saveVBLANK;
-       uint32_t saveVSYNC;
-       uint32_t saveDSPSTRIDE;
-       uint32_t saveDSPSIZE;
-       uint32_t saveDSPPOS;
-       uint32_t saveDSPBASE;
-       uint32_t savePalette[256];
-};
-
-struct psb_intel_crtc {
-       struct drm_crtc base;
-       int pipe;
-       int plane;
-       uint32_t cursor_addr;
-       u8 lut_r[256], lut_g[256], lut_b[256];
-       u8 lut_adj[256];
-       struct psb_intel_framebuffer *fbdev_fb;
-       /* a mode_set for fbdev users on this crtc */
-       struct drm_mode_set mode_set;
-
-       /* GEM object that holds our cursor */
-       struct drm_gem_object *cursor_obj;
-
-       struct drm_display_mode saved_mode;
-       struct drm_display_mode saved_adjusted_mode;
-
-       struct psb_intel_mode_device *mode_dev;
-
-       /*crtc mode setting flags*/
-       u32 mode_flags;
-
-       /* Saved Crtc HW states */
-       struct psb_intel_crtc_state *crtc_state;
-};
-
-#define to_psb_intel_crtc(x)   \
-               container_of(x, struct psb_intel_crtc, base)
-#define to_psb_intel_output(x) \
-               container_of(x, struct psb_intel_output, base)
-#define enc_to_psb_intel_output(x)     \
-               container_of(x, struct psb_intel_output, enc)
-#define to_psb_intel_framebuffer(x)    \
-               container_of(x, struct psb_intel_framebuffer, base)
-
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
-                                       const u32 reg, const char *name);
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan);
-int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output);
-extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output);
-
-extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
-                           struct psb_intel_mode_device *mode_dev);
-extern void psb_intel_crt_init(struct drm_device *dev);
-extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device);
-extern void psb_intel_dvo_init(struct drm_device *dev);
-extern void psb_intel_tv_init(struct drm_device *dev);
-extern void psb_intel_lvds_init(struct drm_device *dev,
-                           struct psb_intel_mode_device *mode_dev);
-extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level);
-extern void mrst_lvds_init(struct drm_device *dev,
-                          struct psb_intel_mode_device *mode_dev);
-extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev);
-extern void mrst_dsi_init(struct drm_device *dev,
-                          struct psb_intel_mode_device *mode_dev);
-extern void mid_dsi_init(struct drm_device *dev,
-                   struct psb_intel_mode_device *mode_dev, int dsi_num);
-
-extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
-extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
-
-extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
-                                             *connector);
-
-extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
-                                                   struct drm_crtc *crtc);
-extern void psb_intel_wait_for_vblank(struct drm_device *dev);
-extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
-                                                int pipe);
-extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
-                                            int sdvoB);
-extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector);
-extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
-                                  int enable);
-extern int intelfb_probe(struct drm_device *dev);
-extern int intelfb_remove(struct drm_device *dev,
-                         struct drm_framebuffer *fb);
-extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device
-                                                       *dev, struct
-                                                       drm_mode_fb_cmd
-                                                       *mode_cmd,
-                                                       void *mm_private);
-extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
-                                     struct drm_display_mode *mode,
-                                     struct drm_display_mode *adjusted_mode);
-extern int psb_intel_lvds_mode_valid(struct drm_connector *connector,
-                                    struct drm_display_mode *mode);
-extern int psb_intel_lvds_set_property(struct drm_connector *connector,
-                                       struct drm_property *property,
-                                       uint64_t value);
-extern void psb_intel_lvds_destroy(struct drm_connector *connector);
-extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
-
-extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
-extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
-
-#endif                         /* __INTEL_DRV_H__ */
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
deleted file mode 100644 (file)
index 21022e1..0000000
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
- * Copyright Â© 2006-2007 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- *     Dave Airlie <airlied@linux.ie>
- *     Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-/*
- * LVDS I2C backlight control macros
- */
-#define BRIGHTNESS_MAX_LEVEL 100
-#define BRIGHTNESS_MASK 0xFF
-#define BLC_I2C_TYPE   0x01
-#define BLC_PWM_TYPT   0x02
-
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-
-#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
-#define PSB_BLC_MIN_PWM_REG_FREQ       (0x2)
-#define PSB_BLC_PWM_PRECISION_FACTOR   (10)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT    (16)
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-
-struct psb_intel_lvds_priv {
-       /*
-        * Saved LVDO output states
-        */
-       uint32_t savePP_ON;
-       uint32_t savePP_OFF;
-       uint32_t saveLVDS;
-       uint32_t savePP_CONTROL;
-       uint32_t savePP_CYCLE;
-       uint32_t savePFIT_CONTROL;
-       uint32_t savePFIT_PGM_RATIOS;
-       uint32_t saveBLC_PWM_CTL;
-};
-
-
-/*
- * Returns the maximum level of the backlight duty cycle field.
- */
-static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 ret;
-
-       if (gma_power_begin(dev, false)) {
-               ret = REG_READ(BLC_PWM_CTL);
-               gma_power_end(dev);
-       } else /* Powered off, use the saved value */
-               ret = dev_priv->saveBLC_PWM_CTL;
-
-       /* Top 15bits hold the frequency mask */
-       ret = (ret &  BACKLIGHT_MODULATION_FREQ_MASK) >>
-                                       BACKLIGHT_MODULATION_FREQ_SHIFT;
-
-        ret *= 2;      /* Return a 16bit range as needed for setting */
-        if (ret == 0)
-                dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",
-                        REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL);
-       return ret;
-}
-
-/*
- * Set LVDS backlight level by I2C command
- *
- * FIXME: at some point we need to both track this for PM and also
- * disable runtime pm on MRST if the brightness is nil (ie blanked)
- */
-static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
-                                       unsigned int level)
-{
-       struct drm_psb_private *dev_priv =
-               (struct drm_psb_private *)dev->dev_private;
-
-       struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
-       u8 out_buf[2];
-       unsigned int blc_i2c_brightness;
-
-       struct i2c_msg msgs[] = {
-               {
-                       .addr = lvds_i2c_bus->slave_addr,
-                       .flags = 0,
-                       .len = 2,
-                       .buf = out_buf,
-               }
-       };
-
-       blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
-                            BRIGHTNESS_MASK /
-                            BRIGHTNESS_MAX_LEVEL);
-
-       if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
-               blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
-
-       out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
-       out_buf[1] = (u8)blc_i2c_brightness;
-
-       if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
-               dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",
-                       dev_priv->lvds_bl->brightnesscmd,
-                       blc_i2c_brightness);
-               return 0;
-       }
-
-       dev_err(dev->dev, "I2C transfer error\n");
-       return -1;
-}
-
-
-static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
-{
-       struct drm_psb_private *dev_priv =
-                       (struct drm_psb_private *)dev->dev_private;
-
-       u32 max_pwm_blc;
-       u32 blc_pwm_duty_cycle;
-
-       max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);
-
-       /*BLC_PWM_CTL Should be initiated while backlight device init*/
-       BUG_ON(max_pwm_blc == 0);
-
-       blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
-
-       if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
-               blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
-
-       blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
-       REG_WRITE(BLC_PWM_CTL,
-                 (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
-                 (blc_pwm_duty_cycle));
-
-        dev_info(dev->dev, "Backlight lvds set brightness %08x\n",
-                 (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
-                 (blc_pwm_duty_cycle));
-
-       return 0;
-}
-
-/*
- * Set LVDS backlight level either by I2C or PWM
- */
-void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-
-       dev_dbg(dev->dev, "backlight level is %d\n", level);
-
-       if (!dev_priv->lvds_bl) {
-               dev_err(dev->dev, "NO LVDS backlight info\n");
-               return;
-       }
-
-       if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
-               psb_lvds_i2c_set_brightness(dev, level);
-       else
-               psb_lvds_pwm_set_brightness(dev, level);
-}
-
-/*
- * Sets the backlight level.
- *
- * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight().
- */
-static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 blc_pwm_ctl;
-
-       if (gma_power_begin(dev, false)) {
-               blc_pwm_ctl = REG_READ(BLC_PWM_CTL);
-               blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-               REG_WRITE(BLC_PWM_CTL,
-                               (blc_pwm_ctl |
-                               (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
-               dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
-                                       (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
-               gma_power_end(dev);
-       } else {
-               blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
-                               ~BACKLIGHT_DUTY_CYCLE_MASK;
-               dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
-                                       (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
-       }
-}
-
-/*
- * Sets the power state for the panel.
- */
-static void psb_intel_lvds_set_power(struct drm_device *dev,
-                                struct psb_intel_output *output, bool on)
-{
-       u32 pp_status;
-
-       if (!gma_power_begin(dev, true)) {
-               dev_err(dev->dev, "set power, chip off!\n");
-               return;
-        }
-        
-       if (on) {
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
-                         POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-
-               psb_intel_lvds_set_backlight(dev,
-                                        output->
-                                        mode_dev->backlight_duty_cycle);
-       } else {
-               psb_intel_lvds_set_backlight(dev, 0);
-
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
-                         ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while (pp_status & PP_ON);
-       }
-
-       gma_power_end(dev);
-}
-
-static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-
-       if (mode == DRM_MODE_DPMS_ON)
-               psb_intel_lvds_set_power(dev, output, true);
-       else
-               psb_intel_lvds_set_power(dev, output, false);
-
-       /* XXX: We never power down the LVDS pairs. */
-}
-
-static void psb_intel_lvds_save(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct drm_psb_private *dev_priv =
-               (struct drm_psb_private *)dev->dev_private;
-       struct psb_intel_output *psb_intel_output =
-               to_psb_intel_output(connector);
-       struct psb_intel_lvds_priv *lvds_priv =
-               (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
-
-       lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);
-       lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);
-       lvds_priv->saveLVDS = REG_READ(LVDS);
-       lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL);
-       lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE);
-       /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/
-       lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
-       lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL);
-       lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);
-
-       /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/
-       dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
-                                               BACKLIGHT_DUTY_CYCLE_MASK);
-
-       /*
-        * If the light is off at server startup,
-        * just make it full brightness
-        */
-       if (dev_priv->backlight_duty_cycle == 0)
-               dev_priv->backlight_duty_cycle =
-               psb_intel_lvds_get_max_backlight(dev);
-
-       dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
-                       lvds_priv->savePP_ON,
-                       lvds_priv->savePP_OFF,
-                       lvds_priv->saveLVDS,
-                       lvds_priv->savePP_CONTROL,
-                       lvds_priv->savePP_CYCLE,
-                       lvds_priv->saveBLC_PWM_CTL);
-}
-
-static void psb_intel_lvds_restore(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       u32 pp_status;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-       struct psb_intel_lvds_priv *lvds_priv =
-               (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
-
-       dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
-                       lvds_priv->savePP_ON,
-                       lvds_priv->savePP_OFF,
-                       lvds_priv->saveLVDS,
-                       lvds_priv->savePP_CONTROL,
-                       lvds_priv->savePP_CYCLE,
-                       lvds_priv->saveBLC_PWM_CTL);
-
-       REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL);
-       REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL);
-       REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS);
-       REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON);
-       REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF);
-       /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/
-       REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE);
-       REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL);
-       REG_WRITE(LVDS, lvds_priv->saveLVDS);
-
-       if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) {
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
-                       POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-       } else {
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
-                       ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while (pp_status & PP_ON);
-       }
-}
-
-int psb_intel_lvds_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
-{
-       struct psb_intel_output *psb_intel_output =
-                               to_psb_intel_output(connector);
-       struct drm_display_mode *fixed_mode =
-           psb_intel_output->mode_dev->panel_fixed_mode;
-
-       if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
-               fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
-
-       /* just in case */
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return MODE_NO_DBLESCAN;
-
-       /* just in case */
-       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-               return MODE_NO_INTERLACE;
-
-       if (fixed_mode) {
-               if (mode->hdisplay > fixed_mode->hdisplay)
-                       return MODE_PANEL;
-               if (mode->vdisplay > fixed_mode->vdisplay)
-                       return MODE_PANEL;
-       }
-       return MODE_OK;
-}
-
-bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       struct psb_intel_mode_device *mode_dev =
-           enc_to_psb_intel_output(encoder)->mode_dev;
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_crtc *psb_intel_crtc =
-                               to_psb_intel_crtc(encoder->crtc);
-       struct drm_encoder *tmp_encoder;
-       struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
-       struct psb_intel_output *psb_intel_output =
-                                       enc_to_psb_intel_output(encoder);
-
-       if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
-               panel_fixed_mode = mode_dev->panel_fixed_mode2;
-
-       /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
-       if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) {
-               printk(KERN_ERR "Can't support LVDS on pipe A\n");
-               return false;
-       }
-       if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) {
-               printk(KERN_ERR "Must use PIPE A\n");
-               return false;
-       }
-       /* Should never happen!! */
-       list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
-                           head) {
-               if (tmp_encoder != encoder
-                   && tmp_encoder->crtc == encoder->crtc) {
-                       printk(KERN_ERR "Can't enable LVDS and another "
-                              "encoder on the same pipe\n");
-                       return false;
-               }
-       }
-
-       /*
-        * If we have timings from the BIOS for the panel, put them in
-        * to the adjusted mode.  The CRTC will be set up for this mode,
-        * with the panel scaling set up to source from the H/VDisplay
-        * of the original mode.
-        */
-       if (panel_fixed_mode != NULL) {
-               adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
-               adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
-               adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
-               adjusted_mode->htotal = panel_fixed_mode->htotal;
-               adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
-               adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
-               adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
-               adjusted_mode->vtotal = panel_fixed_mode->vtotal;
-               adjusted_mode->clock = panel_fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode,
-                                     CRTC_INTERLACE_HALVE_V);
-       }
-
-       /*
-        * XXX: It would be nice to support lower refresh rates on the
-        * panels to reduce power consumption, and perhaps match the
-        * user's requested refresh rate.
-        */
-
-       return true;
-}
-
-static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
-       if (!gma_power_begin(dev, true))
-               return;
-
-       mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
-       mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
-                                         BACKLIGHT_DUTY_CYCLE_MASK);
-
-       psb_intel_lvds_set_power(dev, output, false);
-
-       gma_power_end(dev);
-}
-
-static void psb_intel_lvds_commit(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-       struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
-       if (mode_dev->backlight_duty_cycle == 0)
-               mode_dev->backlight_duty_cycle =
-                   psb_intel_lvds_get_max_backlight(dev);
-
-       psb_intel_lvds_set_power(dev, output, true);
-}
-
-static void psb_intel_lvds_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_psb_private *dev_priv = dev->dev_private;
-       u32 pfit_control;
-
-       /*
-        * The LVDS pin pair will already have been turned on in the
-        * psb_intel_crtc_mode_set since it has a large impact on the DPLL
-        * settings.
-        */
-
-       /*
-        * Enable automatic panel scaling so that non-native modes fill the
-        * screen.  Should be enabled before the pipe is enabled, according to
-        * register description and PRM.
-        */
-       if (mode->hdisplay != adjusted_mode->hdisplay ||
-           mode->vdisplay != adjusted_mode->vdisplay)
-               pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
-                               HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
-                               HORIZ_INTERP_BILINEAR);
-       else
-               pfit_control = 0;
-
-       if (dev_priv->lvds_dither)
-               pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
-       REG_WRITE(PFIT_CONTROL, pfit_control);
-}
-
-/*
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
-                                                  *connector, bool force)
-{
-       return connector_status_connected;
-}
-
-/*
- * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
- */
-static int psb_intel_lvds_get_modes(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-       struct psb_intel_mode_device *mode_dev =
-                                       psb_intel_output->mode_dev;
-       int ret = 0;
-
-       if (!IS_MRST(dev))
-               ret = psb_intel_ddc_get_modes(psb_intel_output);
-
-       if (ret)
-               return ret;
-
-       /* Didn't get an EDID, so
-        * Set wide sync ranges so we get all modes
-        * handed to valid_mode for checking
-        */
-       connector->display_info.min_vfreq = 0;
-       connector->display_info.max_vfreq = 200;
-       connector->display_info.min_hfreq = 0;
-       connector->display_info.max_hfreq = 200;
-
-       if (mode_dev->panel_fixed_mode != NULL) {
-               struct drm_display_mode *mode =
-                   drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
-               drm_mode_probed_add(connector, mode);
-               return 1;
-       }
-
-       return 0;
-}
-
-/**
- * psb_intel_lvds_destroy - unregister and free LVDS structures
- * @connector: connector to free
- *
- * Unregister the DDC bus for this connector then free the driver private
- * structure.
- */
-void psb_intel_lvds_destroy(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       if (psb_intel_output->ddc_bus)
-               psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
-int psb_intel_lvds_set_property(struct drm_connector *connector,
-                                      struct drm_property *property,
-                                      uint64_t value)
-{
-       struct drm_encoder *encoder = connector->encoder;
-
-       if (!encoder)
-               return -1;
-
-       if (!strcmp(property->name, "scaling mode")) {
-               struct psb_intel_crtc *crtc =
-                                       to_psb_intel_crtc(encoder->crtc);
-               uint64_t curval;
-
-               if (!crtc)
-                       goto set_prop_error;
-
-               switch (value) {
-               case DRM_MODE_SCALE_FULLSCREEN:
-                       break;
-               case DRM_MODE_SCALE_NO_SCALE:
-                       break;
-               case DRM_MODE_SCALE_ASPECT:
-                       break;
-               default:
-                       goto set_prop_error;
-               }
-
-               if (drm_connector_property_get_value(connector,
-                                                    property,
-                                                    &curval))
-                       goto set_prop_error;
-
-               if (curval == value)
-                       goto set_prop_done;
-
-               if (drm_connector_property_set_value(connector,
-                                                       property,
-                                                       value))
-                       goto set_prop_error;
-
-               if (crtc->saved_mode.hdisplay != 0 &&
-                   crtc->saved_mode.vdisplay != 0) {
-                       if (!drm_crtc_helper_set_mode(encoder->crtc,
-                                                     &crtc->saved_mode,
-                                                     encoder->crtc->x,
-                                                     encoder->crtc->y,
-                                                     encoder->crtc->fb))
-                               goto set_prop_error;
-               }
-       } else if (!strcmp(property->name, "backlight")) {
-               if (drm_connector_property_set_value(connector,
-                                                       property,
-                                                       value))
-                       goto set_prop_error;
-               else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-                       struct drm_psb_private *devp =
-                                               encoder->dev->dev_private;
-                       struct backlight_device *bd = devp->backlight_device;
-                       if (bd) {
-                               bd->props.brightness = value;
-                               backlight_update_status(bd);
-                       }
-#endif
-               }
-       } else if (!strcmp(property->name, "DPMS")) {
-               struct drm_encoder_helper_funcs *hfuncs
-                                               = encoder->helper_private;
-               hfuncs->dpms(encoder, value);
-       }
-
-set_prop_done:
-       return 0;
-set_prop_error:
-       return -1;
-}
-
-static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = {
-       .dpms = psb_intel_lvds_encoder_dpms,
-       .mode_fixup = psb_intel_lvds_mode_fixup,
-       .prepare = psb_intel_lvds_prepare,
-       .mode_set = psb_intel_lvds_mode_set,
-       .commit = psb_intel_lvds_commit,
-};
-
-const struct drm_connector_helper_funcs
-                               psb_intel_lvds_connector_helper_funcs = {
-       .get_modes = psb_intel_lvds_get_modes,
-       .mode_valid = psb_intel_lvds_mode_valid,
-       .best_encoder = psb_intel_best_encoder,
-};
-
-const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .save = psb_intel_lvds_save,
-       .restore = psb_intel_lvds_restore,
-       .detect = psb_intel_lvds_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .set_property = psb_intel_lvds_set_property,
-       .destroy = psb_intel_lvds_destroy,
-};
-
-
-static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
-       .destroy = psb_intel_lvds_enc_destroy,
-};
-
-
-
-/**
- * psb_intel_lvds_init - setup LVDS connectors on this device
- * @dev: drm device
- *
- * Create the connector, register the LVDS DDC bus, and try to figure out what
- * modes we can display on the LVDS panel (if present).
- */
-void psb_intel_lvds_init(struct drm_device *dev,
-                    struct psb_intel_mode_device *mode_dev)
-{
-       struct psb_intel_output *psb_intel_output;
-       struct psb_intel_lvds_priv *lvds_priv;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-       struct drm_display_mode *scan;  /* *modes, *bios_mode; */
-       struct drm_crtc *crtc;
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 lvds;
-       int pipe;
-
-       psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
-       if (!lvds_priv) {
-               kfree(psb_intel_output);
-               dev_err(dev->dev, "LVDS private allocation error\n");
-               return;
-       }
-
-       psb_intel_output->dev_priv = lvds_priv;
-       psb_intel_output->mode_dev = mode_dev;
-
-       connector = &psb_intel_output->base;
-       encoder = &psb_intel_output->enc;
-       drm_connector_init(dev, &psb_intel_output->base,
-                          &psb_intel_lvds_connector_funcs,
-                          DRM_MODE_CONNECTOR_LVDS);
-
-       drm_encoder_init(dev, &psb_intel_output->enc,
-                        &psb_intel_lvds_enc_funcs,
-                        DRM_MODE_ENCODER_LVDS);
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-       psb_intel_output->type = INTEL_OUTPUT_LVDS;
-
-       drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);
-       drm_connector_helper_add(connector,
-                                &psb_intel_lvds_connector_helper_funcs);
-       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-
-       /*Attach connector properties*/
-       drm_connector_attach_property(connector,
-                                     dev->mode_config.scaling_mode_property,
-                                     DRM_MODE_SCALE_FULLSCREEN);
-       drm_connector_attach_property(connector,
-                                     dev_priv->backlight_property,
-                                     BRIGHTNESS_MAX_LEVEL);
-
-       /*
-        * Set up I2C bus
-        * FIXME: distroy i2c_bus when exit
-        */
-       psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
-                                                        GPIOB,
-                                                        "LVDSBLC_B");
-       if (!psb_intel_output->i2c_bus) {
-               dev_printk(KERN_ERR,
-                       &dev->pdev->dev, "I2C bus registration failed.\n");
-               goto failed_blc_i2c;
-       }
-       psb_intel_output->i2c_bus->slave_addr = 0x2C;
-       dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus;
-
-       /*
-        * LVDS discovery:
-        * 1) check for EDID on DDC
-        * 2) check for VBT data
-        * 3) check to see if LVDS is already on
-        *    if none of the above, no panel
-        * 4) make sure lid is open
-        *    if closed, act like it's not there for now
-        */
-
-       /* Set up the DDC bus. */
-       psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
-                                                        GPIOC,
-                                                        "LVDSDDC_C");
-       if (!psb_intel_output->ddc_bus) {
-               dev_printk(KERN_ERR, &dev->pdev->dev,
-                          "DDC bus registration " "failed.\n");
-               goto failed_ddc;
-       }
-
-       /*
-        * Attempt to get the fixed panel mode from DDC.  Assume that the
-        * preferred mode is the right one.
-        */
-       psb_intel_ddc_get_modes(psb_intel_output);
-       list_for_each_entry(scan, &connector->probed_modes, head) {
-               if (scan->type & DRM_MODE_TYPE_PREFERRED) {
-                       mode_dev->panel_fixed_mode =
-                           drm_mode_duplicate(dev, scan);
-                       goto out;       /* FIXME: check for quirks */
-               }
-       }
-
-       /* Failed to get EDID, what about VBT? do we need this? */
-       if (mode_dev->vbt_mode)
-               mode_dev->panel_fixed_mode =
-                   drm_mode_duplicate(dev, mode_dev->vbt_mode);
-
-       if (!mode_dev->panel_fixed_mode)
-               if (dev_priv->lfp_lvds_vbt_mode)
-                       mode_dev->panel_fixed_mode =
-                               drm_mode_duplicate(dev,
-                                       dev_priv->lfp_lvds_vbt_mode);
-
-       /*
-        * If we didn't get EDID, try checking if the panel is already turned
-        * on.  If so, assume that whatever is currently programmed is the
-        * correct mode.
-        */
-       lvds = REG_READ(LVDS);
-       pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
-       crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
-
-       if (crtc && (lvds & LVDS_PORT_EN)) {
-               mode_dev->panel_fixed_mode =
-                   psb_intel_crtc_mode_get(dev, crtc);
-               if (mode_dev->panel_fixed_mode) {
-                       mode_dev->panel_fixed_mode->type |=
-                           DRM_MODE_TYPE_PREFERRED;
-                       goto out;       /* FIXME: check for quirks */
-               }
-       }
-
-       /* If we still don't have a mode after all that, give up. */
-       if (!mode_dev->panel_fixed_mode) {
-               dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
-               goto failed_find;
-       }
-
-       /*
-        * Blacklist machines with BIOSes that list an LVDS panel without
-        * actually having one.
-        */
-out:
-       drm_sysfs_connector_add(connector);
-       return;
-
-failed_find:
-       if (psb_intel_output->ddc_bus)
-               psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-failed_ddc:
-       if (psb_intel_output->i2c_bus)
-               psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-failed_blc_i2c:
-       drm_encoder_cleanup(encoder);
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c
deleted file mode 100644 (file)
index bde1aff..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2007 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authers: Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <drm/drmP.h>
-#include "psb_intel_drv.h"
-
-/**
- * psb_intel_ddc_probe
- *
- */
-bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output)
-{
-       u8 out_buf[] = { 0x0, 0x0 };
-       u8 buf[2];
-       int ret;
-       struct i2c_msg msgs[] = {
-               {
-                .addr = 0x50,
-                .flags = 0,
-                .len = 1,
-                .buf = out_buf,
-                },
-               {
-                .addr = 0x50,
-                .flags = I2C_M_RD,
-                .len = 1,
-                .buf = buf,
-                }
-       };
-
-       ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2);
-       if (ret == 2)
-               return true;
-
-       return false;
-}
-
-/**
- * psb_intel_ddc_get_modes - get modelist from monitor
- * @connector: DRM connector device to use
- *
- * Fetch the EDID information from @connector using the DDC bus.
- */
-int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output)
-{
-       struct edid *edid;
-       int ret = 0;
-
-       edid =
-           drm_get_edid(&psb_intel_output->base,
-                        &psb_intel_output->ddc_bus->adapter);
-       if (edid) {
-               drm_mode_connector_update_edid_property(&psb_intel_output->
-                                                       base, edid);
-               ret = drm_add_edid_modes(&psb_intel_output->base, edid);
-               kfree(edid);
-       }
-       return ret;
-}
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h
deleted file mode 100644 (file)
index 1ac16aa..0000000
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- * Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef __PSB_INTEL_REG_H__
-#define __PSB_INTEL_REG_H__
-
-#define BLC_PWM_CTL            0x61254
-#define BLC_PWM_CTL2           0x61250
-#define BLC_PWM_CTL_C          0x62254
-#define BLC_PWM_CTL2_C         0x62250
-#define BACKLIGHT_MODULATION_FREQ_SHIFT                (17)
-/*
- * This is the most significant 15 bits of the number of backlight cycles in a
- * complete cycle of the modulated backlight control.
- *
- * The actual value is this field multiplied by two.
- */
-#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
-#define BLM_LEGACY_MODE                        (1 << 16)
-/*
- * This is the number of cycles out of the backlight modulation cycle for which
- * the backlight is on.
- *
- * This field must be no greater than the number of cycles in the complete
- * backlight modulation cycle.
- */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT     (0)
-#define BACKLIGHT_DUTY_CYCLE_MASK      (0xffff)
-
-#define I915_GCFGC                     0xf0
-#define I915_LOW_FREQUENCY_ENABLE      (1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ     (4 << 4)
-#define I915_DISPLAY_CLOCK_MASK                (7 << 4)
-
-#define I855_HPLLCC                    0xc0
-#define I855_CLOCK_CONTROL_MASK                (3 << 0)
-#define I855_CLOCK_133_200             (0 << 0)
-#define I855_CLOCK_100_200             (1 << 0)
-#define I855_CLOCK_100_133             (2 << 0)
-#define I855_CLOCK_166_250             (3 << 0)
-
-/* I830 CRTC registers */
-#define HTOTAL_A               0x60000
-#define HBLANK_A               0x60004
-#define HSYNC_A                        0x60008
-#define VTOTAL_A               0x6000c
-#define VBLANK_A               0x60010
-#define VSYNC_A                        0x60014
-#define PIPEASRC               0x6001c
-#define BCLRPAT_A              0x60020
-#define VSYNCSHIFT_A           0x60028
-
-#define HTOTAL_B               0x61000
-#define HBLANK_B               0x61004
-#define HSYNC_B                        0x61008
-#define VTOTAL_B               0x6100c
-#define VBLANK_B               0x61010
-#define VSYNC_B                        0x61014
-#define PIPEBSRC               0x6101c
-#define BCLRPAT_B              0x61020
-#define VSYNCSHIFT_B           0x61028
-
-#define HTOTAL_C               0x62000
-#define HBLANK_C               0x62004
-#define HSYNC_C                        0x62008
-#define VTOTAL_C               0x6200c
-#define VBLANK_C               0x62010
-#define VSYNC_C                        0x62014
-#define PIPECSRC               0x6201c
-#define BCLRPAT_C              0x62020
-#define VSYNCSHIFT_C           0x62028
-
-#define PP_STATUS              0x61200
-# define PP_ON                         (1 << 31)
-/*
- * Indicates that all dependencies of the panel are on:
- *
- * - PLL enabled
- * - pipe enabled
- * - LVDS/DVOB/DVOC on
- */
-#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_CONTROL             0x61204
-#define POWER_TARGET_ON                        (1 << 0)
-
-#define LVDSPP_ON              0x61208
-#define LVDSPP_OFF             0x6120c
-#define PP_CYCLE               0x61210
-
-#define PFIT_CONTROL           0x61230
-#define PFIT_ENABLE                    (1 << 31)
-#define PFIT_PIPE_MASK                 (3 << 29)
-#define PFIT_PIPE_SHIFT                        29
-#define PFIT_SCALING_MODE_PILLARBOX    (1 << 27)
-#define PFIT_SCALING_MODE_LETTERBOX    (3 << 26)
-#define VERT_INTERP_DISABLE            (0 << 10)
-#define VERT_INTERP_BILINEAR           (1 << 10)
-#define VERT_INTERP_MASK               (3 << 10)
-#define VERT_AUTO_SCALE                        (1 << 9)
-#define HORIZ_INTERP_DISABLE           (0 << 6)
-#define HORIZ_INTERP_BILINEAR          (1 << 6)
-#define HORIZ_INTERP_MASK              (3 << 6)
-#define HORIZ_AUTO_SCALE               (1 << 5)
-#define PANEL_8TO6_DITHER_ENABLE       (1 << 3)
-
-#define PFIT_PGM_RATIOS                0x61234
-#define PFIT_VERT_SCALE_MASK                   0xfff00000
-#define PFIT_HORIZ_SCALE_MASK                  0x0000fff0
-
-#define PFIT_AUTO_RATIOS       0x61238
-
-#define DPLL_A                 0x06014
-#define DPLL_B                 0x06018
-#define DPLL_VCO_ENABLE                        (1 << 31)
-#define DPLL_DVO_HIGH_SPEED            (1 << 30)
-#define DPLL_SYNCLOCK_ENABLE           (1 << 29)
-#define DPLL_VGA_MODE_DIS              (1 << 28)
-#define DPLLB_MODE_DAC_SERIAL          (1 << 26)       /* i915 */
-#define DPLLB_MODE_LVDS                        (2 << 26)       /* i915 */
-#define DPLL_MODE_MASK                 (3 << 26)
-#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10        (0 << 24)       /* i915 */
-#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24)       /* i915 */
-#define DPLLB_LVDS_P2_CLOCK_DIV_14     (0 << 24)       /* i915 */
-#define DPLLB_LVDS_P2_CLOCK_DIV_7      (1 << 24)       /* i915 */
-#define DPLL_P2_CLOCK_DIV_MASK         0x03000000      /* i915 */
-#define DPLL_FPA01_P1_POST_DIV_MASK    0x00ff0000      /* i915 */
-#define DPLL_LOCK                      (1 << 15)       /* CDV */
-
-/*
- *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830      0x001f0000
-/*
- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
- * this field (only one bit may be set).
- */
-#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS  0x003f0000
-#define DPLL_FPA01_P1_POST_DIV_SHIFT   16
-#define PLL_P2_DIVIDE_BY_4             (1 << 23)       /* i830, required
-                                                        * in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO          (1 << 21)       /* i830 */
-#define PLL_REF_INPUT_DREFCLK          (0 << 13)
-#define PLL_REF_INPUT_TVCLKINA         (1 << 13)       /* i830 */
-#define PLL_REF_INPUT_TVCLKINBC                (2 << 13)       /* SDVO
-                                                                * TVCLKIN */
-#define PLLB_REF_INPUT_SPREADSPECTRUMIN        (3 << 13)
-#define PLL_REF_INPUT_MASK             (3 << 13)
-#define PLL_LOAD_PULSE_PHASE_SHIFT     9
-/*
- * Parallel to Serial Load Pulse phase selection.
- * Selects the phase for the 10X DPLL clock for the PCIe
- * digital display port. The range is 4 to 13; 10 or more
- * is just a flip delay. The default is 6
- */
-#define PLL_LOAD_PULSE_PHASE_MASK      (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-#define DISPLAY_RATE_SELECT_FPA1       (1 << 8)
-
-/*
- * SDVO multiplier for 945G/GM. Not used on 965.
- *
- * DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_MULTIPLIER_MASK           0x000000ff
-#define SDVO_MULTIPLIER_SHIFT_HIRES    4
-#define SDVO_MULTIPLIER_SHIFT_VGA      0
-
-/*
- * PLL_MD
- */
-/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_A_MD              0x0601c
-/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_B_MD              0x06020
-/*
- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
- *
- * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
- */
-#define DPLL_MD_UDI_DIVIDER_MASK       0x3f000000
-#define DPLL_MD_UDI_DIVIDER_SHIFT      24
-/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-#define DPLL_MD_VGA_UDI_DIVIDER_MASK   0x003f0000
-#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT  16
-/*
- * SDVO/UDI pixel multiplier.
- *
- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
- * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
- * dummy bytes in the datastream at an increased clock rate, with both sides of
- * the link knowing how many bytes are fill.
- *
- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
- * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
- * through an SDVO command.
- *
- * This register field has values of multiplication factor minus 1, with
- * a maximum multiplier of 5 for SDVO.
- */
-#define DPLL_MD_UDI_MULTIPLIER_MASK    0x00003f00
-#define DPLL_MD_UDI_MULTIPLIER_SHIFT   8
-/*
- * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
- * This best be set to the default value (3) or the CRT won't work. No,
- * I don't entirely understand what this does...
- */
-#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK        0x0000003f
-#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
-
-#define DPLL_TEST              0x606c
-#define DPLLB_TEST_SDVO_DIV_1          (0 << 22)
-#define DPLLB_TEST_SDVO_DIV_2          (1 << 22)
-#define DPLLB_TEST_SDVO_DIV_4          (2 << 22)
-#define DPLLB_TEST_SDVO_DIV_MASK       (3 << 22)
-#define DPLLB_TEST_N_BYPASS            (1 << 19)
-#define DPLLB_TEST_M_BYPASS            (1 << 18)
-#define DPLLB_INPUT_BUFFER_ENABLE      (1 << 16)
-#define DPLLA_TEST_N_BYPASS            (1 << 3)
-#define DPLLA_TEST_M_BYPASS            (1 << 2)
-#define DPLLA_INPUT_BUFFER_ENABLE      (1 << 0)
-
-#define ADPA                   0x61100
-#define ADPA_DAC_ENABLE                        (1 << 31)
-#define ADPA_DAC_DISABLE               0
-#define ADPA_PIPE_SELECT_MASK          (1 << 30)
-#define ADPA_PIPE_A_SELECT             0
-#define ADPA_PIPE_B_SELECT             (1 << 30)
-#define ADPA_USE_VGA_HVPOLARITY                (1 << 15)
-#define ADPA_SETS_HVPOLARITY           0
-#define ADPA_VSYNC_CNTL_DISABLE                (1 << 11)
-#define ADPA_VSYNC_CNTL_ENABLE         0
-#define ADPA_HSYNC_CNTL_DISABLE                (1 << 10)
-#define ADPA_HSYNC_CNTL_ENABLE         0
-#define ADPA_VSYNC_ACTIVE_HIGH         (1 << 4)
-#define ADPA_VSYNC_ACTIVE_LOW          0
-#define ADPA_HSYNC_ACTIVE_HIGH         (1 << 3)
-#define ADPA_HSYNC_ACTIVE_LOW          0
-
-#define FPA0                   0x06040
-#define FPA1                   0x06044
-#define FPB0                   0x06048
-#define FPB1                   0x0604c
-#define FP_N_DIV_MASK                  0x003f0000
-#define FP_N_DIV_SHIFT                 16
-#define FP_M1_DIV_MASK                 0x00003f00
-#define FP_M1_DIV_SHIFT                        8
-#define FP_M2_DIV_MASK                 0x0000003f
-#define FP_M2_DIV_SHIFT                        0
-
-#define PORT_HOTPLUG_EN                0x61110
-#define SDVOB_HOTPLUG_INT_EN           (1 << 26)
-#define SDVOC_HOTPLUG_INT_EN           (1 << 25)
-#define TV_HOTPLUG_INT_EN              (1 << 18)
-#define CRT_HOTPLUG_INT_EN             (1 << 9)
-#define CRT_HOTPLUG_FORCE_DETECT       (1 << 3)
-/* CDV.. */
-#define CRT_HOTPLUG_ACTIVATION_PERIOD_64       (1 << 8)
-#define CRT_HOTPLUG_DAC_ON_TIME_2M             (0 << 7)
-#define CRT_HOTPLUG_DAC_ON_TIME_4M             (1 << 7)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_40         (0 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_50         (1 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_60         (2 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_70         (3 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK       (3 << 5)
-#define CRT_HOTPLUG_DETECT_DELAY_1G            (0 << 4)
-#define CRT_HOTPLUG_DETECT_DELAY_2G            (1 << 4)
-#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV       (0 << 2)
-#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
-#define CRT_HOTPLUG_DETECT_MASK                        0x000000F8
-
-#define PORT_HOTPLUG_STAT      0x61114
-#define CRT_HOTPLUG_INT_STATUS         (1 << 11)
-#define TV_HOTPLUG_INT_STATUS          (1 << 10)
-#define CRT_HOTPLUG_MONITOR_MASK       (3 << 8)
-#define CRT_HOTPLUG_MONITOR_COLOR      (3 << 8)
-#define CRT_HOTPLUG_MONITOR_MONO       (2 << 8)
-#define CRT_HOTPLUG_MONITOR_NONE       (0 << 8)
-#define SDVOC_HOTPLUG_INT_STATUS       (1 << 7)
-#define SDVOB_HOTPLUG_INT_STATUS       (1 << 6)
-
-#define SDVOB                  0x61140
-#define SDVOC                  0x61160
-#define SDVO_ENABLE                    (1 << 31)
-#define SDVO_PIPE_B_SELECT             (1 << 30)
-#define SDVO_STALL_SELECT              (1 << 29)
-#define SDVO_INTERRUPT_ENABLE          (1 << 26)
-
-/**
- * 915G/GM SDVO pixel multiplier.
- *
- * Programmed value is multiplier - 1, up to 5x.
- *
- * DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_PORT_MULTIPLY_MASK                (7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT       23
-#define SDVO_PHASE_SELECT_MASK         (15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT      (6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT       (1 << 18)
-#define SDVOC_GANG_MODE                        (1 << 16)
-#define SDVO_BORDER_ENABLE             (1 << 7)
-#define SDVOB_PCIE_CONCURRENCY         (1 << 3)
-#define SDVO_DETECTED                  (1 << 2)
-/* Bits to be preserved when writing */
-#define SDVOB_PRESERVE_MASK            ((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK            (1 << 17)
-
-/*
- * This register controls the LVDS output enable, pipe selection, and data
- * format selection.
- *
- * All of the clock/data pairs are force powered down by power sequencing.
- */
-#define LVDS                   0x61180
-/*
- * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
- * the DPLL semantics change when the LVDS is assigned to that pipe.
- */
-#define LVDS_PORT_EN                   (1 << 31)
-/* Selects pipe B for LVDS data.  Must be set on pre-965. */
-#define LVDS_PIPEB_SELECT              (1 << 30)
-
-/* Turns on border drawing to allow centered display. */
-#define LVDS_BORDER_EN                 (1 << 15)
-
-/*
- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
- * pixel.
- */
-#define LVDS_A0A2_CLKA_POWER_MASK      (3 << 8)
-#define LVDS_A0A2_CLKA_POWER_DOWN      (0 << 8)
-#define LVDS_A0A2_CLKA_POWER_UP                (3 << 8)
-/*
- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
- * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
- * on.
- */
-#define LVDS_A3_POWER_MASK             (3 << 6)
-#define LVDS_A3_POWER_DOWN             (0 << 6)
-#define LVDS_A3_POWER_UP               (3 << 6)
-/*
- * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
- * is set.
- */
-#define LVDS_CLKB_POWER_MASK           (3 << 4)
-#define LVDS_CLKB_POWER_DOWN           (0 << 4)
-#define LVDS_CLKB_POWER_UP             (3 << 4)
-/*
- * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
- * setting for whether we are in dual-channel mode.  The B3 pair will
- * additionally only be powered up when LVDS_A3_POWER_UP is set.
- */
-#define LVDS_B0B3_POWER_MASK           (3 << 2)
-#define LVDS_B0B3_POWER_DOWN           (0 << 2)
-#define LVDS_B0B3_POWER_UP             (3 << 2)
-
-#define PIPEACONF              0x70008
-#define PIPEACONF_ENABLE               (1 << 31)
-#define PIPEACONF_DISABLE              0
-#define PIPEACONF_DOUBLE_WIDE          (1 << 30)
-#define PIPECONF_ACTIVE                        (1 << 30)
-#define I965_PIPECONF_ACTIVE           (1 << 30)
-#define PIPECONF_DSIPLL_LOCK           (1 << 29)
-#define PIPEACONF_SINGLE_WIDE          0
-#define PIPEACONF_PIPE_UNLOCKED                0
-#define PIPEACONF_DSR                  (1 << 26)
-#define PIPEACONF_PIPE_LOCKED          (1 << 25)
-#define PIPEACONF_PALETTE              0
-#define PIPECONF_FORCE_BORDER          (1 << 25)
-#define PIPEACONF_GAMMA                        (1 << 24)
-#define PIPECONF_PROGRESSIVE           (0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION  (6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY                (7 << 21)
-#define PIPECONF_PLANE_OFF             (1 << 19)
-#define PIPECONF_CURSOR_OFF            (1 << 18)
-
-#define PIPEBCONF              0x71008
-#define PIPEBCONF_ENABLE               (1 << 31)
-#define PIPEBCONF_DISABLE              0
-#define PIPEBCONF_DOUBLE_WIDE          (1 << 30)
-#define PIPEBCONF_DISABLE              0
-#define PIPEBCONF_GAMMA                        (1 << 24)
-#define PIPEBCONF_PALETTE              0
-
-#define PIPECCONF              0x72008
-
-#define PIPEBGCMAXRED          0x71010
-#define PIPEBGCMAXGREEN                0x71014
-#define PIPEBGCMAXBLUE         0x71018
-
-#define PIPEASTAT              0x70024
-#define PIPEBSTAT              0x71024
-#define PIPECSTAT              0x72024
-#define PIPE_VBLANK_INTERRUPT_STATUS           (1UL << 1)
-#define PIPE_START_VBLANK_INTERRUPT_STATUS     (1UL << 2)
-#define PIPE_VBLANK_CLEAR                      (1 << 1)
-#define PIPE_VBLANK_STATUS                     (1 << 1)
-#define PIPE_TE_STATUS                         (1UL << 6)
-#define PIPE_DPST_EVENT_STATUS                 (1UL << 7)
-#define PIPE_VSYNC_CLEAR                       (1UL << 9)
-#define PIPE_VSYNC_STATUS                      (1UL << 9)
-#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS                (1UL << 10)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS     (1UL << 11)
-#define PIPE_VBLANK_INTERRUPT_ENABLE           (1UL << 17)
-#define PIPE_START_VBLANK_INTERRUPT_ENABLE     (1UL << 18)
-#define PIPE_TE_ENABLE                         (1UL << 22)
-#define PIPE_DPST_EVENT_ENABLE                 (1UL << 23)
-#define PIPE_VSYNC_ENABL                       (1UL << 25)
-#define PIPE_HDMI_AUDIO_UNDERRUN               (1UL << 26)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE            (1UL << 27)
-#define PIPE_HDMI_AUDIO_INT_MASK               (PIPE_HDMI_AUDIO_UNDERRUN | \
-                                               PIPE_HDMI_AUDIO_BUFFER_DONE)
-#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16))
-#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17))
-#define HISTOGRAM_INT_CONTROL          0x61268
-#define HISTOGRAM_BIN_DATA             0X61264
-#define HISTOGRAM_LOGIC_CONTROL                0x61260
-#define PWM_CONTROL_LOGIC              0x61250
-#define PIPE_HOTPLUG_INTERRUPT_STATUS          (1UL << 10)
-#define HISTOGRAM_INTERRUPT_ENABLE             (1UL << 31)
-#define HISTOGRAM_LOGIC_ENABLE                 (1UL << 31)
-#define PWM_LOGIC_ENABLE                       (1UL << 31)
-#define PWM_PHASEIN_ENABLE                     (1UL << 25)
-#define PWM_PHASEIN_INT_ENABLE                 (1UL << 24)
-#define PWM_PHASEIN_VB_COUNT                   0x00001f00
-#define PWM_PHASEIN_INC                                0x0000001f
-#define HISTOGRAM_INT_CTRL_CLEAR               (1UL << 30)
-#define DPST_YUV_LUMA_MODE                     0
-
-struct dpst_ie_histogram_control {
-       union {
-               uint32_t data;
-               struct {
-                       uint32_t bin_reg_index:7;
-                       uint32_t reserved:4;
-                       uint32_t bin_reg_func_select:1;
-                       uint32_t sync_to_phase_in:1;
-                       uint32_t alt_enhancement_mode:2;
-                       uint32_t reserved1:1;
-                       uint32_t sync_to_phase_in_count:8;
-                       uint32_t histogram_mode_select:1;
-                       uint32_t reserved2:4;
-                       uint32_t ie_pipe_assignment:1;
-                       uint32_t ie_mode_table_enabled:1;
-                       uint32_t ie_histogram_enable:1;
-               };
-       };
-};
-
-struct dpst_guardband {
-       union {
-               uint32_t data;
-               struct {
-                       uint32_t guardband:22;
-                       uint32_t guardband_interrupt_delay:8;
-                       uint32_t interrupt_status:1;
-                       uint32_t interrupt_enable:1;
-               };
-       };
-};
-
-#define PIPEAFRAMEHIGH         0x70040
-#define PIPEAFRAMEPIXEL                0x70044
-#define PIPEBFRAMEHIGH         0x71040
-#define PIPEBFRAMEPIXEL                0x71044
-#define PIPECFRAMEHIGH         0x72040
-#define PIPECFRAMEPIXEL                0x72044
-#define PIPE_FRAME_HIGH_MASK   0x0000ffff
-#define PIPE_FRAME_HIGH_SHIFT  0
-#define PIPE_FRAME_LOW_MASK    0xff000000
-#define PIPE_FRAME_LOW_SHIFT   24
-#define PIPE_PIXEL_MASK                0x00ffffff
-#define PIPE_PIXEL_SHIFT       0
-
-#define DSPARB                 0x70030
-#define DSPFW1                 0x70034
-#define DSPFW2                 0x70038
-#define DSPFW3                 0x7003c
-#define DSPFW4                 0x70050
-#define DSPFW5                 0x70054
-#define DSPFW6                 0x70058
-#define DSPCHICKENBIT          0x70400
-#define DSPACNTR               0x70180
-#define DSPBCNTR               0x71180
-#define DSPCCNTR               0x72180
-#define DISPLAY_PLANE_ENABLE                   (1 << 31)
-#define DISPLAY_PLANE_DISABLE                  0
-#define DISPPLANE_GAMMA_ENABLE                 (1 << 30)
-#define DISPPLANE_GAMMA_DISABLE                        0
-#define DISPPLANE_PIXFORMAT_MASK               (0xf << 26)
-#define DISPPLANE_8BPP                         (0x2 << 26)
-#define DISPPLANE_15_16BPP                     (0x4 << 26)
-#define DISPPLANE_16BPP                                (0x5 << 26)
-#define DISPPLANE_32BPP_NO_ALPHA               (0x6 << 26)
-#define DISPPLANE_32BPP                                (0x7 << 26)
-#define DISPPLANE_STEREO_ENABLE                        (1 << 25)
-#define DISPPLANE_STEREO_DISABLE               0
-#define DISPPLANE_SEL_PIPE_MASK                        (1 << 24)
-#define DISPPLANE_SEL_PIPE_POS                 24
-#define DISPPLANE_SEL_PIPE_A                   0
-#define DISPPLANE_SEL_PIPE_B                   (1 << 24)
-#define DISPPLANE_SRC_KEY_ENABLE               (1 << 22)
-#define DISPPLANE_SRC_KEY_DISABLE              0
-#define DISPPLANE_LINE_DOUBLE                  (1 << 20)
-#define DISPPLANE_NO_LINE_DOUBLE               0
-#define DISPPLANE_STEREO_POLARITY_FIRST                0
-#define DISPPLANE_STEREO_POLARITY_SECOND       (1 << 18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE           (1 << 15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE          0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA                0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY         (1)
-#define DISPPLANE_BOTTOM                       (4)
-
-#define DSPABASE               0x70184
-#define DSPALINOFF             0x70184
-#define DSPASTRIDE             0x70188
-
-#define DSPBBASE               0x71184
-#define DSPBLINOFF             0X71184
-#define DSPBADDR               DSPBBASE
-#define DSPBSTRIDE             0x71188
-
-#define DSPCBASE               0x72184
-#define DSPCLINOFF             0x72184
-#define DSPCSTRIDE             0x72188
-
-#define DSPAKEYVAL             0x70194
-#define DSPAKEYMASK            0x70198
-
-#define DSPAPOS                        0x7018C /* reserved */
-#define DSPASIZE               0x70190
-#define DSPBPOS                        0x7118C
-#define DSPBSIZE               0x71190
-#define DSPCPOS                        0x7218C
-#define DSPCSIZE               0x72190
-
-#define DSPASURF               0x7019C
-#define DSPATILEOFF            0x701A4
-
-#define DSPBSURF               0x7119C
-#define DSPBTILEOFF            0x711A4
-
-#define DSPCSURF               0x7219C
-#define DSPCTILEOFF            0x721A4
-#define DSPCKEYMAXVAL          0x721A0
-#define DSPCKEYMINVAL          0x72194
-#define DSPCKEYMSK             0x72198
-
-#define VGACNTRL               0x71400
-#define VGA_DISP_DISABLE               (1 << 31)
-#define VGA_2X_MODE                    (1 << 30)
-#define VGA_PIPE_B_SELECT              (1 << 29)
-
-/*
- * Overlay registers
- */
-#define OV_C_OFFSET            0x08000
-#define OV_OVADD               0x30000
-#define OV_DOVASTA             0x30008
-# define OV_PIPE_SELECT                        ((1 << 6)|(1 << 7))
-# define OV_PIPE_SELECT_POS            6
-# define OV_PIPE_A                     0
-# define OV_PIPE_C                     1
-#define OV_OGAMC5              0x30010
-#define OV_OGAMC4              0x30014
-#define OV_OGAMC3              0x30018
-#define OV_OGAMC2              0x3001C
-#define OV_OGAMC1              0x30020
-#define OV_OGAMC0              0x30024
-#define OVC_OVADD              0x38000
-#define OVC_DOVCSTA            0x38008
-#define OVC_OGAMC5             0x38010
-#define OVC_OGAMC4             0x38014
-#define OVC_OGAMC3             0x38018
-#define OVC_OGAMC2             0x3801C
-#define OVC_OGAMC1             0x38020
-#define OVC_OGAMC0             0x38024
-
-/*
- * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
- * of video memory available to the BIOS in SWF1.
- */
-#define SWF0                   0x71410
-#define SWF1                   0x71414
-#define SWF2                   0x71418
-#define SWF3                   0x7141c
-#define SWF4                   0x71420
-#define SWF5                   0x71424
-#define SWF6                   0x71428
-
-/*
- * 855 scratch registers.
- */
-#define SWF00                  0x70410
-#define SWF01                  0x70414
-#define SWF02                  0x70418
-#define SWF03                  0x7041c
-#define SWF04                  0x70420
-#define SWF05                  0x70424
-#define SWF06                  0x70428
-
-#define SWF10                  SWF0
-#define SWF11                  SWF1
-#define SWF12                  SWF2
-#define SWF13                  SWF3
-#define SWF14                  SWF4
-#define SWF15                  SWF5
-#define SWF16                  SWF6
-
-#define SWF30                  0x72414
-#define SWF31                  0x72418
-#define SWF32                  0x7241c
-
-
-/*
- * Palette registers
- */
-#define PALETTE_A              0x0a000
-#define PALETTE_B              0x0a800
-#define PALETTE_C              0x0ac00
-
-/* Cursor A & B regs */
-#define CURACNTR               0x70080
-#define CURSOR_MODE_DISABLE            0x00
-#define CURSOR_MODE_64_32B_AX          0x07
-#define CURSOR_MODE_64_ARGB_AX         ((1 << 5) | CURSOR_MODE_64_32B_AX)
-#define MCURSOR_GAMMA_ENABLE           (1 << 26)
-#define CURABASE               0x70084
-#define CURAPOS                        0x70088
-#define CURSOR_POS_MASK                        0x007FF
-#define CURSOR_POS_SIGN                        0x8000
-#define CURSOR_X_SHIFT                 0
-#define CURSOR_Y_SHIFT                 16
-#define CURBCNTR               0x700c0
-#define CURBBASE               0x700c4
-#define CURBPOS                        0x700c8
-#define CURCCNTR               0x700e0
-#define CURCBASE               0x700e4
-#define CURCPOS                        0x700e8
-
-/*
- * Interrupt Registers
- */
-#define IER                    0x020a0
-#define IIR                    0x020a4
-#define IMR                    0x020a8
-#define ISR                    0x020ac
-
-/*
- * MOORESTOWN delta registers
- */
-#define MRST_DPLL_A            0x0f014
-#define MDFLD_DPLL_B           0x0f018
-#define MDFLD_INPUT_REF_SEL            (1 << 14)
-#define MDFLD_VCO_SEL                  (1 << 16)
-#define DPLLA_MODE_LVDS                        (2 << 26)       /* mrst */
-#define MDFLD_PLL_LATCHEN              (1 << 28)
-#define MDFLD_PWR_GATE_EN              (1 << 30)
-#define MDFLD_P1_MASK                  (0x1FF << 17)
-#define MRST_FPA0              0x0f040
-#define MRST_FPA1              0x0f044
-#define MDFLD_DPLL_DIV0                0x0f048
-#define MDFLD_DPLL_DIV1                0x0f04c
-#define MRST_PERF_MODE         0x020f4
-
-/*
- * MEDFIELD HDMI registers
- */
-#define HDMIPHYMISCCTL         0x61134
-#define HDMI_PHY_POWER_DOWN            0x7f
-#define HDMIB_CONTROL          0x61140
-#define HDMIB_PORT_EN                  (1 << 31)
-#define HDMIB_PIPE_B_SELECT            (1 << 30)
-#define HDMIB_NULL_PACKET              (1 << 9)
-#define HDMIB_HDCP_PORT                        (1 << 5)
-
-/* #define LVDS                        0x61180 */
-#define MRST_PANEL_8TO6_DITHER_ENABLE  (1 << 25)
-#define MRST_PANEL_24_DOT_1_FORMAT     (1 << 24)
-#define LVDS_A3_POWER_UP_0_OUTPUT      (1 << 6)
-
-#define MIPI                   0x61190
-#define MIPI_C                 0x62190
-#define MIPI_PORT_EN                   (1 << 31)
-/* Turns on border drawing to allow centered display. */
-#define SEL_FLOPPED_HSTX               (1 << 23)
-#define PASS_FROM_SPHY_TO_AFE          (1 << 16)
-#define MIPI_BORDER_EN                 (1 << 15)
-#define MIPIA_3LANE_MIPIC_1LANE                0x1
-#define MIPIA_2LANE_MIPIC_2LANE                0x2
-#define TE_TRIGGER_DSI_PROTOCOL                (1 << 2)
-#define TE_TRIGGER_GPIO_PIN            (1 << 3)
-#define MIPI_TE_COUNT          0x61194
-
-/* #define PP_CONTROL  0x61204 */
-#define POWER_DOWN_ON_RESET            (1 << 1)
-
-/* #define PFIT_CONTROL        0x61230 */
-#define PFIT_PIPE_SELECT               (3 << 29)
-#define PFIT_PIPE_SELECT_SHIFT         (29)
-
-/* #define BLC_PWM_CTL         0x61254 */
-#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT   (16)
-#define MRST_BACKLIGHT_MODULATION_FREQ_MASK    (0xffff << 16)
-
-/* #define PIPEACONF 0x70008 */
-#define PIPEACONF_PIPE_STATE           (1 << 30)
-/* #define DSPACNTR            0x70180 */
-
-#define MRST_DSPABASE          0x7019c
-#define MRST_DSPBBASE          0x7119c
-#define MDFLD_DSPCBASE         0x7219c
-
-/*
- * Moorestown registers.
- */
-
-/*
- *     MIPI IP registers
- */
-#define MIPIC_REG_OFFSET               0x800
-
-#define DEVICE_READY_REG               0xb000
-#define LP_OUTPUT_HOLD                         (1 << 16)
-#define EXIT_ULPS_DEV_READY                    0x3
-#define LP_OUTPUT_HOLD_RELEASE                 0x810000
-# define ENTERING_ULPS                         (2 << 1)
-# define EXITING_ULPS                          (1 << 1)
-# define ULPS_MASK                             (3 << 1)
-# define BUS_POSSESSION                                (1 << 3)
-#define INTR_STAT_REG                  0xb004
-#define RX_SOT_ERROR                           (1 << 0)
-#define RX_SOT_SYNC_ERROR                      (1 << 1)
-#define RX_ESCAPE_MODE_ENTRY_ERROR             (1 << 3)
-#define RX_LP_TX_SYNC_ERROR                    (1 << 4)
-#define RX_HS_RECEIVE_TIMEOUT_ERROR            (1 << 5)
-#define RX_FALSE_CONTROL_ERROR                 (1 << 6)
-#define RX_ECC_SINGLE_BIT_ERROR                        (1 << 7)
-#define RX_ECC_MULTI_BIT_ERROR                 (1 << 8)
-#define RX_CHECKSUM_ERROR                      (1 << 9)
-#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED                (1 << 10)
-#define RX_DSI_VC_ID_INVALID                   (1 << 11)
-#define TX_FALSE_CONTROL_ERROR                 (1 << 12)
-#define TX_ECC_SINGLE_BIT_ERROR                        (1 << 13)
-#define TX_ECC_MULTI_BIT_ERROR                 (1 << 14)
-#define TX_CHECKSUM_ERROR                      (1 << 15)
-#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED                (1 << 16)
-#define TX_DSI_VC_ID_INVALID                   (1 << 17)
-#define HIGH_CONTENTION                                (1 << 18)
-#define LOW_CONTENTION                         (1 << 19)
-#define DPI_FIFO_UNDER_RUN                     (1 << 20)
-#define HS_TX_TIMEOUT                          (1 << 21)
-#define LP_RX_TIMEOUT                          (1 << 22)
-#define TURN_AROUND_ACK_TIMEOUT                        (1 << 23)
-#define ACK_WITH_NO_ERROR                      (1 << 24)
-#define HS_GENERIC_WR_FIFO_FULL                        (1 << 27)
-#define LP_GENERIC_WR_FIFO_FULL                        (1 << 28)
-#define SPL_PKT_SENT                           (1 << 30)
-#define INTR_EN_REG                    0xb008
-#define DSI_FUNC_PRG_REG               0xb00c
-#define DPI_CHANNEL_NUMBER_POS                 0x03
-#define DBI_CHANNEL_NUMBER_POS                 0x05
-#define FMT_DPI_POS                            0x07
-#define FMT_DBI_POS                            0x0A
-#define DBI_DATA_WIDTH_POS                     0x0D
-
-/* DPI PIXEL FORMATS */
-#define RGB_565_FMT                            0x01    /* RGB 565 FORMAT */
-#define RGB_666_FMT                            0x02    /* RGB 666 FORMAT */
-#define LRGB_666_FMT                           0x03    /* RGB LOOSELY PACKED
-                                                        * 666 FORMAT
-                                                        */
-#define RGB_888_FMT                            0x04    /* RGB 888 FORMAT */
-#define VIRTUAL_CHANNEL_NUMBER_0               0x00    /* Virtual channel 0 */
-#define VIRTUAL_CHANNEL_NUMBER_1               0x01    /* Virtual channel 1 */
-#define VIRTUAL_CHANNEL_NUMBER_2               0x02    /* Virtual channel 2 */
-#define VIRTUAL_CHANNEL_NUMBER_3               0x03    /* Virtual channel 3 */
-
-#define DBI_NOT_SUPPORTED                      0x00    /* command mode
-                                                        * is not supported
-                                                        */
-#define DBI_DATA_WIDTH_16BIT                   0x01    /* 16 bit data */
-#define DBI_DATA_WIDTH_9BIT                    0x02    /* 9 bit data */
-#define DBI_DATA_WIDTH_8BIT                    0x03    /* 8 bit data */
-#define DBI_DATA_WIDTH_OPT1                    0x04    /* option 1 */
-#define DBI_DATA_WIDTH_OPT2                    0x05    /* option 2 */
-
-#define HS_TX_TIMEOUT_REG              0xb010
-#define LP_RX_TIMEOUT_REG              0xb014
-#define TURN_AROUND_TIMEOUT_REG                0xb018
-#define DEVICE_RESET_REG               0xb01C
-#define DPI_RESOLUTION_REG             0xb020
-#define RES_V_POS                              0x10
-#define DBI_RESOLUTION_REG             0xb024 /* Reserved for MDFLD */
-#define HORIZ_SYNC_PAD_COUNT_REG       0xb028
-#define HORIZ_BACK_PORCH_COUNT_REG     0xb02C
-#define HORIZ_FRONT_PORCH_COUNT_REG    0xb030
-#define HORIZ_ACTIVE_AREA_COUNT_REG    0xb034
-#define VERT_SYNC_PAD_COUNT_REG                0xb038
-#define VERT_BACK_PORCH_COUNT_REG      0xb03c
-#define VERT_FRONT_PORCH_COUNT_REG     0xb040
-#define HIGH_LOW_SWITCH_COUNT_REG      0xb044
-#define DPI_CONTROL_REG                        0xb048
-#define DPI_SHUT_DOWN                          (1 << 0)
-#define DPI_TURN_ON                            (1 << 1)
-#define DPI_COLOR_MODE_ON                      (1 << 2)
-#define DPI_COLOR_MODE_OFF                     (1 << 3)
-#define DPI_BACK_LIGHT_ON                      (1 << 4)
-#define DPI_BACK_LIGHT_OFF                     (1 << 5)
-#define DPI_LP                                 (1 << 6)
-#define DPI_DATA_REG                   0xb04c
-#define DPI_BACK_LIGHT_ON_DATA                 0x07
-#define DPI_BACK_LIGHT_OFF_DATA                        0x17
-#define INIT_COUNT_REG                 0xb050
-#define MAX_RET_PAK_REG                        0xb054
-#define VIDEO_FMT_REG                  0xb058
-#define COMPLETE_LAST_PCKT                     (1 << 2)
-#define EOT_DISABLE_REG                        0xb05c
-#define ENABLE_CLOCK_STOPPING                  (1 << 1)
-#define LP_BYTECLK_REG                 0xb060
-#define LP_GEN_DATA_REG                        0xb064
-#define HS_GEN_DATA_REG                        0xb068
-#define LP_GEN_CTRL_REG                        0xb06C
-#define HS_GEN_CTRL_REG                        0xb070
-#define DCS_CHANNEL_NUMBER_POS         0x6
-#define MCS_COMMANDS_POS               0x8
-#define WORD_COUNTS_POS                        0x8
-#define MCS_PARAMETER_POS                      0x10
-#define GEN_FIFO_STAT_REG              0xb074
-#define HS_DATA_FIFO_FULL                      (1 << 0)
-#define HS_DATA_FIFO_HALF_EMPTY                        (1 << 1)
-#define HS_DATA_FIFO_EMPTY                     (1 << 2)
-#define LP_DATA_FIFO_FULL                      (1 << 8)
-#define LP_DATA_FIFO_HALF_EMPTY                        (1 << 9)
-#define LP_DATA_FIFO_EMPTY                     (1 << 10)
-#define HS_CTRL_FIFO_FULL                      (1 << 16)
-#define HS_CTRL_FIFO_HALF_EMPTY                        (1 << 17)
-#define HS_CTRL_FIFO_EMPTY                     (1 << 18)
-#define LP_CTRL_FIFO_FULL                      (1 << 24)
-#define LP_CTRL_FIFO_HALF_EMPTY                        (1 << 25)
-#define LP_CTRL_FIFO_EMPTY                     (1 << 26)
-#define DBI_FIFO_EMPTY                         (1 << 27)
-#define DPI_FIFO_EMPTY                         (1 << 28)
-#define HS_LS_DBI_ENABLE_REG           0xb078
-#define TXCLKESC_REG                   0xb07c
-#define DPHY_PARAM_REG                 0xb080
-#define DBI_BW_CTRL_REG                        0xb084
-#define CLK_LANE_SWT_REG               0xb088
-
-/*
- * MIPI Adapter registers
- */
-#define MIPI_CONTROL_REG               0xb104
-#define MIPI_2X_CLOCK_BITS                     ((1 << 0) | (1 << 1))
-#define MIPI_DATA_ADDRESS_REG          0xb108
-#define MIPI_DATA_LENGTH_REG           0xb10C
-#define MIPI_COMMAND_ADDRESS_REG       0xb110
-#define MIPI_COMMAND_LENGTH_REG                0xb114
-#define MIPI_READ_DATA_RETURN_REG0     0xb118
-#define MIPI_READ_DATA_RETURN_REG1     0xb11C
-#define MIPI_READ_DATA_RETURN_REG2     0xb120
-#define MIPI_READ_DATA_RETURN_REG3     0xb124
-#define MIPI_READ_DATA_RETURN_REG4     0xb128
-#define MIPI_READ_DATA_RETURN_REG5     0xb12C
-#define MIPI_READ_DATA_RETURN_REG6     0xb130
-#define MIPI_READ_DATA_RETURN_REG7     0xb134
-#define MIPI_READ_DATA_VALID_REG       0xb138
-
-/* DBI COMMANDS */
-#define soft_reset                     0x01
-/*
- *     The display module performs a software reset.
- *     Registers are written with their SW Reset default values.
- */
-#define get_power_mode                 0x0a
-/*
- *     The display module returns the current power mode
- */
-#define get_address_mode               0x0b
-/*
- *     The display module returns the current status.
- */
-#define get_pixel_format               0x0c
-/*
- *     This command gets the pixel format for the RGB image data
- *     used by the interface.
- */
-#define get_display_mode               0x0d
-/*
- *     The display module returns the Display Image Mode status.
- */
-#define get_signal_mode                        0x0e
-/*
- *     The display module returns the Display Signal Mode.
- */
-#define get_diagnostic_result          0x0f
-/*
- *     The display module returns the self-diagnostic results following
- *     a Sleep Out command.
- */
-#define enter_sleep_mode               0x10
-/*
- *     This command causes the display module to enter the Sleep mode.
- *     In this mode, all unnecessary blocks inside the display module are
- *     disabled except interface communication. This is the lowest power
- *     mode the display module supports.
- */
-#define exit_sleep_mode                        0x11
-/*
- *     This command causes the display module to exit Sleep mode.
- *     All blocks inside the display module are enabled.
- */
-#define enter_partial_mode             0x12
-/*
- *     This command causes the display module to enter the Partial Display
- *     Mode. The Partial Display Mode window is described by the
- *     set_partial_area command.
- */
-#define enter_normal_mode              0x13
-/*
- *     This command causes the display module to enter the Normal mode.
- *     Normal Mode is defined as Partial Display mode and Scroll mode are off
- */
-#define exit_invert_mode               0x20
-/*
- *     This command causes the display module to stop inverting the image
- *     data on the display device. The frame memory contents remain unchanged.
- *     No status bits are changed.
- */
-#define enter_invert_mode              0x21
-/*
- *     This command causes the display module to invert the image data only on
- *     the display device. The frame memory contents remain unchanged.
- *     No status bits are changed.
- */
-#define set_gamma_curve                        0x26
-/*
- *     This command selects the desired gamma curve for the display device.
- *     Four fixed gamma curves are defined in section DCS spec.
- */
-#define set_display_off                        0x28
-/* ************************************************************************* *\
-This command causes the display module to stop displaying the image data
-on the display device. The frame memory contents remain unchanged.
-No status bits are changed.
-\* ************************************************************************* */
-#define set_display_on                 0x29
-/* ************************************************************************* *\
-This command causes the display module to start displaying the image data
-on the display device. The frame memory contents remain unchanged.
-No status bits are changed.
-\* ************************************************************************* */
-#define set_column_address             0x2a
-/*
- *     This command defines the column extent of the frame memory accessed by
- *     the hostprocessor with the read_memory_continue and
- *     write_memory_continue commands.
- *     No status bits are changed.
- */
-#define set_page_addr                  0x2b
-/*
- *     This command defines the page extent of the frame memory accessed by
- *     the host processor with the write_memory_continue and
- *     read_memory_continue command.
- *     No status bits are changed.
- */
-#define write_mem_start                        0x2c
-/*
- *     This command transfers image data from the host processor to the
- *     display modules frame memory starting at the pixel location specified
- *     by preceding set_column_address and set_page_address commands.
- */
-#define set_partial_area               0x30
-/*
- *     This command defines the Partial Display mode s display area.
- *     There are two parameters associated with this command, the first
- *     defines the Start Row (SR) and the second the End Row (ER). SR and ER
- *     refer to the Frame Memory Line Pointer.
- */
-#define set_scroll_area                        0x33
-/*
- *     This command defines the display modules Vertical Scrolling Area.
- */
-#define set_tear_off                   0x34
-/*
- *     This command turns off the display modules Tearing Effect output
- *     signal on the TE signal line.
- */
-#define set_tear_on                    0x35
-/*
- *     This command turns on the display modules Tearing Effect output signal
- *     on the TE signal line.
- */
-#define set_address_mode               0x36
-/*
- *     This command sets the data order for transfers from the host processor
- *     to display modules frame memory,bits B[7:5] and B3, and from the
- *     display modules frame memory to the display device, bits B[2:0] and B4.
- */
-#define set_scroll_start               0x37
-/*
- *     This command sets the start of the vertical scrolling area in the frame
- *     memory. The vertical scrolling area is fully defined when this command
- *     is used with the set_scroll_area command The set_scroll_start command
- *     has one parameter, the Vertical Scroll Pointer. The VSP defines the
- *     line in the frame memory that is written to the display device as the
- *     first line of the vertical scroll area.
- */
-#define exit_idle_mode                 0x38
-/*
- *     This command causes the display module to exit Idle mode.
- */
-#define enter_idle_mode                        0x39
-/*
- *     This command causes the display module to enter Idle Mode.
- *     In Idle Mode, color expression is reduced. Colors are shown on the
- *     display device using the MSB of each of the R, G and B color
- *     components in the frame memory
- */
-#define set_pixel_format               0x3a
-/*
- *     This command sets the pixel format for the RGB image data used by the
- *     interface.
- *     Bits D[6:4]  DPI Pixel Format Definition
- *     Bits D[2:0]  DBI Pixel Format Definition
- *     Bits D7 and D3 are not used.
- */
-#define DCS_PIXEL_FORMAT_3bpp          0x1
-#define DCS_PIXEL_FORMAT_8bpp          0x2
-#define DCS_PIXEL_FORMAT_12bpp         0x3
-#define DCS_PIXEL_FORMAT_16bpp         0x5
-#define DCS_PIXEL_FORMAT_18bpp         0x6
-#define DCS_PIXEL_FORMAT_24bpp         0x7
-
-#define write_mem_cont                 0x3c
-
-/*
- *     This command transfers image data from the host processor to the
- *     display module's frame memory continuing from the pixel location
- *     following the previous write_memory_continue or write_memory_start
- *     command.
- */
-#define set_tear_scanline              0x44
-/*
- *     This command turns on the display modules Tearing Effect output signal
- *     on the TE signal line when the display module reaches line N.
- */
-#define get_scanline                   0x45
-/*
- *     The display module returns the current scanline, N, used to update the
- *      display device. The total number of scanlines on a display device is
- *     defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as
- *     the first line of V Sync and is denoted as Line 0.
- *     When in Sleep Mode, the value returned by get_scanline is undefined.
- */
-
-/* MCS or Generic COMMANDS */
-/* MCS/generic data type */
-#define GEN_SHORT_WRITE_0      0x03  /* generic short write, no parameters */
-#define GEN_SHORT_WRITE_1      0x13  /* generic short write, 1 parameters */
-#define GEN_SHORT_WRITE_2      0x23  /* generic short write, 2 parameters */
-#define GEN_READ_0             0x04  /* generic read, no parameters */
-#define GEN_READ_1             0x14  /* generic read, 1 parameters */
-#define GEN_READ_2             0x24  /* generic read, 2 parameters */
-#define GEN_LONG_WRITE         0x29  /* generic long write */
-#define MCS_SHORT_WRITE_0      0x05  /* MCS short write, no parameters */
-#define MCS_SHORT_WRITE_1      0x15  /* MCS short write, 1 parameters */
-#define MCS_READ               0x06  /* MCS read, no parameters */
-#define MCS_LONG_WRITE         0x39  /* MCS long write */
-/* MCS/generic commands */
-/* TPO MCS */
-#define write_display_profile          0x50
-#define write_display_brightness       0x51
-#define write_ctrl_display             0x53
-#define write_ctrl_cabc                        0x55
-  #define UI_IMAGE             0x01
-  #define STILL_IMAGE          0x02
-  #define MOVING_IMAGE         0x03
-#define write_hysteresis               0x57
-#define write_gamma_setting            0x58
-#define write_cabc_min_bright          0x5e
-#define write_kbbc_profile             0x60
-/* TMD MCS */
-#define tmd_write_display_brightness 0x8c
-
-/*
- *     This command is used to control ambient light, panel backlight
- *     brightness and gamma settings.
- */
-#define BRIGHT_CNTL_BLOCK_ON   (1 << 5)
-#define AMBIENT_LIGHT_SENSE_ON (1 << 4)
-#define DISPLAY_DIMMING_ON     (1 << 3)
-#define BACKLIGHT_ON           (1 << 2)
-#define DISPLAY_BRIGHTNESS_AUTO        (1 << 1)
-#define GAMMA_AUTO             (1 << 0)
-
-/* DCS Interface Pixel Formats */
-#define DCS_PIXEL_FORMAT_3BPP  0x1
-#define DCS_PIXEL_FORMAT_8BPP  0x2
-#define DCS_PIXEL_FORMAT_12BPP 0x3
-#define DCS_PIXEL_FORMAT_16BPP 0x5
-#define DCS_PIXEL_FORMAT_18BPP 0x6
-#define DCS_PIXEL_FORMAT_24BPP 0x7
-/* ONE PARAMETER READ DATA */
-#define addr_mode_data         0xfc
-#define diag_res_data          0x00
-#define disp_mode_data         0x23
-#define pxl_fmt_data           0x77
-#define pwr_mode_data          0x74
-#define sig_mode_data          0x00
-/* TWO PARAMETERS READ DATA */
-#define scanline_data1         0xff
-#define scanline_data2         0xff
-#define NON_BURST_MODE_SYNC_PULSE      0x01    /* Non Burst Mode
-                                                * with Sync Pulse
-                                                */
-#define NON_BURST_MODE_SYNC_EVENTS     0x02    /* Non Burst Mode
-                                                * with Sync events
-                                                */
-#define BURST_MODE                     0x03    /* Burst Mode */
-#define DBI_COMMAND_BUFFER_SIZE                0x240   /* 0x32 */    /* 0x120 */
-                                               /* Allocate at least
-                                                * 0x100 Byte with 32
-                                                * byte alignment
-                                                */
-#define DBI_DATA_BUFFER_SIZE           0x120   /* Allocate at least
-                                                * 0x100 Byte with 32
-                                                * byte alignment
-                                                */
-#define DBI_CB_TIME_OUT                        0xFFFF
-
-#define GEN_FB_TIME_OUT                        2000
-
-#define SKU_83                         0x01
-#define SKU_100                                0x02
-#define SKU_100L                       0x04
-#define SKU_BYPASS                     0x08
-
-/* Some handy macros for playing with bitfields. */
-#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low))
-#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK)
-#define GET_FIELD(word, field) (((word)  & field ## _MASK) >> field ## _SHIFT)
-
-#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
-
-/* PCI config space */
-
-#define SB_PCKT         0x02100 /* cedarview */
-# define SB_OPCODE_MASK                         PSB_MASK(31, 16)
-# define SB_OPCODE_SHIFT                        16
-# define SB_OPCODE_READ                         0
-# define SB_OPCODE_WRITE                        1
-# define SB_DEST_MASK                           PSB_MASK(15, 8)
-# define SB_DEST_SHIFT                          8
-# define SB_DEST_DPLL                           0x88
-# define SB_BYTE_ENABLE_MASK                    PSB_MASK(7, 4)
-# define SB_BYTE_ENABLE_SHIFT                   4
-# define SB_BUSY                                (1 << 0)
-
-
-/* 32-bit value read/written from the DPIO reg. */
-#define SB_DATA                0x02104 /* cedarview */
-/* 32-bit address of the DPIO reg to be read/written. */
-#define SB_ADDR                0x02108 /* cedarview */
-#define DPIO_CFG       0x02110 /* cedarview */
-# define DPIO_MODE_SELECT_1                    (1 << 3)
-# define DPIO_MODE_SELECT_0                    (1 << 2)
-# define DPIO_SFR_BYPASS                       (1 << 1)
-/* reset is active low */
-# define DPIO_CMN_RESET_N                      (1 << 0)
-
-/* Cedarview sideband registers */
-#define _SB_M_A                        0x8008
-#define _SB_M_B                        0x8028
-#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B)
-# define SB_M_DIVIDER_MASK                     (0xFF << 24)
-# define SB_M_DIVIDER_SHIFT                    24
-
-#define _SB_N_VCO_A            0x8014
-#define _SB_N_VCO_B            0x8034
-#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B)
-#define SB_N_VCO_SEL_MASK                      PSB_MASK(31, 30)
-#define SB_N_VCO_SEL_SHIFT                     30
-#define SB_N_DIVIDER_MASK                      PSB_MASK(29, 26)
-#define SB_N_DIVIDER_SHIFT                     26
-#define SB_N_CB_TUNE_MASK                      PSB_MASK(25, 24)
-#define SB_N_CB_TUNE_SHIFT                     24
-
-#define _SB_REF_A              0x8018
-#define _SB_REF_B              0x8038
-#define SB_REF_SFR(pipe)       _PIPE(pipe, _SB_REF_A, _SB_REF_B)
-
-#define _SB_P_A                        0x801c
-#define _SB_P_B                        0x803c
-#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B)
-#define SB_P2_DIVIDER_MASK                     PSB_MASK(31, 30)
-#define SB_P2_DIVIDER_SHIFT                    30
-#define SB_P2_10                               0 /* HDMI, DP, DAC */
-#define SB_P2_5                                1 /* DAC */
-#define SB_P2_14                               2 /* LVDS single */
-#define SB_P2_7                                3 /* LVDS double */
-#define SB_P1_DIVIDER_MASK                     PSB_MASK(15, 12)
-#define SB_P1_DIVIDER_SHIFT                    12
-
-#define PSB_LANE0              0x120
-#define PSB_LANE1              0x220
-#define PSB_LANE2              0x2320
-#define PSB_LANE3              0x2420
-
-#define LANE_PLL_MASK          (0x7 << 20)
-#define LANE_PLL_ENABLE                (0x3 << 20)
-
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c
deleted file mode 100644 (file)
index a4bad1a..0000000
+++ /dev/null
@@ -1,1293 +0,0 @@
-/*
- * Copyright (c) 2006-2007 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-/* #include <drm/drm_crtc.h> */
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_sdvo_regs.h"
-
-struct psb_intel_sdvo_priv {
-       struct psb_intel_i2c_chan *i2c_bus;
-       int slaveaddr;
-       int output_device;
-
-       u16 active_outputs;
-
-       struct psb_intel_sdvo_caps caps;
-       int pixel_clock_min, pixel_clock_max;
-
-       int save_sdvo_mult;
-       u16 save_active_outputs;
-       struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
-       struct psb_intel_sdvo_dtd save_output_dtd[16];
-       u32 save_SDVOX;
-       u8 in_out_map[4];
-
-       u8 by_input_wiring;
-       u32 active_device;
-};
-
-/**
- * Writes the SDVOB or SDVOC with the given value, but always writes both
- * SDVOB and SDVOC to work around apparent hardware issues (according to
- * comments in the BIOS).
- */
-void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output,
-                               u32 val)
-{
-       struct drm_device *dev = psb_intel_output->base.dev;
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       u32 bval = val, cval = val;
-       int i;
-
-       if (sdvo_priv->output_device == SDVOB)
-               cval = REG_READ(SDVOC);
-       else
-               bval = REG_READ(SDVOB);
-       /*
-        * Write the registers twice for luck. Sometimes,
-        * writing them only once doesn't appear to 'stick'.
-        * The BIOS does this too. Yay, magic
-        */
-       for (i = 0; i < 2; i++) {
-               REG_WRITE(SDVOB, bval);
-               REG_READ(SDVOB);
-               REG_WRITE(SDVOC, cval);
-               REG_READ(SDVOC);
-       }
-}
-
-static bool psb_intel_sdvo_read_byte(
-                               struct psb_intel_output *psb_intel_output,
-                               u8 addr, u8 *ch)
-{
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       u8 out_buf[2];
-       u8 buf[2];
-       int ret;
-
-       struct i2c_msg msgs[] = {
-               {
-                .addr = sdvo_priv->i2c_bus->slave_addr,
-                .flags = 0,
-                .len = 1,
-                .buf = out_buf,
-                },
-               {
-                .addr = sdvo_priv->i2c_bus->slave_addr,
-                .flags = I2C_M_RD,
-                .len = 1,
-                .buf = buf,
-                }
-       };
-
-       out_buf[0] = addr;
-       out_buf[1] = 0;
-
-       ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2);
-       if (ret == 2) {
-               *ch = buf[0];
-               return true;
-       }
-
-       return false;
-}
-
-static bool psb_intel_sdvo_write_byte(
-                       struct psb_intel_output *psb_intel_output,
-                       int addr, u8 ch)
-{
-       u8 out_buf[2];
-       struct i2c_msg msgs[] = {
-               {
-                .addr = psb_intel_output->i2c_bus->slave_addr,
-                .flags = 0,
-                .len = 2,
-                .buf = out_buf,
-                }
-       };
-
-       out_buf[0] = addr;
-       out_buf[1] = ch;
-
-       if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1)
-               return true;
-       return false;
-}
-
-#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
-/** Mapping of command numbers to names, for debug output */
-static const struct _sdvo_cmd_name {
-       u8 cmd;
-       char *name;
-} sdvo_cmd_names[] = {
-SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
-           SDVO_CMD_NAME_ENTRY
-           (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
-           SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),};
-
-#define SDVO_NAME(dev_priv) \
-                ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
-#define SDVO_PRIV(output)   ((struct psb_intel_sdvo_priv *) (output)->dev_priv)
-
-static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output,
-                                    u8 cmd,
-                                    void *args,
-                                    int args_len)
-{
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       int i;
-
-       if (0) {
-               printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
-               for (i = 0; i < args_len; i++)
-                       printk(KERN_CONT "%02X ", ((u8 *) args)[i]);
-               for (; i < 8; i++)
-                       printk(KERN_CONT "   ");
-               for (i = 0;
-                    i <
-                    sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
-                    i++) {
-                       if (cmd == sdvo_cmd_names[i].cmd) {
-                               printk(KERN_CONT
-                                       "(%s)", sdvo_cmd_names[i].name);
-                               break;
-                       }
-               }
-               if (i ==
-                   sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
-                       printk(KERN_CONT "(%02X)", cmd);
-               printk(KERN_CONT "\n");
-       }
-
-       for (i = 0; i < args_len; i++) {
-               psb_intel_sdvo_write_byte(psb_intel_output,
-                                       SDVO_I2C_ARG_0 - i,
-                                       ((u8 *) args)[i]);
-       }
-
-       psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd);
-}
-
-static const char *const cmd_status_names[] = {
-       "Power on",
-       "Success",
-       "Not supported",
-       "Invalid arg",
-       "Pending",
-       "Target not specified",
-       "Scaling not supported"
-};
-
-static u8 psb_intel_sdvo_read_response(
-                               struct psb_intel_output *psb_intel_output,
-                               void *response, int response_len)
-{
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       int i;
-       u8 status;
-       u8 retry = 50;
-
-       while (retry--) {
-               /* Read the command response */
-               for (i = 0; i < response_len; i++) {
-                       psb_intel_sdvo_read_byte(psb_intel_output,
-                                            SDVO_I2C_RETURN_0 + i,
-                                            &((u8 *) response)[i]);
-               }
-
-               /* read the return status */
-               psb_intel_sdvo_read_byte(psb_intel_output,
-                                        SDVO_I2C_CMD_STATUS,
-                                        &status);
-
-               if (0) {
-                       pr_debug("%s: R: ", SDVO_NAME(sdvo_priv));
-                       for (i = 0; i < response_len; i++)
-                               printk(KERN_CONT "%02X ", ((u8 *) response)[i]);
-                       for (; i < 8; i++)
-                               printk("   ");
-                       if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-                               printk(KERN_CONT "(%s)",
-                                        cmd_status_names[status]);
-                       else
-                               printk(KERN_CONT "(??? %d)", status);
-                       printk(KERN_CONT "\n");
-               }
-
-               if (status != SDVO_CMD_STATUS_PENDING)
-                       return status;
-
-               mdelay(50);
-       }
-
-       return status;
-}
-
-int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
-{
-       if (mode->clock >= 100000)
-               return 1;
-       else if (mode->clock >= 50000)
-               return 2;
-       else
-               return 4;
-}
-
-/**
- * Don't check status code from this as it switches the bus back to the
- * SDVO chips which defeats the purpose of doing a bus switch in the first
- * place.
- */
-void psb_intel_sdvo_set_control_bus_switch(
-                               struct psb_intel_output *psb_intel_output,
-                               u8 target)
-{
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_SET_CONTROL_BUS_SWITCH,
-                                &target,
-                                1);
-}
-
-static bool psb_intel_sdvo_set_target_input(
-                               struct psb_intel_output *psb_intel_output,
-                               bool target_0, bool target_1)
-{
-       struct psb_intel_sdvo_set_target_input_args targets = { 0 };
-       u8 status;
-
-       if (target_0 && target_1)
-               return SDVO_CMD_STATUS_NOTSUPP;
-
-       if (target_1)
-               targets.target_1 = 1;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT,
-                            &targets, sizeof(targets));
-
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-
-       return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-/**
- * Return whether each input is trained.
- *
- * This function is making an assumption about the layout of the response,
- * which should be checked against the docs.
- */
-static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output
-                                         *psb_intel_output, bool *input_1,
-                                         bool *input_2)
-{
-       struct psb_intel_sdvo_get_trained_inputs_response response;
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS,
-                            NULL, 0);
-       status =
-           psb_intel_sdvo_read_response(psb_intel_output, &response,
-                                    sizeof(response));
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       *input_1 = response.input0_trained;
-       *input_2 = response.input1_trained;
-       return true;
-}
-
-static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output
-                                         *psb_intel_output, u16 *outputs)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS,
-                            NULL, 0);
-       status =
-           psb_intel_sdvo_read_response(psb_intel_output, outputs,
-                                    sizeof(*outputs));
-
-       return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output
-                                         *psb_intel_output, u16 outputs)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS,
-                            &outputs, sizeof(outputs));
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-       return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output
-                                              *psb_intel_output, int mode)
-{
-       u8 status, state = SDVO_ENCODER_STATE_ON;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               state = SDVO_ENCODER_STATE_ON;
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-               state = SDVO_ENCODER_STATE_STANDBY;
-               break;
-       case DRM_MODE_DPMS_SUSPEND:
-               state = SDVO_ENCODER_STATE_SUSPEND;
-               break;
-       case DRM_MODE_DPMS_OFF:
-               state = SDVO_ENCODER_STATE_OFF;
-               break;
-       }
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                            SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
-                            sizeof(state));
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-
-       return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output
-                                                  *psb_intel_output,
-                                                  int *clock_min,
-                                                  int *clock_max)
-{
-       struct psb_intel_sdvo_pixel_clock_range clocks;
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                            SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL,
-                            0);
-
-       status =
-           psb_intel_sdvo_read_response(psb_intel_output, &clocks,
-                                    sizeof(clocks));
-
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       /* Convert the values from units of 10 kHz to kHz. */
-       *clock_min = clocks.min * 10;
-       *clock_max = clocks.max * 10;
-
-       return true;
-}
-
-static bool psb_intel_sdvo_set_target_output(
-                               struct psb_intel_output *psb_intel_output,
-                               u16 outputs)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT,
-                            &outputs, sizeof(outputs));
-
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-       return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output,
-                                 u8 cmd, struct psb_intel_sdvo_dtd *dtd)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0);
-       status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1,
-                                         sizeof(dtd->part1));
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0);
-       status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2,
-                                         sizeof(dtd->part2));
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       return true;
-}
-
-static bool psb_intel_sdvo_get_input_timing(
-                               struct psb_intel_output *psb_intel_output,
-                               struct psb_intel_sdvo_dtd *dtd)
-{
-       return psb_intel_sdvo_get_timing(psb_intel_output,
-                                    SDVO_CMD_GET_INPUT_TIMINGS_PART1,
-                                    dtd);
-}
-
-static bool psb_intel_sdvo_set_timing(
-                               struct psb_intel_output *psb_intel_output,
-                               u8 cmd,
-                               struct psb_intel_sdvo_dtd *dtd)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1,
-                            sizeof(dtd->part1));
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2,
-                            sizeof(dtd->part2));
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       return true;
-}
-
-static bool psb_intel_sdvo_set_input_timing(
-                               struct psb_intel_output *psb_intel_output,
-                               struct psb_intel_sdvo_dtd *dtd)
-{
-       return psb_intel_sdvo_set_timing(psb_intel_output,
-                                    SDVO_CMD_SET_INPUT_TIMINGS_PART1,
-                                    dtd);
-}
-
-static bool psb_intel_sdvo_set_output_timing(
-                               struct psb_intel_output *psb_intel_output,
-                               struct psb_intel_sdvo_dtd *dtd)
-{
-       return psb_intel_sdvo_set_timing(psb_intel_output,
-                                    SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
-                                    dtd);
-}
-
-static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output
-                                               *psb_intel_output)
-{
-       u8 response, status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_GET_CLOCK_RATE_MULT,
-                                NULL,
-                                0);
-
-       status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1);
-
-       if (status != SDVO_CMD_STATUS_SUCCESS) {
-               DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n");
-               return SDVO_CLOCK_RATE_MULT_1X;
-       } else {
-               DRM_DEBUG("Current clock rate multiplier: %d\n", response);
-       }
-
-       return response;
-}
-
-static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output
-                                               *psb_intel_output, u8 val)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                               SDVO_CMD_SET_CLOCK_RATE_MULT,
-                               &val,
-                               1);
-
-       status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       return true;
-}
-
-static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output,
-                                         u32 in0outputmask,
-                                         u32 in1outputmask)
-{
-       u8 byArgs[4];
-       u8 status;
-       int i;
-       struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv;
-
-       /* Make all fields of the  args/ret to zero */
-       memset(byArgs, 0, sizeof(byArgs));
-
-       /* Fill up the argument values; */
-       byArgs[0] = (u8) (in0outputmask & 0xFF);
-       byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF);
-       byArgs[2] = (u8) (in1outputmask & 0xFF);
-       byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF);
-
-
-       /*save inoutmap arg here*/
-       for (i = 0; i < 4; i++)
-               sdvo_priv->in_out_map[i] = byArgs[0];
-
-       psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4);
-       status = psb_intel_sdvo_read_response(output, NULL, 0);
-
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-       return true;
-}
-
-
-static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output)
-{
-       u32 dwCurrentSDVOIn0 = 0;
-       u32 dwCurrentSDVOIn1 = 0;
-       u32 dwDevMask = 0;
-
-
-       struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv;
-
-       /* Please DO NOT change the following code. */
-       /* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */
-       /* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */
-       if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) {
-               switch (sdvo_priv->active_device) {
-               case SDVO_DEVICE_LVDS:
-                       dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1;
-                       break;
-               case SDVO_DEVICE_TMDS:
-                       dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1;
-                       break;
-               case SDVO_DEVICE_TV:
-                       dwDevMask =
-                       SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 |
-                       SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 |
-                       SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 |
-                       SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1;
-                       break;
-               case SDVO_DEVICE_CRT:
-                       dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1;
-                       break;
-               }
-               dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask);
-       } else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) {
-               switch (sdvo_priv->active_device) {
-               case SDVO_DEVICE_LVDS:
-                       dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1;
-                       break;
-               case SDVO_DEVICE_TMDS:
-                       dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1;
-                       break;
-               case SDVO_DEVICE_TV:
-                       dwDevMask =
-                       SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 |
-                       SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 |
-                       SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 |
-                       SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1;
-                       break;
-               case SDVO_DEVICE_CRT:
-                       dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1;
-                       break;
-               }
-               dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask);
-       }
-
-       psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0,
-                                         dwCurrentSDVOIn1);
-}
-
-
-static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
-{
-       /* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
-        * device will be told of the multiplier during mode_set.
-        */
-       adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode);
-       return true;
-}
-
-static void psb_intel_sdvo_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_crtc *crtc = encoder->crtc;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       struct psb_intel_output *psb_intel_output =
-                                       enc_to_psb_intel_output(encoder);
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       u16 width, height;
-       u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
-       u16 h_sync_offset, v_sync_offset;
-       u32 sdvox;
-       struct psb_intel_sdvo_dtd output_dtd;
-       int sdvo_pixel_multiply;
-
-       if (!mode)
-               return;
-
-       psb_intel_sdvo_set_target_output(psb_intel_output, 0);
-
-       width = mode->crtc_hdisplay;
-       height = mode->crtc_vdisplay;
-
-       /* do some mode translations */
-       h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
-       h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
-
-       v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
-       v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
-
-       h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
-       v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
-
-       output_dtd.part1.clock = mode->clock / 10;
-       output_dtd.part1.h_active = width & 0xff;
-       output_dtd.part1.h_blank = h_blank_len & 0xff;
-       output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
-           ((h_blank_len >> 8) & 0xf);
-       output_dtd.part1.v_active = height & 0xff;
-       output_dtd.part1.v_blank = v_blank_len & 0xff;
-       output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
-           ((v_blank_len >> 8) & 0xf);
-
-       output_dtd.part2.h_sync_off = h_sync_offset;
-       output_dtd.part2.h_sync_width = h_sync_len & 0xff;
-       output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
-           (v_sync_len & 0xf);
-       output_dtd.part2.sync_off_width_high =
-           ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) |
-           ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4);
-
-       output_dtd.part2.dtd_flags = 0x18;
-       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
-               output_dtd.part2.dtd_flags |= 0x2;
-       if (mode->flags & DRM_MODE_FLAG_PVSYNC)
-               output_dtd.part2.dtd_flags |= 0x4;
-
-       output_dtd.part2.sdvo_flags = 0;
-       output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
-       output_dtd.part2.reserved = 0;
-
-       /* Set the output timing to the screen */
-       psb_intel_sdvo_set_target_output(psb_intel_output,
-                                    sdvo_priv->active_outputs);
-
-       /* Set the input timing to the screen. Assume always input 0. */
-       psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
-
-       psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd);
-
-       /* We would like to use i830_sdvo_create_preferred_input_timing() to
-        * provide the device with a timing it can support, if it supports that
-        * feature.  However, presumably we would need to adjust the CRTC to
-        * output the preferred timing, and we don't support that currently.
-        */
-       psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd);
-
-       switch (psb_intel_sdvo_get_pixel_multiplier(mode)) {
-       case 1:
-               psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
-                                              SDVO_CLOCK_RATE_MULT_1X);
-               break;
-       case 2:
-               psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
-                                              SDVO_CLOCK_RATE_MULT_2X);
-               break;
-       case 4:
-               psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
-                                              SDVO_CLOCK_RATE_MULT_4X);
-               break;
-       }
-
-       /* Set the SDVO control regs. */
-       sdvox = REG_READ(sdvo_priv->output_device);
-       switch (sdvo_priv->output_device) {
-       case SDVOB:
-               sdvox &= SDVOB_PRESERVE_MASK;
-               break;
-       case SDVOC:
-               sdvox &= SDVOC_PRESERVE_MASK;
-               break;
-       }
-       sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
-       if (psb_intel_crtc->pipe == 1)
-               sdvox |= SDVO_PIPE_B_SELECT;
-
-       sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode);
-
-       psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox);
-
-        psb_intel_sdvo_set_iomap(psb_intel_output);
-}
-
-static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct psb_intel_output *psb_intel_output =
-                                       enc_to_psb_intel_output(encoder);
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       u32 temp;
-
-       if (mode != DRM_MODE_DPMS_ON) {
-               psb_intel_sdvo_set_active_outputs(psb_intel_output, 0);
-               if (0)
-                       psb_intel_sdvo_set_encoder_power_state(
-                                                       psb_intel_output,
-                                                       mode);
-
-               if (mode == DRM_MODE_DPMS_OFF) {
-                       temp = REG_READ(sdvo_priv->output_device);
-                       if ((temp & SDVO_ENABLE) != 0) {
-                               psb_intel_sdvo_write_sdvox(psb_intel_output,
-                                                      temp &
-                                                      ~SDVO_ENABLE);
-                       }
-               }
-       } else {
-               bool input1, input2;
-               int i;
-               u8 status;
-
-               temp = REG_READ(sdvo_priv->output_device);
-               if ((temp & SDVO_ENABLE) == 0)
-                       psb_intel_sdvo_write_sdvox(psb_intel_output,
-                                              temp | SDVO_ENABLE);
-               for (i = 0; i < 2; i++)
-                       psb_intel_wait_for_vblank(dev);
-
-               status =
-                   psb_intel_sdvo_get_trained_inputs(psb_intel_output,
-                                                       &input1,
-                                                       &input2);
-
-
-               /* Warn if the device reported failure to sync.
-                * A lot of SDVO devices fail to notify of sync, but it's
-                * a given it the status is a success, we succeeded.
-                */
-               if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
-                       DRM_DEBUG
-                           ("First %s output reported failure to sync\n",
-                            SDVO_NAME(sdvo_priv));
-               }
-
-               if (0)
-                       psb_intel_sdvo_set_encoder_power_state(
-                                                       psb_intel_output,
-                                                       mode);
-               psb_intel_sdvo_set_active_outputs(psb_intel_output,
-                                             sdvo_priv->active_outputs);
-       }
-       return;
-}
-
-static void psb_intel_sdvo_save(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       /*int o;*/
-
-       sdvo_priv->save_sdvo_mult =
-           psb_intel_sdvo_get_clock_rate_mult(psb_intel_output);
-       psb_intel_sdvo_get_active_outputs(psb_intel_output,
-                                     &sdvo_priv->save_active_outputs);
-
-       if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
-               psb_intel_sdvo_set_target_input(psb_intel_output,
-                                               true,
-                                               false);
-               psb_intel_sdvo_get_input_timing(psb_intel_output,
-                                           &sdvo_priv->save_input_dtd_1);
-       }
-
-       if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
-               psb_intel_sdvo_set_target_input(psb_intel_output,
-                                               false,
-                                               true);
-               psb_intel_sdvo_get_input_timing(psb_intel_output,
-                                           &sdvo_priv->save_input_dtd_2);
-       }
-       sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device);
-
-       /*TODO: save the in_out_map state*/
-}
-
-static void psb_intel_sdvo_restore(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-       /*int o;*/
-       int i;
-       bool input1, input2;
-       u8 status;
-
-       psb_intel_sdvo_set_active_outputs(psb_intel_output, 0);
-
-       if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
-               psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
-               psb_intel_sdvo_set_input_timing(psb_intel_output,
-                                           &sdvo_priv->save_input_dtd_1);
-       }
-
-       if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
-               psb_intel_sdvo_set_target_input(psb_intel_output, false, true);
-               psb_intel_sdvo_set_input_timing(psb_intel_output,
-                                           &sdvo_priv->save_input_dtd_2);
-       }
-
-       psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
-                                      sdvo_priv->save_sdvo_mult);
-
-       REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX);
-
-       if (sdvo_priv->save_SDVOX & SDVO_ENABLE) {
-               for (i = 0; i < 2; i++)
-                       psb_intel_wait_for_vblank(dev);
-               status =
-                   psb_intel_sdvo_get_trained_inputs(psb_intel_output,
-                                                       &input1,
-                                                       &input2);
-               if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
-                       DRM_DEBUG
-                           ("First %s output reported failure to sync\n",
-                            SDVO_NAME(sdvo_priv));
-       }
-
-       psb_intel_sdvo_set_active_outputs(psb_intel_output,
-                                     sdvo_priv->save_active_outputs);
-
-       /*TODO: restore in_out_map*/
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_SET_IN_OUT_MAP,
-                                sdvo_priv->in_out_map,
-                                4);
-
-       psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-}
-
-static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
-{
-       struct psb_intel_output *psb_intel_output =
-                               to_psb_intel_output(connector);
-       struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return MODE_NO_DBLESCAN;
-
-       if (sdvo_priv->pixel_clock_min > mode->clock)
-               return MODE_CLOCK_LOW;
-
-       if (sdvo_priv->pixel_clock_max < mode->clock)
-               return MODE_CLOCK_HIGH;
-
-       return MODE_OK;
-}
-
-static bool psb_intel_sdvo_get_capabilities(
-                               struct psb_intel_output *psb_intel_output,
-                               struct psb_intel_sdvo_caps *caps)
-{
-       u8 status;
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_GET_DEVICE_CAPS,
-                                NULL,
-                                0);
-       status = psb_intel_sdvo_read_response(psb_intel_output,
-                                               caps,
-                                               sizeof(*caps));
-       if (status != SDVO_CMD_STATUS_SUCCESS)
-               return false;
-
-       return true;
-}
-
-struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB)
-{
-       struct drm_connector *connector = NULL;
-       struct psb_intel_output *iout = NULL;
-       struct psb_intel_sdvo_priv *sdvo;
-
-       /* find the sdvo connector */
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
-               iout = to_psb_intel_output(connector);
-
-               if (iout->type != INTEL_OUTPUT_SDVO)
-                       continue;
-
-               sdvo = iout->dev_priv;
-
-               if (sdvo->output_device == SDVOB && sdvoB)
-                       return connector;
-
-               if (sdvo->output_device == SDVOC && !sdvoB)
-                       return connector;
-
-       }
-
-       return NULL;
-}
-
-int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector)
-{
-       u8 response[2];
-       u8 status;
-       struct psb_intel_output *psb_intel_output;
-
-       if (!connector)
-               return 0;
-
-       psb_intel_output = to_psb_intel_output(connector);
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_GET_HOT_PLUG_SUPPORT,
-                                NULL,
-                                0);
-       status = psb_intel_sdvo_read_response(psb_intel_output,
-                                               &response,
-                                               2);
-
-       if (response[0] != 0)
-               return 1;
-
-       return 0;
-}
-
-void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
-{
-       u8 response[2];
-       u8 status;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_GET_ACTIVE_HOT_PLUG,
-                                NULL,
-                                0);
-       psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
-
-       if (on) {
-               psb_intel_sdvo_write_cmd(psb_intel_output,
-                                    SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL,
-                                    0);
-               status = psb_intel_sdvo_read_response(psb_intel_output,
-                                                     &response,
-                                                     2);
-
-               psb_intel_sdvo_write_cmd(psb_intel_output,
-                                    SDVO_CMD_SET_ACTIVE_HOT_PLUG,
-                                    &response, 2);
-       } else {
-               response[0] = 0;
-               response[1] = 0;
-               psb_intel_sdvo_write_cmd(psb_intel_output,
-                                    SDVO_CMD_SET_ACTIVE_HOT_PLUG,
-                                    &response, 2);
-       }
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_GET_ACTIVE_HOT_PLUG,
-                                NULL,
-                                0);
-       psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
-}
-
-static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector
-                                                  *connector, bool force)
-{
-       u8 response[2];
-       u8 status;
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       psb_intel_sdvo_write_cmd(psb_intel_output,
-                                SDVO_CMD_GET_ATTACHED_DISPLAYS,
-                                NULL,
-                                0);
-       status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
-
-       DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
-       if ((response[0] != 0) || (response[1] != 0))
-               return connector_status_connected;
-       else
-               return connector_status_disconnected;
-}
-
-static int psb_intel_sdvo_get_modes(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                                       to_psb_intel_output(connector);
-
-       /* set the bus switch and get the modes */
-       psb_intel_sdvo_set_control_bus_switch(psb_intel_output,
-                                         SDVO_CONTROL_BUS_DDC2);
-       psb_intel_ddc_get_modes(psb_intel_output);
-
-       if (list_empty(&connector->probed_modes))
-               return 0;
-       return 1;
-}
-
-static void psb_intel_sdvo_destroy(struct drm_connector *connector)
-{
-       struct psb_intel_output *psb_intel_output =
-                               to_psb_intel_output(connector);
-
-       if (psb_intel_output->i2c_bus)
-               psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-       kfree(psb_intel_output);
-}
-
-static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = {
-       .dpms = psb_intel_sdvo_dpms,
-       .mode_fixup = psb_intel_sdvo_mode_fixup,
-       .prepare = psb_intel_encoder_prepare,
-       .mode_set = psb_intel_sdvo_mode_set,
-       .commit = psb_intel_encoder_commit,
-};
-
-static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .save = psb_intel_sdvo_save,
-       .restore = psb_intel_sdvo_restore,
-       .detect = psb_intel_sdvo_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = psb_intel_sdvo_destroy,
-};
-
-static const struct drm_connector_helper_funcs
-                               psb_intel_sdvo_connector_helper_funcs = {
-       .get_modes = psb_intel_sdvo_get_modes,
-       .mode_valid = psb_intel_sdvo_mode_valid,
-       .best_encoder = psb_intel_best_encoder,
-};
-
-void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = {
-       .destroy = psb_intel_sdvo_enc_destroy,
-};
-
-
-void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
-{
-       struct drm_connector *connector;
-       struct psb_intel_output *psb_intel_output;
-       struct psb_intel_sdvo_priv *sdvo_priv;
-       struct psb_intel_i2c_chan *i2cbus = NULL;
-       int connector_type;
-       u8 ch[0x40];
-       int i;
-       int encoder_type, output_id;
-
-       psb_intel_output =
-           kcalloc(sizeof(struct psb_intel_output) +
-                   sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL);
-       if (!psb_intel_output)
-               return;
-
-       connector = &psb_intel_output->base;
-
-       drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs,
-                          DRM_MODE_CONNECTOR_Unknown);
-       drm_connector_helper_add(connector,
-                                &psb_intel_sdvo_connector_helper_funcs);
-       sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1);
-       psb_intel_output->type = INTEL_OUTPUT_SDVO;
-
-       connector->interlace_allowed = 0;
-       connector->doublescan_allowed = 0;
-
-       /* setup the DDC bus. */
-       if (output_device == SDVOB)
-               i2cbus =
-                   psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
-       else
-               i2cbus =
-                   psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
-
-       if (!i2cbus)
-               goto err_connector;
-
-       sdvo_priv->i2c_bus = i2cbus;
-
-       if (output_device == SDVOB) {
-               output_id = 1;
-               sdvo_priv->by_input_wiring = SDVOB_IN0;
-               sdvo_priv->i2c_bus->slave_addr = 0x38;
-       } else {
-               output_id = 2;
-               sdvo_priv->i2c_bus->slave_addr = 0x39;
-       }
-
-       sdvo_priv->output_device = output_device;
-       psb_intel_output->i2c_bus = i2cbus;
-       psb_intel_output->dev_priv = sdvo_priv;
-
-
-       /* Read the regs to test if we can talk to the device */
-       for (i = 0; i < 0x40; i++) {
-               if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) {
-                       dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n",
-                                 output_device == SDVOB ? 'B' : 'C');
-                       goto err_i2c;
-               }
-       }
-
-       psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps);
-
-       memset(&sdvo_priv->active_outputs, 0,
-              sizeof(sdvo_priv->active_outputs));
-
-       /* TODO, CVBS, SVID, YPRPB & SCART outputs. */
-       if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) {
-               sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
-               sdvo_priv->active_device = SDVO_DEVICE_CRT;
-               connector->display_info.subpixel_order =
-                   SubPixelHorizontalRGB;
-               encoder_type = DRM_MODE_ENCODER_DAC;
-               connector_type = DRM_MODE_CONNECTOR_VGA;
-       } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) {
-               sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
-               sdvo_priv->active_outputs = SDVO_DEVICE_CRT;
-               connector->display_info.subpixel_order =
-                   SubPixelHorizontalRGB;
-               encoder_type = DRM_MODE_ENCODER_DAC;
-               connector_type = DRM_MODE_CONNECTOR_VGA;
-       } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) {
-               sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0;
-               sdvo_priv->active_device = SDVO_DEVICE_TMDS;
-               connector->display_info.subpixel_order =
-                   SubPixelHorizontalRGB;
-               encoder_type = DRM_MODE_ENCODER_TMDS;
-               connector_type = DRM_MODE_CONNECTOR_DVID;
-       } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) {
-               sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1;
-               sdvo_priv->active_device = SDVO_DEVICE_TMDS;
-               connector->display_info.subpixel_order =
-                   SubPixelHorizontalRGB;
-               encoder_type = DRM_MODE_ENCODER_TMDS;
-               connector_type = DRM_MODE_CONNECTOR_DVID;
-       } else {
-               unsigned char bytes[2];
-
-               memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
-               dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
-                    SDVO_NAME(sdvo_priv), bytes[0], bytes[1]);
-               goto err_i2c;
-       }
-
-       drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs,
-                        encoder_type);
-       drm_encoder_helper_add(&psb_intel_output->enc,
-                              &psb_intel_sdvo_helper_funcs);
-       connector->connector_type = connector_type;
-
-       drm_mode_connector_attach_encoder(&psb_intel_output->base,
-                                         &psb_intel_output->enc);
-       drm_sysfs_connector_add(connector);
-
-       /* Set the input timing to the screen. Assume always input 0. */
-       psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
-
-       psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output,
-                                              &sdvo_priv->pixel_clock_min,
-                                              &sdvo_priv->
-                                              pixel_clock_max);
-
-
-       dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, "
-                 "clock range %dMHz - %dMHz, "
-                 "input 1: %c, input 2: %c, "
-                 "output 1: %c, output 2: %c\n",
-                 SDVO_NAME(sdvo_priv),
-                 sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
-                 sdvo_priv->caps.device_rev_id,
-                 sdvo_priv->pixel_clock_min / 1000,
-                 sdvo_priv->pixel_clock_max / 1000,
-                 (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
-                 (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
-                 /* check currently supported outputs */
-                 sdvo_priv->caps.output_flags &
-                 (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
-                 sdvo_priv->caps.output_flags &
-                 (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
-
-       psb_intel_output->ddc_bus = i2cbus;
-
-       return;
-
-err_i2c:
-       psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-err_connector:
-       drm_connector_cleanup(connector);
-       kfree(psb_intel_output);
-
-       return;
-}
diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h
deleted file mode 100644 (file)
index 96862ea..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * SDVO command definitions and structures.
- *
- * Copyright (c) 2008, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *     Eric Anholt <eric@anholt.net>
- */
-
-#define SDVO_OUTPUT_FIRST   (0)
-#define SDVO_OUTPUT_TMDS0   (1 << 0)
-#define SDVO_OUTPUT_RGB0    (1 << 1)
-#define SDVO_OUTPUT_CVBS0   (1 << 2)
-#define SDVO_OUTPUT_SVID0   (1 << 3)
-#define SDVO_OUTPUT_YPRPB0  (1 << 4)
-#define SDVO_OUTPUT_SCART0  (1 << 5)
-#define SDVO_OUTPUT_LVDS0   (1 << 6)
-#define SDVO_OUTPUT_TMDS1   (1 << 8)
-#define SDVO_OUTPUT_RGB1    (1 << 9)
-#define SDVO_OUTPUT_CVBS1   (1 << 10)
-#define SDVO_OUTPUT_SVID1   (1 << 11)
-#define SDVO_OUTPUT_YPRPB1  (1 << 12)
-#define SDVO_OUTPUT_SCART1  (1 << 13)
-#define SDVO_OUTPUT_LVDS1   (1 << 14)
-#define SDVO_OUTPUT_LAST    (14)
-
-struct psb_intel_sdvo_caps {
-       u8 vendor_id;
-       u8 device_id;
-       u8 device_rev_id;
-       u8 sdvo_version_major;
-       u8 sdvo_version_minor;
-       unsigned int sdvo_inputs_mask:2;
-       unsigned int smooth_scaling:1;
-       unsigned int sharp_scaling:1;
-       unsigned int up_scaling:1;
-       unsigned int down_scaling:1;
-       unsigned int stall_support:1;
-       unsigned int pad:1;
-       u16 output_flags;
-} __packed;
-
-/** This matches the EDID DTD structure, more or less */
-struct psb_intel_sdvo_dtd {
-       struct {
-               u16 clock;      /**< pixel clock, in 10kHz units */
-               u8 h_active;    /**< lower 8 bits (pixels) */
-               u8 h_blank;     /**< lower 8 bits (pixels) */
-               u8 h_high;      /**< upper 4 bits each h_active, h_blank */
-               u8 v_active;    /**< lower 8 bits (lines) */
-               u8 v_blank;     /**< lower 8 bits (lines) */
-               u8 v_high;      /**< upper 4 bits each v_active, v_blank */
-       } part1;
-
-       struct {
-               u8 h_sync_off;
-                       /**< lower 8 bits, from hblank start */
-               u8 h_sync_width;/**< lower 8 bits (pixels) */
-       /** lower 4 bits each vsync offset, vsync width */
-               u8 v_sync_off_width;
-       /**
-        * 2 high bits of hsync offset, 2 high bits of hsync width,
-        * bits 4-5 of vsync offset, and 2 high bits of vsync width.
-        */
-               u8 sync_off_width_high;
-               u8 dtd_flags;
-               u8 sdvo_flags;
-       /** bits 6-7 of vsync offset at bits 6-7 */
-               u8 v_sync_off_high;
-               u8 reserved;
-       } part2;
-} __packed;
-
-struct psb_intel_sdvo_pixel_clock_range {
-       u16 min;                /**< pixel clock, in 10kHz units */
-       u16 max;                /**< pixel clock, in 10kHz units */
-} __packed;
-
-struct psb_intel_sdvo_preferred_input_timing_args {
-       u16 clock;
-       u16 width;
-       u16 height;
-} __packed;
-
-/* I2C registers for SDVO */
-#define SDVO_I2C_ARG_0                         0x07
-#define SDVO_I2C_ARG_1                         0x06
-#define SDVO_I2C_ARG_2                         0x05
-#define SDVO_I2C_ARG_3                         0x04
-#define SDVO_I2C_ARG_4                         0x03
-#define SDVO_I2C_ARG_5                         0x02
-#define SDVO_I2C_ARG_6                         0x01
-#define SDVO_I2C_ARG_7                         0x00
-#define SDVO_I2C_OPCODE                                0x08
-#define SDVO_I2C_CMD_STATUS                    0x09
-#define SDVO_I2C_RETURN_0                      0x0a
-#define SDVO_I2C_RETURN_1                      0x0b
-#define SDVO_I2C_RETURN_2                      0x0c
-#define SDVO_I2C_RETURN_3                      0x0d
-#define SDVO_I2C_RETURN_4                      0x0e
-#define SDVO_I2C_RETURN_5                      0x0f
-#define SDVO_I2C_RETURN_6                      0x10
-#define SDVO_I2C_RETURN_7                      0x11
-#define SDVO_I2C_VENDOR_BEGIN                  0x20
-
-/* Status results */
-#define SDVO_CMD_STATUS_POWER_ON               0x0
-#define SDVO_CMD_STATUS_SUCCESS                        0x1
-#define SDVO_CMD_STATUS_NOTSUPP                        0x2
-#define SDVO_CMD_STATUS_INVALID_ARG            0x3
-#define SDVO_CMD_STATUS_PENDING                        0x4
-#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED   0x5
-#define SDVO_CMD_STATUS_SCALING_NOT_SUPP       0x6
-
-/* SDVO commands, argument/result registers */
-
-#define SDVO_CMD_RESET                                 0x01
-
-/** Returns a struct psb_intel_sdvo_caps */
-#define SDVO_CMD_GET_DEVICE_CAPS                       0x02
-
-#define SDVO_CMD_GET_FIRMWARE_REV                      0x86
-# define SDVO_DEVICE_FIRMWARE_MINOR                    SDVO_I2C_RETURN_0
-# define SDVO_DEVICE_FIRMWARE_MAJOR                    SDVO_I2C_RETURN_1
-# define SDVO_DEVICE_FIRMWARE_PATCH                    SDVO_I2C_RETURN_2
-
-/**
- * Reports which inputs are trained (managed to sync).
- *
- * Devices must have trained within 2 vsyncs of a mode change.
- */
-#define SDVO_CMD_GET_TRAINED_INPUTS                    0x03
-struct psb_intel_sdvo_get_trained_inputs_response {
-       unsigned int input0_trained:1;
-       unsigned int input1_trained:1;
-       unsigned int pad:6;
-} __packed;
-
-/** Returns a struct psb_intel_sdvo_output_flags of active outputs. */
-#define SDVO_CMD_GET_ACTIVE_OUTPUTS                    0x04
-
-/**
- * Sets the current set of active outputs.
- *
- * Takes a struct psb_intel_sdvo_output_flags.
- * Must be preceded by a SET_IN_OUT_MAP
- * on multi-output devices.
- */
-#define SDVO_CMD_SET_ACTIVE_OUTPUTS                    0x05
-
-/**
- * Returns the current mapping of SDVO inputs to outputs on the device.
- *
- * Returns two struct psb_intel_sdvo_output_flags structures.
- */
-#define SDVO_CMD_GET_IN_OUT_MAP                                0x06
-
-/**
- * Sets the current mapping of SDVO inputs to outputs on the device.
- *
- * Takes two struct i380_sdvo_output_flags structures.
- */
-#define SDVO_CMD_SET_IN_OUT_MAP                                0x07
-
-/**
- * Returns a struct psb_intel_sdvo_output_flags of attached displays.
- */
-#define SDVO_CMD_GET_ATTACHED_DISPLAYS                 0x0b
-
-/**
- * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging.
- */
-#define SDVO_CMD_GET_HOT_PLUG_SUPPORT                  0x0c
-
-/**
- * Takes a struct psb_intel_sdvo_output_flags.
- */
-#define SDVO_CMD_SET_ACTIVE_HOT_PLUG                   0x0d
-
-/**
- * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug
- * interrupts enabled.
- */
-#define SDVO_CMD_GET_ACTIVE_HOT_PLUG                   0x0e
-
-#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE            0x0f
-struct psb_intel_sdvo_get_interrupt_event_source_response {
-       u16 interrupt_status;
-       unsigned int ambient_light_interrupt:1;
-       unsigned int pad:7;
-} __packed;
-
-/**
- * Selects which input is affected by future input commands.
- *
- * Commands affected include SET_INPUT_TIMINGS_PART[12],
- * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
- * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
- */
-#define SDVO_CMD_SET_TARGET_INPUT                      0x10
-struct psb_intel_sdvo_set_target_input_args {
-       unsigned int target_1:1;
-       unsigned int pad:7;
-} __packed;
-
-/**
- * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by
- * future output commands.
- *
- * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
- * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
- */
-#define SDVO_CMD_SET_TARGET_OUTPUT                     0x11
-
-#define SDVO_CMD_GET_INPUT_TIMINGS_PART1               0x12
-#define SDVO_CMD_GET_INPUT_TIMINGS_PART2               0x13
-#define SDVO_CMD_SET_INPUT_TIMINGS_PART1               0x14
-#define SDVO_CMD_SET_INPUT_TIMINGS_PART2               0x15
-#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1              0x16
-#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2              0x17
-#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1              0x18
-#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2              0x19
-/* Part 1 */
-# define SDVO_DTD_CLOCK_LOW                            SDVO_I2C_ARG_0
-# define SDVO_DTD_CLOCK_HIGH                           SDVO_I2C_ARG_1
-# define SDVO_DTD_H_ACTIVE                             SDVO_I2C_ARG_2
-# define SDVO_DTD_H_BLANK                              SDVO_I2C_ARG_3
-# define SDVO_DTD_H_HIGH                               SDVO_I2C_ARG_4
-# define SDVO_DTD_V_ACTIVE                             SDVO_I2C_ARG_5
-# define SDVO_DTD_V_BLANK                              SDVO_I2C_ARG_6
-# define SDVO_DTD_V_HIGH                               SDVO_I2C_ARG_7
-/* Part 2 */
-# define SDVO_DTD_HSYNC_OFF                            SDVO_I2C_ARG_0
-# define SDVO_DTD_HSYNC_WIDTH                          SDVO_I2C_ARG_1
-# define SDVO_DTD_VSYNC_OFF_WIDTH                      SDVO_I2C_ARG_2
-# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH                  SDVO_I2C_ARG_3
-# define SDVO_DTD_DTD_FLAGS                            SDVO_I2C_ARG_4
-# define SDVO_DTD_DTD_FLAG_INTERLACED                          (1 << 7)
-# define SDVO_DTD_DTD_FLAG_STEREO_MASK                         (3 << 5)
-# define SDVO_DTD_DTD_FLAG_INPUT_MASK                          (3 << 3)
-# define SDVO_DTD_DTD_FLAG_SYNC_MASK                           (3 << 1)
-# define SDVO_DTD_SDVO_FLAS                            SDVO_I2C_ARG_5
-# define SDVO_DTD_SDVO_FLAG_STALL                              (1 << 7)
-# define SDVO_DTD_SDVO_FLAG_CENTERED                           (0 << 6)
-# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT                         (1 << 6)
-# define SDVO_DTD_SDVO_FLAG_SCALING_MASK                       (3 << 4)
-# define SDVO_DTD_SDVO_FLAG_SCALING_NONE                       (0 << 4)
-# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP                      (1 << 4)
-# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH                     (2 << 4)
-# define SDVO_DTD_VSYNC_OFF_HIGH                       SDVO_I2C_ARG_6
-
-/**
- * Generates a DTD based on the given width, height, and flags.
- *
- * This will be supported by any device supporting scaling or interlaced
- * modes.
- */
-#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING         0x1a
-# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW         SDVO_I2C_ARG_0
-# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH                SDVO_I2C_ARG_1
-# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW         SDVO_I2C_ARG_2
-# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH                SDVO_I2C_ARG_3
-# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW                SDVO_I2C_ARG_4
-# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH       SDVO_I2C_ARG_5
-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS             SDVO_I2C_ARG_6
-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED          (1 << 0)
-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED              (1 << 1)
-
-#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1      0x1b
-#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2      0x1c
-
-/** Returns a struct psb_intel_sdvo_pixel_clock_range */
-#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE           0x1d
-/** Returns a struct psb_intel_sdvo_pixel_clock_range */
-#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE          0x1e
-
-/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
-#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS                0x1f
-
-/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
-#define SDVO_CMD_GET_CLOCK_RATE_MULT                   0x20
-/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
-#define SDVO_CMD_SET_CLOCK_RATE_MULT                   0x21
-# define SDVO_CLOCK_RATE_MULT_1X                               (1 << 0)
-# define SDVO_CLOCK_RATE_MULT_2X                               (1 << 1)
-# define SDVO_CLOCK_RATE_MULT_4X                               (1 << 3)
-
-#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS              0x27
-
-#define SDVO_CMD_GET_TV_FORMAT                         0x28
-
-#define SDVO_CMD_SET_TV_FORMAT                         0x29
-
-#define SDVO_CMD_GET_SUPPORTED_POWER_STATES            0x2a
-#define SDVO_CMD_GET_ENCODER_POWER_STATE               0x2b
-#define SDVO_CMD_SET_ENCODER_POWER_STATE               0x2c
-# define SDVO_ENCODER_STATE_ON                                 (1 << 0)
-# define SDVO_ENCODER_STATE_STANDBY                            (1 << 1)
-# define SDVO_ENCODER_STATE_SUSPEND                            (1 << 2)
-# define SDVO_ENCODER_STATE_OFF                                        (1 << 3)
-
-#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT             0x93
-
-#define SDVO_CMD_SET_CONTROL_BUS_SWITCH                        0x7a
-# define SDVO_CONTROL_BUS_PROM                         0x0
-# define SDVO_CONTROL_BUS_DDC1                         0x1
-# define SDVO_CONTROL_BUS_DDC2                         0x2
-# define SDVO_CONTROL_BUS_DDC3                         0x3
-
-/* SDVO Bus & SDVO Inputs wiring details*/
-/* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/
-/* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/
-/* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/
-/* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/
-#define SDVOB_IN0 0x01
-#define SDVOB_IN1 0x02
-#define SDVOC_IN0 0x04
-#define SDVOC_IN1 0x08
-
-#define SDVO_DEVICE_NONE 0x00
-#define        SDVO_DEVICE_CRT 0x01
-#define        SDVO_DEVICE_TV 0x02
-#define        SDVO_DEVICE_LVDS 0x04
-#define        SDVO_DEVICE_TMDS 0x08
-
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
deleted file mode 100644 (file)
index 36dd630..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-/*
- */
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include "mdfld_output.h"
-
-/*
- * inline functions
- */
-
-static inline u32
-psb_pipestat(int pipe)
-{
-       if (pipe == 0)
-               return PIPEASTAT;
-       if (pipe == 1)
-               return PIPEBSTAT;
-       if (pipe == 2)
-               return PIPECSTAT;
-       BUG();
-}
-
-static inline u32
-mid_pipe_event(int pipe)
-{
-       if (pipe == 0)
-               return _PSB_PIPEA_EVENT_FLAG;
-       if (pipe == 1)
-               return _MDFLD_PIPEB_EVENT_FLAG;
-       if (pipe == 2)
-               return _MDFLD_PIPEC_EVENT_FLAG;
-       BUG();
-}
-
-static inline u32
-mid_pipe_vsync(int pipe)
-{
-       if (pipe == 0)
-               return _PSB_VSYNC_PIPEA_FLAG;
-       if (pipe == 1)
-               return _PSB_VSYNC_PIPEB_FLAG;
-       if (pipe == 2)
-               return _MDFLD_PIPEC_VBLANK_FLAG;
-       BUG();
-}
-
-static inline u32
-mid_pipeconf(int pipe)
-{
-       if (pipe == 0)
-               return PIPEACONF;
-       if (pipe == 1)
-               return PIPEBCONF;
-       if (pipe == 2)
-               return PIPECCONF;
-       BUG();
-}
-
-void
-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
-{
-       if ((dev_priv->pipestat[pipe] & mask) != mask) {
-               u32 reg = psb_pipestat(pipe);
-               dev_priv->pipestat[pipe] |= mask;
-               /* Enable the interrupt, clear any pending status */
-               if (gma_power_begin(dev_priv->dev, false)) {
-                       u32 writeVal = PSB_RVDC32(reg);
-                       writeVal |= (mask | (mask >> 16));
-                       PSB_WVDC32(writeVal, reg);
-                       (void) PSB_RVDC32(reg);
-                       gma_power_end(dev_priv->dev);
-               }
-       }
-}
-
-void
-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
-{
-       if ((dev_priv->pipestat[pipe] & mask) != 0) {
-               u32 reg = psb_pipestat(pipe);
-               dev_priv->pipestat[pipe] &= ~mask;
-               if (gma_power_begin(dev_priv->dev, false)) {
-                       u32 writeVal = PSB_RVDC32(reg);
-                       writeVal &= ~mask;
-                       PSB_WVDC32(writeVal, reg);
-                       (void) PSB_RVDC32(reg);
-                       gma_power_end(dev_priv->dev);
-               }
-       }
-}
-
-void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
-{
-       if (gma_power_begin(dev_priv->dev, false)) {
-               u32 pipe_event = mid_pipe_event(pipe);
-               dev_priv->vdc_irq_mask |= pipe_event;
-               PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
-               PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-               gma_power_end(dev_priv->dev);
-       }
-}
-
-void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
-{
-       if (dev_priv->pipestat[pipe] == 0) {
-               if (gma_power_begin(dev_priv->dev, false)) {
-                       u32 pipe_event = mid_pipe_event(pipe);
-                       dev_priv->vdc_irq_mask &= ~pipe_event;
-                       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
-                       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-                       gma_power_end(dev_priv->dev);
-               }
-       }
-}
-
-/**
- * Display controller interrupt handler for pipe event.
- *
- */
-static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-
-       uint32_t pipe_stat_val = 0;
-       uint32_t pipe_stat_reg = psb_pipestat(pipe);
-       uint32_t pipe_enable = dev_priv->pipestat[pipe];
-       uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
-       uint32_t pipe_clear;
-       uint32_t i = 0;
-
-       spin_lock(&dev_priv->irqmask_lock);
-
-       pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
-       pipe_stat_val &= pipe_enable | pipe_status;
-       pipe_stat_val &= pipe_stat_val >> 16;
-
-       spin_unlock(&dev_priv->irqmask_lock);
-
-       /* Clear the 2nd level interrupt status bits
-        * Sometimes the bits are very sticky so we repeat until they unstick */
-       for (i = 0; i < 0xffff; i++) {
-               PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
-               pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status;
-
-               if (pipe_clear == 0)
-                       break;
-       }
-
-       if (pipe_clear)
-               dev_err(dev->dev,
-               "%s, can't clear status bits for pipe %d, its value = 0x%x.\n",
-               __func__, pipe, PSB_RVDC32(pipe_stat_reg));
-
-       if (pipe_stat_val & PIPE_VBLANK_STATUS)
-               drm_handle_vblank(dev, pipe);
-
-       if (pipe_stat_val & PIPE_TE_STATUS)
-               drm_handle_vblank(dev, pipe);
-}
-
-/*
- * Display controller interrupt handler.
- */
-static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
-{
-       if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
-               mid_pipe_event_handler(dev, 0);
-
-       if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)
-               mid_pipe_event_handler(dev, 1);
-}
-
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-
-       uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
-       int handled = 0;
-
-       spin_lock(&dev_priv->irqmask_lock);
-
-       vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
-
-       if (vdc_stat & _PSB_PIPE_EVENT_FLAG)
-               dsp_int = 1;
-
-       /* FIXME: Handle Medfield
-       if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
-               dsp_int = 1;
-       */
-
-       if (vdc_stat & _PSB_IRQ_SGX_FLAG)
-               sgx_int = 1;
-
-       vdc_stat &= dev_priv->vdc_irq_mask;
-       spin_unlock(&dev_priv->irqmask_lock);
-
-       if (dsp_int && gma_power_is_on(dev)) {
-               psb_vdc_interrupt(dev, vdc_stat);
-               handled = 1;
-       }
-
-       if (sgx_int) {
-               /* Not expected - we have it masked, shut it up */
-               u32 s, s2;
-               s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
-               s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
-               PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
-               PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
-               /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
-                  we may as well poll even if we add that ! */
-               handled = 1;
-       }
-
-       PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
-       (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
-       DRM_READMEMORYBARRIER();
-
-       if (!handled)
-               return IRQ_NONE;
-
-       return IRQ_HANDLED;
-}
-
-void psb_irq_preinstall(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       if (gma_power_is_on(dev))
-               PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
-       if (dev->vblank_enabled[0])
-               dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
-       if (dev->vblank_enabled[1])
-               dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
-
-       /* FIXME: Handle Medfield irq mask
-       if (dev->vblank_enabled[1])
-               dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
-       if (dev->vblank_enabled[2])
-               dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
-       */
-
-       /* This register is safe even if display island is off */
-       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-int psb_irq_postinstall(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       /* This register is safe even if display island is off */
-       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-       PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
-
-       if (dev->vblank_enabled[0])
-               psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-       else
-               psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank_enabled[1])
-               psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-       else
-               psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank_enabled[2])
-               psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-       else
-               psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-       return 0;
-}
-
-void psb_irq_uninstall(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
-
-       if (dev->vblank_enabled[0])
-               psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank_enabled[1])
-               psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       if (dev->vblank_enabled[2])
-               psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
-                                 _PSB_IRQ_MSVDX_FLAG |
-                                 _LNC_IRQ_TOPAZ_FLAG;
-
-       /* These two registers are safe even if display island is off */
-       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
-       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-
-       wmb();
-
-       /* This register is safe even if display island is off */
-       PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-void psb_irq_turn_on_dpst(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-               (struct drm_psb_private *) dev->dev_private;
-       u32 hist_reg;
-       u32 pwm_reg;
-
-       if (gma_power_begin(dev, false)) {
-               PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL);
-               hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
-               PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL);
-               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-
-               PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
-               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-               PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE
-                                               | PWM_PHASEIN_INT_ENABLE,
-                                                          PWM_CONTROL_LOGIC);
-               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
-               psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
-
-               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-               PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR,
-                                                       HISTOGRAM_INT_CONTROL);
-               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-               PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
-                                                       PWM_CONTROL_LOGIC);
-
-               gma_power_end(dev);
-       }
-}
-
-int psb_irq_enable_dpst(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-               (struct drm_psb_private *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       /* enable DPST */
-       mid_enable_pipe_event(dev_priv, 0);
-       psb_irq_turn_on_dpst(dev);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-       return 0;
-}
-
-void psb_irq_turn_off_dpst(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-       u32 hist_reg;
-       u32 pwm_reg;
-
-       if (gma_power_begin(dev, false)) {
-               PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
-               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-
-               psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
-
-               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-               PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE),
-                                                       PWM_CONTROL_LOGIC);
-               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
-               gma_power_end(dev);
-       }
-}
-
-int psb_irq_disable_dpst(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       mid_disable_pipe_event(dev_priv, 0);
-       psb_irq_turn_off_dpst(dev);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-
-       return 0;
-}
-
-#ifdef PSB_FIXME
-static int psb_vblank_do_wait(struct drm_device *dev,
-                             unsigned int *sequence, atomic_t *counter)
-{
-       unsigned int cur_vblank;
-       int ret = 0;
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                     - *sequence) <= (1 << 23)));
-       *sequence = cur_vblank;
-
-       return ret;
-}
-#endif
-
-/*
- * It is used to enable VBLANK interrupt
- */
-int psb_enable_vblank(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long irqflags;
-       uint32_t reg_val = 0;
-       uint32_t pipeconf_reg = mid_pipeconf(pipe);
-
-#if defined(CONFIG_DRM_PSB_MFLD)
-       /* Medfield is different - we should perhaps extract out vblank
-          and blacklight etc ops */
-       if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
-               return mdfld_enable_te(dev, pipe);
-#endif
-       if (gma_power_begin(dev, false)) {
-               reg_val = REG_READ(pipeconf_reg);
-               gma_power_end(dev);
-       }
-
-       if (!(reg_val & PIPEACONF_ENABLE))
-               return -EINVAL;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       if (pipe == 0)
-               dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
-       else if (pipe == 1)
-               dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
-
-       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
-       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-       psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-
-       return 0;
-}
-
-/*
- * It is used to disable VBLANK interrupt
- */
-void psb_disable_vblank(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long irqflags;
-
-#if defined(CONFIG_DRM_PSB_MFLD)
-       if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
-               mdfld_disable_te(dev, pipe);
-#endif
-       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
-       if (pipe == 0)
-               dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG;
-       else if (pipe == 1)
-               dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG;
-
-       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
-       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-       psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-/**
- *     mdfld_enable_te         -       enable TE events
- *     @dev: our DRM device
- *     @pipe: which pipe to work on
- *
- *     Enable TE events on a Medfield display pipe. Medfield specific.
- */
-int mdfld_enable_te(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long flags;
-       uint32_t reg_val = 0;
-       uint32_t pipeconf_reg = mid_pipeconf(pipe);
-
-       if (gma_power_begin(dev, false)) {
-               reg_val = REG_READ(pipeconf_reg);
-               gma_power_end(dev);
-       }
-
-       if (!(reg_val & PIPEACONF_ENABLE))
-               return -EINVAL;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
-
-       mid_enable_pipe_event(dev_priv, pipe);
-       psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
-
-       return 0;
-}
-
-/**
- *     mdfld_disable_te                -       disable TE events
- *     @dev: our DRM device
- *     @pipe: which pipe to work on
- *
- *     Disable TE events on a Medfield display pipe. Medfield specific.
- */
-void mdfld_disable_te(struct drm_device *dev, int pipe)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
-
-       mid_disable_pipe_event(dev_priv, pipe);
-       psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
-
-       spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
-}
-
-/* Called from drm generic code, passed a 'crtc', which
- * we use as a pipe index
- */
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
-{
-       uint32_t high_frame = PIPEAFRAMEHIGH;
-       uint32_t low_frame = PIPEAFRAMEPIXEL;
-       uint32_t pipeconf_reg = PIPEACONF;
-       uint32_t reg_val = 0;
-       uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               high_frame = PIPEBFRAMEHIGH;
-               low_frame = PIPEBFRAMEPIXEL;
-               pipeconf_reg = PIPEBCONF;
-               break;
-       case 2:
-               high_frame = PIPECFRAMEHIGH;
-               low_frame = PIPECFRAMEPIXEL;
-               pipeconf_reg = PIPECCONF;
-               break;
-       default:
-               dev_err(dev->dev, "%s, invalid pipe.\n", __func__);
-               return 0;
-       }
-
-       if (!gma_power_begin(dev, false))
-               return 0;
-
-       reg_val = REG_READ(pipeconf_reg);
-
-       if (!(reg_val & PIPEACONF_ENABLE)) {
-               dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
-                                                               pipe);
-               goto psb_get_vblank_counter_exit;
-       }
-
-       /*
-        * High & low register fields aren't synchronized, so make sure
-        * we get a low value that's stable across two reads of the high
-        * register.
-        */
-       do {
-               high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
-                        PIPE_FRAME_HIGH_SHIFT);
-               low =  ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
-                       PIPE_FRAME_LOW_SHIFT);
-               high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
-                        PIPE_FRAME_HIGH_SHIFT);
-       } while (high1 != high2);
-
-       count = (high1 << 8) | low;
-
-psb_get_vblank_counter_exit:
-
-       gma_power_end(dev);
-
-       return count;
-}
-
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h
deleted file mode 100644 (file)
index 216fda3..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- *
- **************************************************************************/
-
-#ifndef _SYSIRQ_H_
-#define _SYSIRQ_H_
-
-#include <drm/drmP.h>
-
-bool sysirq_init(struct drm_device *dev);
-void sysirq_uninit(struct drm_device *dev);
-
-void psb_irq_preinstall(struct drm_device *dev);
-int  psb_irq_postinstall(struct drm_device *dev);
-void psb_irq_uninstall(struct drm_device *dev);
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
-
-int psb_irq_enable_dpst(struct drm_device *dev);
-int psb_irq_disable_dpst(struct drm_device *dev);
-void psb_irq_turn_on_dpst(struct drm_device *dev);
-void psb_irq_turn_off_dpst(struct drm_device *dev);
-int  psb_enable_vblank(struct drm_device *dev, int pipe);
-void psb_disable_vblank(struct drm_device *dev, int pipe);
-u32  psb_get_vblank_counter(struct drm_device *dev, int pipe);
-
-#endif /* _SYSIRQ_H_ */
diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c
deleted file mode 100644 (file)
index b867aab..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- **************************************************************************/
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <linux/spinlock.h>
-
-static void psb_lid_timer_func(unsigned long data)
-{
-       struct drm_psb_private * dev_priv = (struct drm_psb_private *)data;
-       struct drm_device *dev = (struct drm_device *)dev_priv->dev;
-       struct timer_list *lid_timer = &dev_priv->lid_timer;
-       unsigned long irq_flags;
-       u32 *lid_state = dev_priv->lid_state;
-       u32 pp_status;
-
-       if (readl(lid_state) == dev_priv->lid_last_state)
-               goto lid_timer_schedule;
-
-       if ((readl(lid_state)) & 0x01) {
-               /*lid state is open*/
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-
-               /*FIXME: should be backlight level before*/
-               psb_intel_lvds_set_brightness(dev, 100);
-       } else {
-               psb_intel_lvds_set_brightness(dev, 0);
-
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-       }
-       dev_priv->lid_last_state =  readl(lid_state);
-
-lid_timer_schedule:
-       spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-       if (!timer_pending(lid_timer)) {
-               lid_timer->expires = jiffies + PSB_LID_DELAY;
-               add_timer(lid_timer);
-       }
-       spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_init(struct drm_psb_private *dev_priv)
-{
-       struct timer_list *lid_timer = &dev_priv->lid_timer;
-       unsigned long irq_flags;
-
-       spin_lock_init(&dev_priv->lid_lock);
-       spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-
-       init_timer(lid_timer);
-
-       lid_timer->data = (unsigned long)dev_priv;
-       lid_timer->function = psb_lid_timer_func;
-       lid_timer->expires = jiffies + PSB_LID_DELAY;
-
-       add_timer(lid_timer);
-       spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
-{
-       del_timer_sync(&dev_priv->lid_timer);
-}
-
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
deleted file mode 100644 (file)
index b81c7c1..0000000
+++ /dev/null
@@ -1,582 +0,0 @@
-/**************************************************************************
- *
- * Copyright (c) (2005-2007) Imagination Technologies Limited.
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA..
- *
- **************************************************************************/
-
-#ifndef _PSB_REG_H_
-#define _PSB_REG_H_
-
-#define PSB_CR_CLKGATECTL              0x0000
-#define _PSB_C_CLKGATECTL_AUTO_MAN_REG         (1 << 24)
-#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT       (20)
-#define _PSB_C_CLKGATECTL_USE_CLKG_MASK                (0x3 << 20)
-#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT       (16)
-#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK                (0x3 << 16)
-#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT                (12)
-#define _PSB_C_CLKGATECTL_TA_CLKG_MASK         (0x3 << 12)
-#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT       (8)
-#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK                (0x3 << 8)
-#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT       (4)
-#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK                (0x3 << 4)
-#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT                (0)
-#define _PSB_C_CLKGATECTL_2D_CLKG_MASK         (0x3 << 0)
-#define _PSB_C_CLKGATECTL_CLKG_ENABLED         (0)
-#define _PSB_C_CLKGATECTL_CLKG_DISABLED                (1)
-#define _PSB_C_CLKGATECTL_CLKG_AUTO            (2)
-
-#define PSB_CR_CORE_ID                 0x0010
-#define _PSB_CC_ID_ID_SHIFT                    (16)
-#define _PSB_CC_ID_ID_MASK                     (0xFFFF << 16)
-#define _PSB_CC_ID_CONFIG_SHIFT                        (0)
-#define _PSB_CC_ID_CONFIG_MASK                 (0xFFFF << 0)
-
-#define PSB_CR_CORE_REVISION           0x0014
-#define _PSB_CC_REVISION_DESIGNER_SHIFT                (24)
-#define _PSB_CC_REVISION_DESIGNER_MASK         (0xFF << 24)
-#define _PSB_CC_REVISION_MAJOR_SHIFT           (16)
-#define _PSB_CC_REVISION_MAJOR_MASK            (0xFF << 16)
-#define _PSB_CC_REVISION_MINOR_SHIFT           (8)
-#define _PSB_CC_REVISION_MINOR_MASK            (0xFF << 8)
-#define _PSB_CC_REVISION_MAINTENANCE_SHIFT     (0)
-#define _PSB_CC_REVISION_MAINTENANCE_MASK      (0xFF << 0)
-
-#define PSB_CR_DESIGNER_REV_FIELD1     0x0018
-
-#define PSB_CR_SOFT_RESET              0x0080
-#define _PSB_CS_RESET_TSP_RESET                (1 << 6)
-#define _PSB_CS_RESET_ISP_RESET                (1 << 5)
-#define _PSB_CS_RESET_USE_RESET                (1 << 4)
-#define _PSB_CS_RESET_TA_RESET         (1 << 3)
-#define _PSB_CS_RESET_DPM_RESET                (1 << 2)
-#define _PSB_CS_RESET_TWOD_RESET       (1 << 1)
-#define _PSB_CS_RESET_BIF_RESET                        (1 << 0)
-
-#define PSB_CR_DESIGNER_REV_FIELD2     0x001C
-
-#define PSB_CR_EVENT_HOST_ENABLE2      0x0110
-
-#define PSB_CR_EVENT_STATUS2           0x0118
-
-#define PSB_CR_EVENT_HOST_CLEAR2       0x0114
-#define _PSB_CE2_BIF_REQUESTER_FAULT           (1 << 4)
-
-#define PSB_CR_EVENT_STATUS            0x012C
-
-#define PSB_CR_EVENT_HOST_ENABLE       0x0130
-
-#define PSB_CR_EVENT_HOST_CLEAR                0x0134
-#define _PSB_CE_MASTER_INTERRUPT               (1 << 31)
-#define _PSB_CE_TA_DPM_FAULT                   (1 << 28)
-#define _PSB_CE_TWOD_COMPLETE                  (1 << 27)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS          (1 << 25)
-#define _PSB_CE_DPM_TA_MEM_FREE                        (1 << 24)
-#define _PSB_CE_PIXELBE_END_RENDER             (1 << 18)
-#define _PSB_CE_SW_EVENT                       (1 << 14)
-#define _PSB_CE_TA_FINISHED                    (1 << 13)
-#define _PSB_CE_TA_TERMINATE                   (1 << 12)
-#define _PSB_CE_DPM_REACHED_MEM_THRESH         (1 << 3)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL          (1 << 2)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_MT           (1 << 1)
-#define _PSB_CE_DPM_3D_MEM_FREE                        (1 << 0)
-
-
-#define PSB_USE_OFFSET_MASK            0x0007FFFF
-#define PSB_USE_OFFSET_SIZE            (PSB_USE_OFFSET_MASK + 1)
-#define PSB_CR_USE_CODE_BASE0          0x0A0C
-#define PSB_CR_USE_CODE_BASE1          0x0A10
-#define PSB_CR_USE_CODE_BASE2          0x0A14
-#define PSB_CR_USE_CODE_BASE3          0x0A18
-#define PSB_CR_USE_CODE_BASE4          0x0A1C
-#define PSB_CR_USE_CODE_BASE5          0x0A20
-#define PSB_CR_USE_CODE_BASE6          0x0A24
-#define PSB_CR_USE_CODE_BASE7          0x0A28
-#define PSB_CR_USE_CODE_BASE8          0x0A2C
-#define PSB_CR_USE_CODE_BASE9          0x0A30
-#define PSB_CR_USE_CODE_BASE10         0x0A34
-#define PSB_CR_USE_CODE_BASE11         0x0A38
-#define PSB_CR_USE_CODE_BASE12         0x0A3C
-#define PSB_CR_USE_CODE_BASE13         0x0A40
-#define PSB_CR_USE_CODE_BASE14         0x0A44
-#define PSB_CR_USE_CODE_BASE15         0x0A48
-#define PSB_CR_USE_CODE_BASE(_i)       (0x0A0C + ((_i) << 2))
-#define _PSB_CUC_BASE_DM_SHIFT                 (25)
-#define _PSB_CUC_BASE_DM_MASK                  (0x3 << 25)
-#define _PSB_CUC_BASE_ADDR_SHIFT               (0)     /* 1024-bit aligned address? */
-#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT          (7)
-#define _PSB_CUC_BASE_ADDR_MASK                        (0x1FFFFFF << 0)
-#define _PSB_CUC_DM_VERTEX                     (0)
-#define _PSB_CUC_DM_PIXEL                      (1)
-#define _PSB_CUC_DM_RESERVED                   (2)
-#define _PSB_CUC_DM_EDM                                (3)
-
-#define PSB_CR_PDS_EXEC_BASE           0x0AB8
-#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT       (20)    /* 1MB aligned address */
-#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT  (20)
-
-#define PSB_CR_EVENT_KICKER            0x0AC4
-#define _PSB_CE_KICKER_ADDRESS_SHIFT           (4)     /* 128-bit aligned address */
-
-#define PSB_CR_EVENT_KICK              0x0AC8
-#define _PSB_CE_KICK_NOW                       (1 << 0)
-
-#define PSB_CR_BIF_DIR_LIST_BASE1      0x0C38
-
-#define PSB_CR_BIF_CTRL                        0x0C00
-#define _PSB_CB_CTRL_CLEAR_FAULT               (1 << 4)
-#define _PSB_CB_CTRL_INVALDC                   (1 << 3)
-#define _PSB_CB_CTRL_FLUSH                     (1 << 2)
-
-#define PSB_CR_BIF_INT_STAT            0x0C04
-
-#define PSB_CR_BIF_FAULT               0x0C08
-#define _PSB_CBI_STAT_PF_N_RW                  (1 << 14)
-#define _PSB_CBI_STAT_FAULT_SHIFT              (0)
-#define _PSB_CBI_STAT_FAULT_MASK               (0x3FFF << 0)
-#define _PSB_CBI_STAT_FAULT_CACHE              (1 << 1)
-#define _PSB_CBI_STAT_FAULT_TA                 (1 << 2)
-#define _PSB_CBI_STAT_FAULT_VDM                        (1 << 3)
-#define _PSB_CBI_STAT_FAULT_2D                 (1 << 4)
-#define _PSB_CBI_STAT_FAULT_PBE                        (1 << 5)
-#define _PSB_CBI_STAT_FAULT_TSP                        (1 << 6)
-#define _PSB_CBI_STAT_FAULT_ISP                        (1 << 7)
-#define _PSB_CBI_STAT_FAULT_USSEPDS            (1 << 8)
-#define _PSB_CBI_STAT_FAULT_HOST               (1 << 9)
-
-#define PSB_CR_BIF_BANK0               0x0C78
-#define PSB_CR_BIF_BANK1               0x0C7C
-#define PSB_CR_BIF_DIR_LIST_BASE0      0x0C84
-#define PSB_CR_BIF_TWOD_REQ_BASE       0x0C88
-#define PSB_CR_BIF_3D_REQ_BASE         0x0CAC
-
-#define PSB_CR_2D_SOCIF                        0x0E18
-#define _PSB_C2_SOCIF_FREESPACE_SHIFT          (0)
-#define _PSB_C2_SOCIF_FREESPACE_MASK           (0xFF << 0)
-#define _PSB_C2_SOCIF_EMPTY                    (0x80 << 0)
-
-#define PSB_CR_2D_BLIT_STATUS          0x0E04
-#define _PSB_C2B_STATUS_BUSY                   (1 << 24)
-#define _PSB_C2B_STATUS_COMPLETE_SHIFT         (0)
-#define _PSB_C2B_STATUS_COMPLETE_MASK          (0xFFFFFF << 0)
-
-/*
- * 2D defs.
- */
-
-/*
- * 2D Slave Port Data : Block Header's Object Type
- */
-
-#define        PSB_2D_CLIP_BH                  (0x00000000)
-#define        PSB_2D_PAT_BH                   (0x10000000)
-#define        PSB_2D_CTRL_BH                  (0x20000000)
-#define        PSB_2D_SRC_OFF_BH               (0x30000000)
-#define        PSB_2D_MASK_OFF_BH              (0x40000000)
-#define        PSB_2D_RESERVED1_BH             (0x50000000)
-#define        PSB_2D_RESERVED2_BH             (0x60000000)
-#define        PSB_2D_FENCE_BH                 (0x70000000)
-#define        PSB_2D_BLIT_BH                  (0x80000000)
-#define        PSB_2D_SRC_SURF_BH              (0x90000000)
-#define        PSB_2D_DST_SURF_BH              (0xA0000000)
-#define        PSB_2D_PAT_SURF_BH              (0xB0000000)
-#define        PSB_2D_SRC_PAL_BH               (0xC0000000)
-#define        PSB_2D_PAT_PAL_BH               (0xD0000000)
-#define        PSB_2D_MASK_SURF_BH             (0xE0000000)
-#define        PSB_2D_FLUSH_BH                 (0xF0000000)
-
-/*
- * Clip Definition block (PSB_2D_CLIP_BH)
- */
-#define PSB_2D_CLIPCOUNT_MAX           (1)
-#define PSB_2D_CLIPCOUNT_MASK          (0x00000000)
-#define PSB_2D_CLIPCOUNT_CLRMASK       (0xFFFFFFFF)
-#define PSB_2D_CLIPCOUNT_SHIFT         (0)
-/* clip rectangle min & max */
-#define PSB_2D_CLIP_XMAX_MASK          (0x00FFF000)
-#define PSB_2D_CLIP_XMAX_CLRMASK       (0xFF000FFF)
-#define PSB_2D_CLIP_XMAX_SHIFT         (12)
-#define PSB_2D_CLIP_XMIN_MASK          (0x00000FFF)
-#define PSB_2D_CLIP_XMIN_CLRMASK       (0x00FFF000)
-#define PSB_2D_CLIP_XMIN_SHIFT         (0)
-/* clip rectangle offset */
-#define PSB_2D_CLIP_YMAX_MASK          (0x00FFF000)
-#define PSB_2D_CLIP_YMAX_CLRMASK       (0xFF000FFF)
-#define PSB_2D_CLIP_YMAX_SHIFT         (12)
-#define PSB_2D_CLIP_YMIN_MASK          (0x00000FFF)
-#define PSB_2D_CLIP_YMIN_CLRMASK       (0x00FFF000)
-#define PSB_2D_CLIP_YMIN_SHIFT         (0)
-
-/*
- * Pattern Control (PSB_2D_PAT_BH)
- */
-#define PSB_2D_PAT_HEIGHT_MASK         (0x0000001F)
-#define PSB_2D_PAT_HEIGHT_SHIFT                (0)
-#define PSB_2D_PAT_WIDTH_MASK          (0x000003E0)
-#define PSB_2D_PAT_WIDTH_SHIFT         (5)
-#define PSB_2D_PAT_YSTART_MASK         (0x00007C00)
-#define PSB_2D_PAT_YSTART_SHIFT                (10)
-#define PSB_2D_PAT_XSTART_MASK         (0x000F8000)
-#define PSB_2D_PAT_XSTART_SHIFT                (15)
-
-/*
- * 2D Control block (PSB_2D_CTRL_BH)
- */
-/* Present Flags */
-#define PSB_2D_SRCCK_CTRL              (0x00000001)
-#define PSB_2D_DSTCK_CTRL              (0x00000002)
-#define PSB_2D_ALPHA_CTRL              (0x00000004)
-/* Colour Key Colour (SRC/DST)*/
-#define PSB_2D_CK_COL_MASK             (0xFFFFFFFF)
-#define PSB_2D_CK_COL_CLRMASK          (0x00000000)
-#define PSB_2D_CK_COL_SHIFT            (0)
-/* Colour Key Mask (SRC/DST)*/
-#define PSB_2D_CK_MASK_MASK            (0xFFFFFFFF)
-#define PSB_2D_CK_MASK_CLRMASK         (0x00000000)
-#define PSB_2D_CK_MASK_SHIFT           (0)
-/* Alpha Control (Alpha/RGB)*/
-#define PSB_2D_GBLALPHA_MASK           (0x000FF000)
-#define PSB_2D_GBLALPHA_CLRMASK                (0xFFF00FFF)
-#define PSB_2D_GBLALPHA_SHIFT          (12)
-#define PSB_2D_SRCALPHA_OP_MASK                (0x00700000)
-#define PSB_2D_SRCALPHA_OP_CLRMASK     (0xFF8FFFFF)
-#define PSB_2D_SRCALPHA_OP_SHIFT       (20)
-#define PSB_2D_SRCALPHA_OP_ONE         (0x00000000)
-#define PSB_2D_SRCALPHA_OP_SRC         (0x00100000)
-#define PSB_2D_SRCALPHA_OP_DST         (0x00200000)
-#define PSB_2D_SRCALPHA_OP_SG          (0x00300000)
-#define PSB_2D_SRCALPHA_OP_DG          (0x00400000)
-#define PSB_2D_SRCALPHA_OP_GBL         (0x00500000)
-#define PSB_2D_SRCALPHA_OP_ZERO                (0x00600000)
-#define PSB_2D_SRCALPHA_INVERT         (0x00800000)
-#define PSB_2D_SRCALPHA_INVERT_CLR     (0xFF7FFFFF)
-#define PSB_2D_DSTALPHA_OP_MASK                (0x07000000)
-#define PSB_2D_DSTALPHA_OP_CLRMASK     (0xF8FFFFFF)
-#define PSB_2D_DSTALPHA_OP_SHIFT       (24)
-#define PSB_2D_DSTALPHA_OP_ONE         (0x00000000)
-#define PSB_2D_DSTALPHA_OP_SRC         (0x01000000)
-#define PSB_2D_DSTALPHA_OP_DST         (0x02000000)
-#define PSB_2D_DSTALPHA_OP_SG          (0x03000000)
-#define PSB_2D_DSTALPHA_OP_DG          (0x04000000)
-#define PSB_2D_DSTALPHA_OP_GBL         (0x05000000)
-#define PSB_2D_DSTALPHA_OP_ZERO                (0x06000000)
-#define PSB_2D_DSTALPHA_INVERT         (0x08000000)
-#define PSB_2D_DSTALPHA_INVERT_CLR     (0xF7FFFFFF)
-
-#define PSB_2D_PRE_MULTIPLICATION_ENABLE       (0x10000000)
-#define PSB_2D_PRE_MULTIPLICATION_CLRMASK      (0xEFFFFFFF)
-#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE                (0x20000000)
-#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK       (0xDFFFFFFF)
-
-/*
- *Source Offset (PSB_2D_SRC_OFF_BH)
- */
-#define PSB_2D_SRCOFF_XSTART_MASK      ((0x00000FFF) << 12)
-#define PSB_2D_SRCOFF_XSTART_SHIFT     (12)
-#define PSB_2D_SRCOFF_YSTART_MASK      (0x00000FFF)
-#define PSB_2D_SRCOFF_YSTART_SHIFT     (0)
-
-/*
- * Mask Offset (PSB_2D_MASK_OFF_BH)
- */
-#define PSB_2D_MASKOFF_XSTART_MASK     ((0x00000FFF) << 12)
-#define PSB_2D_MASKOFF_XSTART_SHIFT    (12)
-#define PSB_2D_MASKOFF_YSTART_MASK     (0x00000FFF)
-#define PSB_2D_MASKOFF_YSTART_SHIFT    (0)
-
-/*
- * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
- */
-
-/*
- *Blit Rectangle (PSB_2D_BLIT_BH)
- */
-
-#define PSB_2D_ROT_MASK                        (3 << 25)
-#define PSB_2D_ROT_CLRMASK             (~PSB_2D_ROT_MASK)
-#define PSB_2D_ROT_NONE                        (0 << 25)
-#define PSB_2D_ROT_90DEGS              (1 << 25)
-#define PSB_2D_ROT_180DEGS             (2 << 25)
-#define PSB_2D_ROT_270DEGS             (3 << 25)
-
-#define PSB_2D_COPYORDER_MASK          (3 << 23)
-#define PSB_2D_COPYORDER_CLRMASK       (~PSB_2D_COPYORDER_MASK)
-#define PSB_2D_COPYORDER_TL2BR         (0 << 23)
-#define PSB_2D_COPYORDER_BR2TL         (1 << 23)
-#define PSB_2D_COPYORDER_TR2BL         (2 << 23)
-#define PSB_2D_COPYORDER_BL2TR         (3 << 23)
-
-#define PSB_2D_DSTCK_CLRMASK           (0xFF9FFFFF)
-#define PSB_2D_DSTCK_DISABLE           (0x00000000)
-#define PSB_2D_DSTCK_PASS              (0x00200000)
-#define PSB_2D_DSTCK_REJECT            (0x00400000)
-
-#define PSB_2D_SRCCK_CLRMASK           (0xFFE7FFFF)
-#define PSB_2D_SRCCK_DISABLE           (0x00000000)
-#define PSB_2D_SRCCK_PASS              (0x00080000)
-#define PSB_2D_SRCCK_REJECT            (0x00100000)
-
-#define PSB_2D_CLIP_ENABLE             (0x00040000)
-
-#define PSB_2D_ALPHA_ENABLE            (0x00020000)
-
-#define PSB_2D_PAT_CLRMASK             (0xFFFEFFFF)
-#define PSB_2D_PAT_MASK                        (0x00010000)
-#define PSB_2D_USE_PAT                 (0x00010000)
-#define PSB_2D_USE_FILL                        (0x00000000)
-/*
- * Tungsten Graphics note on rop codes: If rop A and rop B are
- * identical, the mask surface will not be read and need not be
- * set up.
- */
-
-#define PSB_2D_ROP3B_MASK              (0x0000FF00)
-#define PSB_2D_ROP3B_CLRMASK           (0xFFFF00FF)
-#define PSB_2D_ROP3B_SHIFT             (8)
-/* rop code A */
-#define PSB_2D_ROP3A_MASK              (0x000000FF)
-#define PSB_2D_ROP3A_CLRMASK           (0xFFFFFF00)
-#define PSB_2D_ROP3A_SHIFT             (0)
-
-#define PSB_2D_ROP4_MASK               (0x0000FFFF)
-/*
- *     DWORD0: (Only pass if Pattern control == Use Fill Colour)
- *     Fill Colour RGBA8888
- */
-#define PSB_2D_FILLCOLOUR_MASK         (0xFFFFFFFF)
-#define PSB_2D_FILLCOLOUR_SHIFT                (0)
-/*
- *     DWORD1: (Always Present)
- *     X Start (Dest)
- *     Y Start (Dest)
- */
-#define PSB_2D_DST_XSTART_MASK         (0x00FFF000)
-#define PSB_2D_DST_XSTART_CLRMASK      (0xFF000FFF)
-#define PSB_2D_DST_XSTART_SHIFT                (12)
-#define PSB_2D_DST_YSTART_MASK         (0x00000FFF)
-#define PSB_2D_DST_YSTART_CLRMASK      (0xFFFFF000)
-#define PSB_2D_DST_YSTART_SHIFT                (0)
-/*
- *     DWORD2: (Always Present)
- *     X Size (Dest)
- *     Y Size (Dest)
- */
-#define PSB_2D_DST_XSIZE_MASK          (0x00FFF000)
-#define PSB_2D_DST_XSIZE_CLRMASK       (0xFF000FFF)
-#define PSB_2D_DST_XSIZE_SHIFT         (12)
-#define PSB_2D_DST_YSIZE_MASK          (0x00000FFF)
-#define PSB_2D_DST_YSIZE_CLRMASK       (0xFFFFF000)
-#define PSB_2D_DST_YSIZE_SHIFT         (0)
-
-/*
- * Source Surface (PSB_2D_SRC_SURF_BH)
- */
-/*
- * WORD 0
- */
-
-#define PSB_2D_SRC_FORMAT_MASK         (0x00078000)
-#define PSB_2D_SRC_1_PAL               (0x00000000)
-#define PSB_2D_SRC_2_PAL               (0x00008000)
-#define PSB_2D_SRC_4_PAL               (0x00010000)
-#define PSB_2D_SRC_8_PAL               (0x00018000)
-#define PSB_2D_SRC_8_ALPHA             (0x00020000)
-#define PSB_2D_SRC_4_ALPHA             (0x00028000)
-#define PSB_2D_SRC_332RGB              (0x00030000)
-#define PSB_2D_SRC_4444ARGB            (0x00038000)
-#define PSB_2D_SRC_555RGB              (0x00040000)
-#define PSB_2D_SRC_1555ARGB            (0x00048000)
-#define PSB_2D_SRC_565RGB              (0x00050000)
-#define PSB_2D_SRC_0888ARGB            (0x00058000)
-#define PSB_2D_SRC_8888ARGB            (0x00060000)
-#define PSB_2D_SRC_8888UYVY            (0x00068000)
-#define PSB_2D_SRC_RESERVED            (0x00070000)
-#define PSB_2D_SRC_1555ARGB_LOOKUP     (0x00078000)
-
-
-#define PSB_2D_SRC_STRIDE_MASK         (0x00007FFF)
-#define PSB_2D_SRC_STRIDE_CLRMASK      (0xFFFF8000)
-#define PSB_2D_SRC_STRIDE_SHIFT                (0)
-/*
- *  WORD 1 - Base Address
- */
-#define PSB_2D_SRC_ADDR_MASK           (0x0FFFFFFC)
-#define PSB_2D_SRC_ADDR_CLRMASK                (0x00000003)
-#define PSB_2D_SRC_ADDR_SHIFT          (2)
-#define PSB_2D_SRC_ADDR_ALIGNSHIFT     (2)
-
-/*
- * Pattern Surface (PSB_2D_PAT_SURF_BH)
- */
-/*
- *  WORD 0
- */
-
-#define PSB_2D_PAT_FORMAT_MASK         (0x00078000)
-#define PSB_2D_PAT_1_PAL               (0x00000000)
-#define PSB_2D_PAT_2_PAL               (0x00008000)
-#define PSB_2D_PAT_4_PAL               (0x00010000)
-#define PSB_2D_PAT_8_PAL               (0x00018000)
-#define PSB_2D_PAT_8_ALPHA             (0x00020000)
-#define PSB_2D_PAT_4_ALPHA             (0x00028000)
-#define PSB_2D_PAT_332RGB              (0x00030000)
-#define PSB_2D_PAT_4444ARGB            (0x00038000)
-#define PSB_2D_PAT_555RGB              (0x00040000)
-#define PSB_2D_PAT_1555ARGB            (0x00048000)
-#define PSB_2D_PAT_565RGB              (0x00050000)
-#define PSB_2D_PAT_0888ARGB            (0x00058000)
-#define PSB_2D_PAT_8888ARGB            (0x00060000)
-
-#define PSB_2D_PAT_STRIDE_MASK         (0x00007FFF)
-#define PSB_2D_PAT_STRIDE_CLRMASK      (0xFFFF8000)
-#define PSB_2D_PAT_STRIDE_SHIFT                (0)
-/*
- *  WORD 1 - Base Address
- */
-#define PSB_2D_PAT_ADDR_MASK           (0x0FFFFFFC)
-#define PSB_2D_PAT_ADDR_CLRMASK                (0x00000003)
-#define PSB_2D_PAT_ADDR_SHIFT          (2)
-#define PSB_2D_PAT_ADDR_ALIGNSHIFT     (2)
-
-/*
- * Destination Surface (PSB_2D_DST_SURF_BH)
- */
-/*
- * WORD 0
- */
-
-#define PSB_2D_DST_FORMAT_MASK         (0x00078000)
-#define PSB_2D_DST_332RGB              (0x00030000)
-#define PSB_2D_DST_4444ARGB            (0x00038000)
-#define PSB_2D_DST_555RGB              (0x00040000)
-#define PSB_2D_DST_1555ARGB            (0x00048000)
-#define PSB_2D_DST_565RGB              (0x00050000)
-#define PSB_2D_DST_0888ARGB            (0x00058000)
-#define PSB_2D_DST_8888ARGB            (0x00060000)
-#define PSB_2D_DST_8888AYUV            (0x00070000)
-
-#define PSB_2D_DST_STRIDE_MASK         (0x00007FFF)
-#define PSB_2D_DST_STRIDE_CLRMASK      (0xFFFF8000)
-#define PSB_2D_DST_STRIDE_SHIFT                (0)
-/*
- * WORD 1 - Base Address
- */
-#define PSB_2D_DST_ADDR_MASK           (0x0FFFFFFC)
-#define PSB_2D_DST_ADDR_CLRMASK                (0x00000003)
-#define PSB_2D_DST_ADDR_SHIFT          (2)
-#define PSB_2D_DST_ADDR_ALIGNSHIFT     (2)
-
-/*
- * Mask Surface (PSB_2D_MASK_SURF_BH)
- */
-/*
- * WORD 0
- */
-#define PSB_2D_MASK_STRIDE_MASK                (0x00007FFF)
-#define PSB_2D_MASK_STRIDE_CLRMASK     (0xFFFF8000)
-#define PSB_2D_MASK_STRIDE_SHIFT       (0)
-/*
- *  WORD 1 - Base Address
- */
-#define PSB_2D_MASK_ADDR_MASK          (0x0FFFFFFC)
-#define PSB_2D_MASK_ADDR_CLRMASK       (0x00000003)
-#define PSB_2D_MASK_ADDR_SHIFT         (2)
-#define PSB_2D_MASK_ADDR_ALIGNSHIFT    (2)
-
-/*
- * Source Palette (PSB_2D_SRC_PAL_BH)
- */
-
-#define PSB_2D_SRCPAL_ADDR_SHIFT       (0)
-#define PSB_2D_SRCPAL_ADDR_CLRMASK     (0xF0000007)
-#define PSB_2D_SRCPAL_ADDR_MASK                (0x0FFFFFF8)
-#define PSB_2D_SRCPAL_BYTEALIGN                (1024)
-
-/*
- * Pattern Palette (PSB_2D_PAT_PAL_BH)
- */
-
-#define PSB_2D_PATPAL_ADDR_SHIFT       (0)
-#define PSB_2D_PATPAL_ADDR_CLRMASK     (0xF0000007)
-#define PSB_2D_PATPAL_ADDR_MASK                (0x0FFFFFF8)
-#define PSB_2D_PATPAL_BYTEALIGN                (1024)
-
-/*
- * Rop3 Codes (2 LS bytes)
- */
-
-#define PSB_2D_ROP3_SRCCOPY            (0xCCCC)
-#define PSB_2D_ROP3_PATCOPY            (0xF0F0)
-#define PSB_2D_ROP3_WHITENESS          (0xFFFF)
-#define PSB_2D_ROP3_BLACKNESS          (0x0000)
-#define PSB_2D_ROP3_SRC                        (0xCC)
-#define PSB_2D_ROP3_PAT                        (0xF0)
-#define PSB_2D_ROP3_DST                        (0xAA)
-
-/*
- * Sizes.
- */
-
-#define PSB_SCENE_HW_COOKIE_SIZE       16
-#define PSB_TA_MEM_HW_COOKIE_SIZE      16
-
-/*
- * Scene stuff.
- */
-
-#define PSB_NUM_HW_SCENES              2
-
-/*
- * Scheduler completion actions.
- */
-
-#define PSB_RASTER_BLOCK               0
-#define PSB_RASTER                     1
-#define PSB_RETURN                     2
-#define PSB_TA                         3
-
-/* Power management */
-#define PSB_PUNIT_PORT                 0x04
-#define PSB_OSPMBA                     0x78
-#define PSB_APMBA                      0x7a
-#define PSB_APM_CMD                    0x0
-#define PSB_APM_STS                    0x04
-#define PSB_PWRGT_VID_ENC_MASK         0x30
-#define PSB_PWRGT_VID_DEC_MASK         0xc
-#define PSB_PWRGT_GL3_MASK             0xc0
-
-#define PSB_PM_SSC                     0x20
-#define PSB_PM_SSS                     0x30
-#define PSB_PWRGT_DISPLAY_MASK         0xc /*on a different BA than video/gfx*/
-#define MDFLD_PWRGT_DISPLAY_A_CNTR     0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_CNTR     0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_CNTR     0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_CNTR     0x000c0000
-#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */
-/* Display SSS register bits are different in A0 vs. B0 */
-#define PSB_PWRGT_GFX_MASK             0x3
-#define MDFLD_PWRGT_DISPLAY_A_STS      0x000000c0
-#define MDFLD_PWRGT_DISPLAY_B_STS      0x00000300
-#define MDFLD_PWRGT_DISPLAY_C_STS      0x00000c00
-#define PSB_PWRGT_GFX_MASK_B0          0xc3
-#define MDFLD_PWRGT_DISPLAY_A_STS_B0   0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_STS_B0   0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_STS_B0   0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_STS      0x000c0000
-#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
-#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
-#endif
index 70e006b50f292259025b50a5b03a2aa26a9c2b5f..5443e25086e9f33b00980d314a874863653c82f8 100644 (file)
@@ -1279,3 +1279,4 @@ static struct usb_driver go7007_usb_driver = {
 };
 
 module_usb_driver(go7007_usb_driver);
+MODULE_LICENSE("GPL v2");
index 592cf69020cd7b6b133e18da3f92b1aef6d0315a..d9cdc120d122e904ea24bec55224ad8635ba6e8a 100644 (file)
@@ -7,6 +7,7 @@ ccflags-y := -Iinclude/drm -Werror
 omapdrm-y := omap_drv.o \
        omap_debugfs.o \
        omap_crtc.o \
+       omap_plane.o \
        omap_encoder.o \
        omap_connector.o \
        omap_fb.o \
index cffdf5e1239424331edb51f45528139255263626..17ca163e5896ba86f8422a77ffdccaec8800fc30 100644 (file)
 
 struct omap_crtc {
        struct drm_crtc base;
-       struct omap_overlay *ovl;
-       struct omap_overlay_info info;
+       struct drm_plane *plane;
+       const char *name;
        int id;
 
-       /* if there is a pending flip, this will be non-null: */
+       /* if there is a pending flip, these will be non-null: */
        struct drm_pending_vblank_event *event;
+       struct drm_framebuffer *old_fb;
 };
 
-/* push changes down to dss2 */
-static int commit(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       struct omap_overlay *ovl = omap_crtc->ovl;
-       struct omap_overlay_info *info = &omap_crtc->info;
-       int ret;
-
-       DBG("%s", omap_crtc->ovl->name);
-       DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
-                       info->out_height, info->screen_width);
-       DBG("%d,%d %08x", info->pos_x, info->pos_y, info->paddr);
-
-       /* NOTE: do we want to do this at all here, or just wait
-        * for dpms(ON) since other CRTC's may not have their mode
-        * set yet, so fb dimensions may still change..
-        */
-       ret = ovl->set_overlay_info(ovl, info);
-       if (ret) {
-               dev_err(dev->dev, "could not set overlay info\n");
-               return ret;
-       }
-
-       /* our encoder doesn't necessarily get a commit() after this, in
-        * particular in the dpms() and mode_set_base() cases, so force the
-        * manager to update:
-        *
-        * could this be in the encoder somehow?
-        */
-       if (ovl->manager) {
-               ret = ovl->manager->apply(ovl->manager);
-               if (ret) {
-                       dev_err(dev->dev, "could not apply settings\n");
-                       return ret;
-               }
-       }
-
-       if (info->enabled) {
-               omap_framebuffer_flush(crtc->fb, crtc->x, crtc->y,
-                               crtc->fb->width, crtc->fb->height);
-       }
-
-       return 0;
-}
-
-/* update parameters that are dependent on the framebuffer dimensions and
- * position within the fb that this crtc scans out from. This is called
- * when framebuffer dimensions or x,y base may have changed, either due
- * to our mode, or a change in another crtc that is scanning out of the
- * same fb.
- */
-static void update_scanout(struct drm_crtc *crtc)
-{
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       dma_addr_t paddr;
-       unsigned int screen_width;
-
-       omap_framebuffer_get_buffer(crtc->fb, crtc->x, crtc->y,
-                       NULL, &paddr, &screen_width);
-
-       DBG("%s: %d,%d: %08x (%d)", omap_crtc->ovl->name,
-                       crtc->x, crtc->y, (u32)paddr, screen_width);
-
-       omap_crtc->info.paddr = paddr;
-       omap_crtc->info.screen_width = screen_width;
-}
-
 static void omap_crtc_gamma_set(struct drm_crtc *crtc,
                u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size)
 {
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       DBG("%s", omap_crtc->ovl->name);
+       /* not supported.. at least not yet */
 }
 
 static void omap_crtc_destroy(struct drm_crtc *crtc)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       DBG("%s", omap_crtc->ovl->name);
+       omap_crtc->plane->funcs->destroy(omap_crtc->plane);
        drm_crtc_cleanup(crtc);
        kfree(omap_crtc);
 }
 
 static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
+       struct omap_drm_private *priv = crtc->dev->dev_private;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       int i;
 
-       DBG("%s: %d", omap_crtc->ovl->name, mode);
+       WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
 
-       if (mode == DRM_MODE_DPMS_ON) {
-               update_scanout(crtc);
-               omap_crtc->info.enabled = true;
-       } else {
-               omap_crtc->info.enabled = false;
+       for (i = 0; i < priv->num_planes; i++) {
+               struct drm_plane *plane = priv->planes[i];
+               if (plane->crtc == crtc)
+                       WARN_ON(omap_plane_dpms(plane, mode));
        }
-
-       WARN_ON(commit(crtc));
 }
 
 static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
+               struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
 {
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       DBG("%s", omap_crtc->ovl->name);
        return true;
 }
 
 static int omap_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y,
-                              struct drm_framebuffer *old_fb)
+               struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode,
+               int x, int y,
+               struct drm_framebuffer *old_fb)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       struct drm_plane *plane = omap_crtc->plane;
 
-       DBG("%s: %d,%d: %dx%d", omap_crtc->ovl->name, x, y,
-                       mode->hdisplay, mode->vdisplay);
-
-       /* just use adjusted mode */
-       mode = adjusted_mode;
-
-       omap_crtc->info.width = mode->hdisplay;
-       omap_crtc->info.height = mode->vdisplay;
-       omap_crtc->info.out_width = mode->hdisplay;
-       omap_crtc->info.out_height = mode->vdisplay;
-       omap_crtc->info.color_mode = OMAP_DSS_COLOR_RGB24U;
-       omap_crtc->info.rotation_type = OMAP_DSS_ROT_DMA;
-       omap_crtc->info.rotation = OMAP_DSS_ROT_0;
-       omap_crtc->info.global_alpha = 0xff;
-       omap_crtc->info.mirror = 0;
-       omap_crtc->info.mirror = 0;
-       omap_crtc->info.pos_x = 0;
-       omap_crtc->info.pos_y = 0;
-#if 0 /* re-enable when these are available in DSS2 driver */
-       omap_crtc->info.zorder = 3;        /* GUI in the front, video behind */
-       omap_crtc->info.min_x_decim = 1;
-       omap_crtc->info.max_x_decim = 1;
-       omap_crtc->info.min_y_decim = 1;
-       omap_crtc->info.max_y_decim = 1;
-#endif
-
-       update_scanout(crtc);
-
-       return 0;
+       return omap_plane_mode_set(plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
 }
 
 static void omap_crtc_prepare(struct drm_crtc *crtc)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       struct omap_overlay *ovl = omap_crtc->ovl;
-
-       DBG("%s", omap_crtc->ovl->name);
-
-       ovl->get_overlay_info(ovl, &omap_crtc->info);
-
+       DBG("%s", omap_crtc->name);
        omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
 static void omap_crtc_commit(struct drm_crtc *crtc)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       DBG("%s", omap_crtc->ovl->name);
+       DBG("%s", omap_crtc->name);
        omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 }
 
 static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-                   struct drm_framebuffer *old_fb)
+               struct drm_framebuffer *old_fb)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       struct drm_plane *plane = omap_crtc->plane;
+       struct drm_display_mode *mode = &crtc->mode;
 
-       DBG("%s %d,%d: fb=%p", omap_crtc->ovl->name, x, y, old_fb);
-
-       update_scanout(crtc);
-
-       return commit(crtc);
+       return plane->funcs->update_plane(plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
 }
 
 static void omap_crtc_load_lut(struct drm_crtc *crtc)
 {
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       DBG("%s", omap_crtc->ovl->name);
 }
 
 static void page_flip_cb(void *arg)
@@ -225,15 +124,16 @@ static void page_flip_cb(void *arg)
        struct drm_device *dev = crtc->dev;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
        struct drm_pending_vblank_event *event = omap_crtc->event;
+       struct drm_framebuffer *old_fb = omap_crtc->old_fb;
        struct timeval now;
        unsigned long flags;
 
        WARN_ON(!event);
 
        omap_crtc->event = NULL;
+       omap_crtc->old_fb = NULL;
 
-       update_scanout(crtc);
-       WARN_ON(commit(crtc));
+       omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
 
        /* wakeup userspace */
        /* TODO: this should happen *after* flip in vsync IRQ handler */
@@ -264,10 +164,11 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
-       crtc->fb = fb;
+       omap_crtc->old_fb = crtc->fb;
        omap_crtc->event = event;
+       crtc->fb = fb;
 
-       omap_gem_op_async(omap_framebuffer_bo(fb), OMAP_GEM_READ,
+       omap_gem_op_async(omap_framebuffer_bo(fb, 0), OMAP_GEM_READ,
                        page_flip_cb, crtc);
 
        return 0;
@@ -290,12 +191,6 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
        .load_lut = omap_crtc_load_lut,
 };
 
-struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc)
-{
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       return omap_crtc->ovl;
-}
-
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                struct omap_overlay *ovl, int id)
@@ -310,9 +205,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                goto fail;
        }
 
-       omap_crtc->ovl = ovl;
-       omap_crtc->id = id;
        crtc = &omap_crtc->base;
+
+       omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true);
+       omap_crtc->plane->crtc = crtc;
+       omap_crtc->name = ovl->name;
+       omap_crtc->id = id;
+
        drm_crtc_init(dev, crtc, &omap_crtc_funcs);
        drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
 
index 602aa2dd49c867d02706680607598ab78ce7bd64..3bbea9aac404338e0d87bb20e0cccc8e7620a489 100644 (file)
@@ -204,12 +204,6 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
        struct omap_overlay_manager *mgr = NULL;
        struct drm_crtc *crtc;
 
-       if (ovl->manager) {
-               DBG("disconnecting %s from %s", ovl->name,
-                                       ovl->manager->name);
-               ovl->unset_manager(ovl);
-       }
-
        /* find next best connector, ones with detected connection first
         */
        while (*j < priv->num_connectors && !mgr) {
@@ -245,11 +239,6 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
                (*j)++;
        }
 
-       if (mgr) {
-               DBG("connecting %s to %s", ovl->name, mgr->name);
-               ovl->set_manager(ovl, mgr);
-       }
-
        crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);
 
        if (!crtc) {
@@ -265,6 +254,26 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
        return 0;
 }
 
+static int create_plane(struct drm_device *dev, struct omap_overlay *ovl,
+               unsigned int possible_crtcs)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       struct drm_plane *plane =
+                       omap_plane_init(dev, ovl, possible_crtcs, false);
+
+       if (!plane) {
+               dev_err(dev->dev, "could not create plane: %s\n",
+                               ovl->name);
+               return -ENOMEM;
+       }
+
+       BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
+
+       priv->planes[priv->num_planes++] = plane;
+
+       return 0;
+}
+
 static int match_dev_name(struct omap_dss_device *dssdev, void *data)
 {
        return !strcmp(dssdev->name, data);
@@ -332,6 +341,12 @@ static int omap_modeset_init(struct drm_device *dev)
                                omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
                        create_crtc(dev, ovl, &j, connected_connectors);
                }
+
+               for (i = 0; i < kms_pdata->pln_cnt; i++) {
+                       struct omap_overlay *ovl =
+                               omap_dss_get_overlay(kms_pdata->pln_ids[i]);
+                       create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
+               }
        } else {
                /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
                 * to make educated guesses about everything else
@@ -353,6 +368,12 @@ static int omap_modeset_init(struct drm_device *dev)
                        create_crtc(dev, omap_dss_get_overlay(i),
                                        &j, connected_connectors);
                }
+
+               /* use any remaining overlays as drm planes */
+               for (; i < omap_dss_get_num_overlays(); i++) {
+                       struct omap_overlay *ovl = omap_dss_get_overlay(i);
+                       create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
+               }
        }
 
        /* for now keep the mapping of CRTCs and encoders static.. */
@@ -361,15 +382,7 @@ static int omap_modeset_init(struct drm_device *dev)
                struct omap_overlay_manager *mgr =
                                omap_encoder_get_manager(encoder);
 
-               encoder->possible_crtcs = 0;
-
-               for (j = 0; j < priv->num_crtcs; j++) {
-                       struct omap_overlay *ovl =
-                                       omap_crtc_get_overlay(priv->crtcs[j]);
-                       if (ovl->manager == mgr) {
-                               encoder->possible_crtcs |= (1 << j);
-                       }
-               }
+               encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
 
                DBG("%s: possible_crtcs=%08x", mgr->name,
                                        encoder->possible_crtcs);
@@ -377,8 +390,8 @@ static int omap_modeset_init(struct drm_device *dev)
 
        dump_video_chains();
 
-       dev->mode_config.min_width = 256;
-       dev->mode_config.min_height = 256;
+       dev->mode_config.min_width = 32;
+       dev->mode_config.min_height = 32;
 
        /* note: eventually will need some cpu_is_omapXYZ() type stuff here
         * to fill in these limits properly on different OMAP generations..
@@ -708,6 +721,18 @@ static struct vm_operations_struct omap_gem_vm_ops = {
        .close = drm_gem_vm_close,
 };
 
+static const struct file_operations omapdriver_fops = {
+               .owner = THIS_MODULE,
+               .open = drm_open,
+               .unlocked_ioctl = drm_ioctl,
+               .release = drm_release,
+               .mmap = omap_gem_mmap,
+               .poll = drm_poll,
+               .fasync = drm_fasync,
+               .read = drm_read,
+               .llseek = noop_llseek,
+};
+
 static struct drm_driver omap_drm_driver = {
                .driver_features =
                                DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM,
@@ -738,17 +763,7 @@ static struct drm_driver omap_drm_driver = {
                .dumb_destroy = omap_gem_dumb_destroy,
                .ioctls = ioctls,
                .num_ioctls = DRM_OMAP_NUM_IOCTLS,
-               .fops = {
-                               .owner = THIS_MODULE,
-                               .open = drm_open,
-                               .unlocked_ioctl = drm_ioctl,
-                               .release = drm_release,
-                               .mmap = omap_gem_mmap,
-                               .poll = drm_poll,
-                               .fasync = drm_fasync,
-                               .read = drm_read,
-                               .llseek = noop_llseek,
-               },
+               .fops = &omapdriver_fops,
                .name = DRIVER_NAME,
                .desc = DRIVER_DESC,
                .date = DRIVER_DATE,
index 76c42515ecc562f85c51cfe0f0a69a8bc33bc7cb..61fe022dda5b8f67c5629ce4e9bcad6625f8f4fc 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
 #include "omap_drm.h"
 #include "omap_priv.h"
 
@@ -41,6 +42,8 @@
 struct omap_drm_private {
        unsigned int num_crtcs;
        struct drm_crtc *crtcs[8];
+       unsigned int num_planes;
+       struct drm_plane *planes[8];
        unsigned int num_encoders;
        struct drm_encoder *encoders[8];
        unsigned int num_connectors;
@@ -61,7 +64,17 @@ void omap_fbdev_free(struct drm_device *dev);
 
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                struct omap_overlay *ovl, int id);
-struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc);
+
+struct drm_plane *omap_plane_init(struct drm_device *dev,
+               struct omap_overlay *ovl, unsigned int possible_crtcs,
+               bool priv);
+int omap_plane_dpms(struct drm_plane *plane, int mode);
+int omap_plane_mode_set(struct drm_plane *plane,
+               struct drm_crtc *crtc, struct drm_framebuffer *fb,
+               int crtc_x, int crtc_y,
+               unsigned int crtc_w, unsigned int crtc_h,
+               uint32_t src_x, uint32_t src_y,
+               uint32_t src_w, uint32_t src_h);
 
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
                struct omap_overlay_manager *mgr);
@@ -80,12 +93,14 @@ void omap_connector_flush(struct drm_connector *connector,
                int x, int y, int w, int h);
 
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
-               struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd);
+               struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
-               struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo);
-struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb);
-int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
-               void **vaddr, dma_addr_t *paddr, unsigned int *screen_width);
+               struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
+struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
+int omap_framebuffer_pin(struct drm_framebuffer *fb);
+void omap_framebuffer_unpin(struct drm_framebuffer *fb);
+void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
+               struct omap_overlay_info *info);
 struct drm_connector *omap_framebuffer_get_next_connector(
                struct drm_framebuffer *fb, struct drm_connector *from);
 void omap_framebuffer_flush(struct drm_framebuffer *fb,
@@ -132,4 +147,29 @@ static inline int align_pitch(int pitch, int width, int bpp)
        return ALIGN(pitch, 8 * bytespp);
 }
 
+/* should these be made into common util helpers?
+ */
+
+static inline int objects_lookup(struct drm_device *dev,
+               struct drm_file *filp, uint32_t pixel_format,
+               struct drm_gem_object **bos, uint32_t *handles)
+{
+       int i, n = drm_format_num_planes(pixel_format);
+
+       for (i = 0; i < n; i++) {
+               bos[i] = drm_gem_object_lookup(dev, filp, handles[i]);
+               if (!bos[i]) {
+                       goto fail;
+               }
+       }
+
+       return 0;
+
+fail:
+       while (--i > 0) {
+               drm_gem_object_unreference_unlocked(bos[i]);
+       }
+       return -ENOENT;
+}
+
 #endif /* __OMAP_DRV_H__ */
index 0b50c5b3b56465ab384fd2e4af88f81190176d45..d021a7ec58dfca6575df127a734bc6923bbc751d 100644 (file)
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 
-
 /*
  * framebuffer funcs
  */
 
+/* per-format info: */
+struct format {
+       enum omap_color_mode dss_format;
+       uint32_t pixel_format;
+       struct {
+               int stride_bpp;           /* this times width is stride */
+               int sub_y;                /* sub-sample in y dimension */
+       } planes[4];
+       bool yuv;
+};
+
+static const struct format formats[] = {
+       /* 16bpp [A]RGB: */
+       { OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565,   {{2, 1}}, false }, /* RGB16-565 */
+       { OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */
+       { OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */
+       { OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */
+       { OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */
+       { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */
+       { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */
+       /* 24bpp RGB: */
+       { OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888,   {{3, 1}}, false }, /* RGB24-888 */
+       /* 32bpp [A]RGB: */
+       { OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */
+       { OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */
+       { OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */
+       { OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */
+       /* YUV: */
+       { OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12,     {{1, 1}, {1, 2}}, true },
+       { OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV,     {{2, 1}}, true },
+       { OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY,     {{2, 1}}, true },
+};
+
+/* per-plane info for the fb: */
+struct plane {
+       struct drm_gem_object *bo;
+       uint32_t pitch;
+       uint32_t offset;
+       dma_addr_t paddr;
+};
+
 #define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)
 
 struct omap_framebuffer {
        struct drm_framebuffer base;
-       struct drm_gem_object *bo;
-       int size;
-       dma_addr_t paddr;
+       const struct format *format;
+       struct plane planes[4];
 };
 
 static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
@@ -41,22 +80,23 @@ static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
                unsigned int *handle)
 {
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-    return drm_gem_handle_create(file_priv, omap_fb->bo, handle);
+       return drm_gem_handle_create(file_priv,
+                       omap_fb->planes[0].bo, handle);
 }
 
 static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
 {
-       struct drm_device *dev = fb->dev;
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+       int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
 
        DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
 
        drm_framebuffer_cleanup(fb);
 
-       if (omap_fb->bo) {
-               if (omap_fb->paddr && omap_gem_put_paddr(omap_fb->bo))
-                       dev_err(dev->dev, "could not unmap!\n");
-               drm_gem_object_unreference_unlocked(omap_fb->bo);
+       for (i = 0; i < n; i++) {
+               struct plane *plane = &omap_fb->planes[i];
+               if (plane->bo)
+                       drm_gem_object_unreference_unlocked(plane->bo);
        }
 
        kfree(omap_fb);
@@ -83,37 +123,76 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
        .dirty = omap_framebuffer_dirty,
 };
 
-/* returns the buffer size */
-int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
-               void **vaddr, dma_addr_t *paddr, unsigned int *screen_width)
+/* pins buffer in preparation for scanout */
+int omap_framebuffer_pin(struct drm_framebuffer *fb)
 {
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-       int bpp = fb->bits_per_pixel / 8;
-       unsigned long offset;
+       int ret, i, n = drm_format_num_planes(omap_fb->format->pixel_format);
 
-       offset = (x * bpp) + (y * fb->pitch);
+       for (i = 0; i < n; i++) {
+               struct plane *plane = &omap_fb->planes[i];
+               ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
+               if (ret)
+                       goto fail;
+       }
 
-       if (vaddr) {
-               void *bo_vaddr = omap_gem_vaddr(omap_fb->bo);
-               /* note: we can only count on having a vaddr for buffers that
-                * are allocated physically contiguously to begin with (ie.
-                * dma_alloc_coherent()).  But this should be ok because it
-                * is only used by legacy fbdev
-                */
-               BUG_ON(IS_ERR_OR_NULL(bo_vaddr));
-               *vaddr = bo_vaddr + offset;
+       return 0;
+
+fail:
+       while (--i > 0) {
+               struct plane *plane = &omap_fb->planes[i];
+               omap_gem_put_paddr(plane->bo);
        }
+       return ret;
+}
 
-       *paddr = omap_fb->paddr + offset;
-       *screen_width = fb->pitch / bpp;
+/* releases buffer when done with scanout */
+void omap_framebuffer_unpin(struct drm_framebuffer *fb)
+{
+       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+       int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
 
-       return omap_fb->size - offset;
+       for (i = 0; i < n; i++) {
+               struct plane *plane = &omap_fb->planes[i];
+               omap_gem_put_paddr(plane->bo);
+       }
 }
 
-struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb)
+/* update ovl info for scanout, handles cases of multi-planar fb's, etc.
+ */
+void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
+               struct omap_overlay_info *info)
 {
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-       return omap_fb->bo;
+       const struct format *format = omap_fb->format;
+       struct plane *plane = &omap_fb->planes[0];
+       unsigned int offset;
+
+       offset = plane->offset +
+                       (x * format->planes[0].stride_bpp) +
+                       (y * plane->pitch / format->planes[0].sub_y);
+
+       info->color_mode   = format->dss_format;
+       info->paddr        = plane->paddr + offset;
+       info->screen_width = plane->pitch / format->planes[0].stride_bpp;
+
+       if (format->dss_format == OMAP_DSS_COLOR_NV12) {
+               plane = &omap_fb->planes[1];
+               offset = plane->offset +
+                               (x * format->planes[1].stride_bpp) +
+                               (y * plane->pitch / format->planes[1].sub_y);
+               info->p_uv_addr = plane->paddr + offset;
+       } else {
+               info->p_uv_addr = 0;
+       }
+}
+
+struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
+{
+       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+       if (p >= drm_format_num_planes(omap_fb->format->pixel_format))
+               return NULL;
+       return omap_fb->planes[p].bo;
 }
 
 /* iterate thru all the connectors, returning ones that are attached
@@ -171,39 +250,57 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,
 }
 
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
-               struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd)
+               struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
 {
-       struct drm_gem_object *bo;
+       struct drm_gem_object *bos[4];
        struct drm_framebuffer *fb;
-       bo = drm_gem_object_lookup(dev, file, mode_cmd->handle);
-       if (!bo) {
-               return ERR_PTR(-ENOENT);
-       }
-       fb = omap_framebuffer_init(dev, mode_cmd, bo);
-       if (!fb) {
-               return ERR_PTR(-ENOMEM);
+       int ret;
+
+       ret = objects_lookup(dev, file, mode_cmd->pixel_format,
+                       bos, mode_cmd->handles);
+       if (ret)
+               return ERR_PTR(ret);
+
+       fb = omap_framebuffer_init(dev, mode_cmd, bos);
+       if (IS_ERR(fb)) {
+               int i, n = drm_format_num_planes(mode_cmd->pixel_format);
+               for (i = 0; i < n; i++)
+                       drm_gem_object_unreference_unlocked(bos[i]);
+               return fb;
        }
        return fb;
 }
 
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
-               struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo)
+               struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
 {
        struct omap_framebuffer *omap_fb;
        struct drm_framebuffer *fb = NULL;
-       int size, ret;
+       const struct format *format = NULL;
+       int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
 
-       DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%d)",
+       DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
                        dev, mode_cmd, mode_cmd->width, mode_cmd->height,
-                       mode_cmd->bpp);
+                       (char *)&mode_cmd->pixel_format);
+
+       for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               if (formats[i].pixel_format == mode_cmd->pixel_format) {
+                       format = &formats[i];
+                       break;
+               }
+       }
 
-       /* in case someone tries to feed us a completely bogus stride: */
-       mode_cmd->pitch = align_pitch(mode_cmd->pitch,
-                       mode_cmd->width, mode_cmd->bpp);
+       if (!format) {
+               dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
+                               (char *)&mode_cmd->pixel_format);
+               ret = -EINVAL;
+               goto fail;
+       }
 
        omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
        if (!omap_fb) {
                dev_err(dev->dev, "could not allocate fb\n");
+               ret = -ENOMEM;
                goto fail;
        }
 
@@ -216,19 +313,32 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 
        DBG("create: FB ID: %d (%p)", fb->base.id, fb);
 
-       size = PAGE_ALIGN(mode_cmd->pitch * mode_cmd->height);
+       omap_fb->format = format;
 
-       if (size > bo->size) {
-               dev_err(dev->dev, "provided buffer object is too small!\n");
-               goto fail;
-       }
+       for (i = 0; i < n; i++) {
+               struct plane *plane = &omap_fb->planes[i];
+               int size, pitch = mode_cmd->pitches[i];
+
+               if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) {
+                       dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
+                                       pitch, mode_cmd->width * format->planes[i].stride_bpp);
+                       ret = -EINVAL;
+                       goto fail;
+               }
 
-       omap_fb->bo = bo;
-       omap_fb->size = size;
+               size = pitch * mode_cmd->height / format->planes[i].sub_y;
 
-       if (omap_gem_get_paddr(bo, &omap_fb->paddr, true)) {
-               dev_err(dev->dev, "could not map (paddr)!\n");
-               goto fail;
+               if (size > (bos[i]->size - mode_cmd->offsets[i])) {
+                       dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
+                                       bos[i]->size - mode_cmd->offsets[i], size);
+                       ret = -EINVAL;
+                       goto fail;
+               }
+
+               plane->bo     = bos[i];
+               plane->offset = mode_cmd->offsets[i];
+               plane->pitch  = mode_cmd->pitches[i];
+               plane->paddr  = pitch;
        }
 
        drm_helper_mode_fill_fb_struct(fb, mode_cmd);
@@ -239,5 +349,5 @@ fail:
        if (fb) {
                omap_framebuffer_destroy(fb);
        }
-       return NULL;
+       return ERR_PTR(ret);
 }
index 093ae2f87b2084c87ff444cbdb6b95aa101381b0..96940bbfc6f433b833cc935e42f566f246e7c0d4 100644 (file)
@@ -129,10 +129,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
        struct drm_framebuffer *fb = NULL;
        union omap_gem_size gsize;
        struct fb_info *fbi = NULL;
-       struct drm_mode_fb_cmd mode_cmd = {0};
+       struct drm_mode_fb_cmd2 mode_cmd = {0};
        dma_addr_t paddr;
-       void __iomem *vaddr;
-       int size, screen_width;
        int ret;
 
        /* only doing ARGB32 since this is what is needed to alpha-blend
@@ -145,36 +143,56 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
                        sizes->surface_height, sizes->surface_bpp,
                        sizes->fb_width, sizes->fb_height);
 
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+                       sizes->surface_depth);
+
        mode_cmd.width = sizes->surface_width;
        mode_cmd.height = sizes->surface_height;
 
-       mode_cmd.bpp = sizes->surface_bpp;
-       mode_cmd.depth = sizes->surface_depth;
-
-       mode_cmd.pitch = align_pitch(
-                       mode_cmd.width * ((mode_cmd.bpp + 7) / 8),
-                       mode_cmd.width, mode_cmd.bpp);
+       mode_cmd.pitches[0] = align_pitch(
+                       mode_cmd.width * ((sizes->surface_bpp + 7) / 8),
+                       mode_cmd.width, sizes->surface_bpp);
 
        fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled;
        if (fbdev->ywrap_enabled) {
                /* need to align pitch to page size if using DMM scrolling */
-               mode_cmd.pitch = ALIGN(mode_cmd.pitch, PAGE_SIZE);
+               mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE);
        }
 
        /* allocate backing bo */
        gsize = (union omap_gem_size){
-               .bytes = PAGE_ALIGN(mode_cmd.pitch * mode_cmd.height),
+               .bytes = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height),
        };
        DBG("allocating %d bytes for fb %d", gsize.bytes, dev->primary->index);
        fbdev->bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);
        if (!fbdev->bo) {
                dev_err(dev->dev, "failed to allocate buffer object\n");
+               ret = -ENOMEM;
                goto fail;
        }
 
-       fb = omap_framebuffer_init(dev, &mode_cmd, fbdev->bo);
-       if (!fb) {
+       fb = omap_framebuffer_init(dev, &mode_cmd, &fbdev->bo);
+       if (IS_ERR(fb)) {
                dev_err(dev->dev, "failed to allocate fb\n");
+               /* note: if fb creation failed, we can't rely on fb destroy
+                * to unref the bo:
+                */
+               drm_gem_object_unreference(fbdev->bo);
+               ret = PTR_ERR(fb);
+               goto fail;
+       }
+
+       /* note: this keeps the bo pinned.. which is perhaps not ideal,
+        * but is needed as long as we use fb_mmap() to mmap to userspace
+        * (since this happens using fix.smem_start).  Possibly we could
+        * implement our own mmap using GEM mmap support to avoid this
+        * (non-tiled buffer doesn't need to be pinned for fbcon to write
+        * to it).  Then we just need to be sure that we are able to re-
+        * pin it in case of an opps.
+        */
+       ret = omap_gem_get_paddr(fbdev->bo, &paddr, true);
+       if (ret) {
+               dev_err(dev->dev, "could not map (paddr)!\n");
                ret = -ENOMEM;
                goto fail;
        }
@@ -206,18 +224,15 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
                goto fail_unlock;
        }
 
-       drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
+       drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
-       size = omap_framebuffer_get_buffer(fb, 0, 0,
-                       &vaddr, &paddr, &screen_width);
-
        dev->mode_config.fb_base = paddr;
 
-       fbi->screen_base = vaddr;
-       fbi->screen_size = size;
+       fbi->screen_base = omap_gem_vaddr(fbdev->bo);
+       fbi->screen_size = fbdev->bo->size;
        fbi->fix.smem_start = paddr;
-       fbi->fix.smem_len = size;
+       fbi->fix.smem_len = fbdev->bo->size;
 
        /* if we have DMM, then we can use it for scrolling by just
         * shuffling pages around in DMM rather than doing sw blit.
@@ -362,11 +377,11 @@ void omap_fbdev_free(struct drm_device *dev)
 
        fbdev = to_omap_fbdev(priv->fbdev);
 
-       kfree(fbdev);
-
        /* this will free the backing object */
        if (fbdev->fb)
                fbdev->fb->funcs->destroy(fbdev->fb);
 
+       kfree(fbdev);
+
        priv->fbdev = NULL;
 }
index e0ebd1d139f6c00e6f8f093c95e99cffdeacb171..b7d6f886c5cf7ca9d412cf5bf9dce0ac427e4f0b 100644 (file)
@@ -116,6 +116,9 @@ struct omap_gem_object {
        } *sync;
 };
 
+static int get_pages(struct drm_gem_object *obj, struct page ***pages);
+static uint64_t mmap_offset(struct drm_gem_object *obj);
+
 /* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are
  * not necessarily pinned in TILER all the time, and (b) when they are
  * they are not necessarily page aligned, we reserve one or more small
@@ -149,7 +152,7 @@ static void evict_entry(struct drm_gem_object *obj,
 {
        if (obj->dev->dev_mapping) {
                size_t size = PAGE_SIZE * usergart[fmt].height;
-               loff_t off = omap_gem_mmap_offset(obj) +
+               loff_t off = mmap_offset(obj) +
                                (entry->obj_pgoff << PAGE_SHIFT);
                unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);
        }
@@ -189,8 +192,6 @@ static inline bool is_shmem(struct drm_gem_object *obj)
        return obj->filp != NULL;
 }
 
-static int get_pages(struct drm_gem_object *obj, struct page ***pages);
-
 static DEFINE_SPINLOCK(sync_lock);
 
 /** ensure backing pages are allocated */
@@ -251,7 +252,7 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
 }
 
 /** get mmap offset */
-uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
+static uint64_t mmap_offset(struct drm_gem_object *obj)
 {
        if (!obj->map_list.map) {
                /* Make it mmapable */
@@ -267,6 +268,15 @@ uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
        return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
 }
 
+uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
+{
+       uint64_t offset;
+       mutex_lock(&obj->dev->struct_mutex);
+       offset = mmap_offset(obj);
+       mutex_unlock(&obj->dev->struct_mutex);
+       return offset;
+}
+
 /** get mmap size */
 size_t omap_gem_mmap_size(struct drm_gem_object *obj)
 {
@@ -1034,6 +1044,11 @@ void omap_gem_free_object(struct drm_gem_object *obj)
                drm_gem_free_mmap_offset(obj);
        }
 
+       /* this means the object is still pinned.. which really should
+        * not happen.  I think..
+        */
+       WARN_ON(omap_obj->paddr_cnt > 0);
+
        /* don't free externally allocated backing memory */
        if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) {
                if (omap_obj->pages) {
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
new file mode 100644 (file)
index 0000000..9790912
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * drivers/staging/omapdrm/omap_plane.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * 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/>.
+ */
+
+#include "omap_drv.h"
+
+/* some hackery because omapdss has an 'enum omap_plane' (which would be
+ * better named omap_plane_id).. and compiler seems unhappy about having
+ * both a 'struct omap_plane' and 'enum omap_plane'
+ */
+#define omap_plane _omap_plane
+
+/*
+ * plane funcs
+ */
+
+#define to_omap_plane(x) container_of(x, struct omap_plane, base)
+
+struct omap_plane {
+       struct drm_plane base;
+       struct omap_overlay *ovl;
+       struct omap_overlay_info info;
+
+       /* Source values, converted to integers because we don't support
+        * fractional positions:
+        */
+       unsigned int src_x, src_y;
+
+       /* last fb that we pinned: */
+       struct drm_framebuffer *pinned_fb;
+};
+
+
+/* push changes down to dss2 */
+static int commit(struct drm_plane *plane)
+{
+       struct drm_device *dev = plane->dev;
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       struct omap_overlay *ovl = omap_plane->ovl;
+       struct omap_overlay_info *info = &omap_plane->info;
+       int ret;
+
+       DBG("%s", ovl->name);
+       DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
+                       info->out_height, info->screen_width);
+       DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
+                       info->paddr, info->p_uv_addr);
+
+       /* NOTE: do we want to do this at all here, or just wait
+        * for dpms(ON) since other CRTC's may not have their mode
+        * set yet, so fb dimensions may still change..
+        */
+       ret = ovl->set_overlay_info(ovl, info);
+       if (ret) {
+               dev_err(dev->dev, "could not set overlay info\n");
+               return ret;
+       }
+
+       /* our encoder doesn't necessarily get a commit() after this, in
+        * particular in the dpms() and mode_set_base() cases, so force the
+        * manager to update:
+        *
+        * could this be in the encoder somehow?
+        */
+       if (ovl->manager) {
+               ret = ovl->manager->apply(ovl->manager);
+               if (ret) {
+                       dev_err(dev->dev, "could not apply settings\n");
+                       return ret;
+               }
+       }
+
+       if (ovl->is_enabled(ovl)) {
+               omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
+                               info->out_width, info->out_height);
+       }
+
+       return 0;
+}
+
+/* when CRTC that we are attached to has potentially changed, this checks
+ * if we are attached to proper manager, and if necessary updates.
+ */
+static void update_manager(struct drm_plane *plane)
+{
+       struct omap_drm_private *priv = plane->dev->dev_private;
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       struct omap_overlay *ovl = omap_plane->ovl;
+       struct omap_overlay_manager *mgr = NULL;
+       int i;
+
+       if (plane->crtc) {
+               for (i = 0; i < priv->num_encoders; i++) {
+                       struct drm_encoder *encoder = priv->encoders[i];
+                       if (encoder->crtc == plane->crtc) {
+                               mgr = omap_encoder_get_manager(encoder);
+                               break;
+                       }
+               }
+       }
+
+       if (ovl->manager != mgr) {
+               bool enabled = ovl->is_enabled(ovl);
+
+               /* don't switch things around with enabled overlays: */
+               if (enabled)
+                       omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+
+               if (ovl->manager) {
+                       DBG("disconnecting %s from %s", ovl->name,
+                                       ovl->manager->name);
+                       ovl->unset_manager(ovl);
+               }
+
+               if (mgr) {
+                       DBG("connecting %s to %s", ovl->name, mgr->name);
+                       ovl->set_manager(ovl, mgr);
+               }
+
+               if (enabled && mgr)
+                       omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+       }
+}
+
+/* update which fb (if any) is pinned for scanout */
+static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
+{
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       int ret = 0;
+
+       if (omap_plane->pinned_fb != fb) {
+               if (omap_plane->pinned_fb)
+                       omap_framebuffer_unpin(omap_plane->pinned_fb);
+               omap_plane->pinned_fb = fb;
+               if (fb)
+                       ret = omap_framebuffer_pin(fb);
+       }
+
+       return ret;
+}
+
+/* update parameters that are dependent on the framebuffer dimensions and
+ * position within the fb that this plane scans out from. This is called
+ * when framebuffer or x,y base may have changed.
+ */
+static void update_scanout(struct drm_plane *plane)
+{
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       struct omap_overlay_info *info = &omap_plane->info;
+       int ret;
+
+       ret = update_pin(plane, plane->fb);
+       if (ret) {
+               dev_err(plane->dev->dev,
+                       "could not pin fb: %d\n", ret);
+               omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+               return;
+       }
+
+       omap_framebuffer_update_scanout(plane->fb,
+                       omap_plane->src_x, omap_plane->src_y, info);
+
+       DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name,
+                       omap_plane->src_x, omap_plane->src_y,
+                       (u32)info->paddr, (u32)info->p_uv_addr,
+                       info->screen_width);
+}
+
+int omap_plane_mode_set(struct drm_plane *plane,
+               struct drm_crtc *crtc, struct drm_framebuffer *fb,
+               int crtc_x, int crtc_y,
+               unsigned int crtc_w, unsigned int crtc_h,
+               uint32_t src_x, uint32_t src_y,
+               uint32_t src_w, uint32_t src_h)
+{
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+
+       /* src values are in Q16 fixed point, convert to integer: */
+       src_x = src_x >> 16;
+       src_y = src_y >> 16;
+       src_w = src_w >> 16;
+       src_h = src_h >> 16;
+
+       omap_plane->info.pos_x = crtc_x;
+       omap_plane->info.pos_y = crtc_y;
+       omap_plane->info.out_width = crtc_w;
+       omap_plane->info.out_height = crtc_h;
+       omap_plane->info.width = src_w;
+       omap_plane->info.height = src_h;
+       omap_plane->src_x = src_x;
+       omap_plane->src_y = src_y;
+
+       /* note: this is done after this fxn returns.. but if we need
+        * to do a commit/update_scanout, etc before this returns we
+        * need the current value.
+        */
+       plane->fb = fb;
+       plane->crtc = crtc;
+
+       update_scanout(plane);
+       update_manager(plane);
+
+       return 0;
+}
+
+static int omap_plane_update(struct drm_plane *plane,
+               struct drm_crtc *crtc, struct drm_framebuffer *fb,
+               int crtc_x, int crtc_y,
+               unsigned int crtc_w, unsigned int crtc_h,
+               uint32_t src_x, uint32_t src_y,
+               uint32_t src_w, uint32_t src_h)
+{
+       omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h,
+                       src_x, src_y, src_w, src_h);
+       return omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+}
+
+static int omap_plane_disable(struct drm_plane *plane)
+{
+       return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+}
+
+static void omap_plane_destroy(struct drm_plane *plane)
+{
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       DBG("%s", omap_plane->ovl->name);
+       omap_plane_disable(plane);
+       drm_plane_cleanup(plane);
+       kfree(omap_plane);
+}
+
+int omap_plane_dpms(struct drm_plane *plane, int mode)
+{
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       struct omap_overlay *ovl = omap_plane->ovl;
+       int r;
+
+       DBG("%s: %d", omap_plane->ovl->name, mode);
+
+       if (mode == DRM_MODE_DPMS_ON) {
+               update_scanout(plane);
+               r = commit(plane);
+               if (!r)
+                       r = ovl->enable(ovl);
+       } else {
+               r = ovl->disable(ovl);
+               update_pin(plane, NULL);
+       }
+
+       return r;
+}
+
+static const struct drm_plane_funcs omap_plane_funcs = {
+               .update_plane = omap_plane_update,
+               .disable_plane = omap_plane_disable,
+               .destroy = omap_plane_destroy,
+};
+
+static const uint32_t formats[] = {
+               DRM_FORMAT_RGB565,
+               DRM_FORMAT_RGBX4444,
+               DRM_FORMAT_XRGB4444,
+               DRM_FORMAT_RGBA4444,
+               DRM_FORMAT_ABGR4444,
+               DRM_FORMAT_XRGB1555,
+               DRM_FORMAT_ARGB1555,
+               DRM_FORMAT_RGB888,
+               DRM_FORMAT_RGBX8888,
+               DRM_FORMAT_XRGB8888,
+               DRM_FORMAT_RGBA8888,
+               DRM_FORMAT_ARGB8888,
+               DRM_FORMAT_NV12,
+               DRM_FORMAT_YUYV,
+               DRM_FORMAT_UYVY,
+};
+
+/* initialize plane */
+struct drm_plane *omap_plane_init(struct drm_device *dev,
+               struct omap_overlay *ovl, unsigned int possible_crtcs,
+               bool priv)
+{
+       struct drm_plane *plane = NULL;
+       struct omap_plane *omap_plane;
+
+       DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name,
+                       possible_crtcs, priv);
+
+       omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
+       if (!omap_plane) {
+               dev_err(dev->dev, "could not allocate plane\n");
+               goto fail;
+       }
+
+       omap_plane->ovl = ovl;
+       plane = &omap_plane->base;
+
+       drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs,
+                       formats, ARRAY_SIZE(formats), priv);
+
+       /* get our starting configuration, set defaults for parameters
+        * we don't currently use, etc:
+        */
+       ovl->get_overlay_info(ovl, &omap_plane->info);
+       omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA;
+       omap_plane->info.rotation = OMAP_DSS_ROT_0;
+       omap_plane->info.global_alpha = 0xff;
+       omap_plane->info.mirror = 0;
+       omap_plane->info.mirror = 0;
+
+       /* Set defaults depending on whether we are a CRTC or overlay
+        * layer.
+        * TODO add ioctl to give userspace an API to change this.. this
+        * will come in a subsequent patch.
+        */
+       if (priv)
+               omap_plane->info.zorder = 0;
+       else
+               omap_plane->info.zorder = 1;
+
+       update_manager(plane);
+
+       return plane;
+
+fail:
+       if (plane) {
+               omap_plane_destroy(plane);
+       }
+       return NULL;
+}
index c324709aa9a1d9e346e9f80884ea0af86f7c82f4..ef6441447147399650399b39523dd31a0ab75b50 100644 (file)
  * pipes/overlays/CRTCs are used.. if this is not provided, then instead the
  * first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
  * one manager, with priority given to managers that are connected to
- * detected devices.  This should be a good default behavior for most cases,
- * but yet there still might be times when you wish to do something different.
+ * detected devices.  Remaining overlays are used as video planes.  This
+ * should be a good default behavior for most cases, but yet there still
+ * might be times when you wish to do something different.
  */
 struct omap_kms_platform_data {
+       /* overlays to use as CRTCs: */
        int ovl_cnt;
        const int *ovl_ids;
+
+       /* overlays to use as video planes: */
+       int pln_cnt;
+       const int *pln_ids;
+
        int mgr_cnt;
        const int *mgr_ids;
+
        int dev_cnt;
        const char **dev_names;
 };
diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig
deleted file mode 100644 (file)
index 8d53b1a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-config POHMELFS
-       tristate "POHMELFS filesystem support"
-       depends on NET
-       select CONNECTOR
-       select CRYPTO
-       select CRYPTO_BLKCIPHER
-       select CRYPTO_HMAC
-       help
-         POHMELFS stands for Parallel Optimized Host Message Exchange Layered
-         File System.  This is a network filesystem which supports coherent
-         caching of data and metadata on clients.
-
-config POHMELFS_DEBUG
-       bool "POHMELFS debugging"
-       depends on POHMELFS
-       default n
-       help
-         Turns on excessive POHMELFS debugging facilities.
-         You usually do not want to slow things down noticeably and get really
-         lots of kernel messages in syslog.
diff --git a/drivers/staging/pohmelfs/Makefile b/drivers/staging/pohmelfs/Makefile
deleted file mode 100644 (file)
index 196561c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_POHMELFS) += pohmelfs.o
-
-pohmelfs-y := inode.o config.o dir.o net.o path_entry.o trans.o crypto.o lock.o mcache.o
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
deleted file mode 100644 (file)
index b6c42cb..0000000
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/connector.h>
-#include <linux/crypto.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-
-#include "netfs.h"
-
-/*
- * Global configuration list.
- * Each client can be asked to get one of them.
- *
- * Allows to provide remote server address (ipv4/v6/whatever), port
- * and so on via kernel connector.
- */
-
-static struct cb_id pohmelfs_cn_id = {.idx = POHMELFS_CN_IDX, .val = POHMELFS_CN_VAL};
-static LIST_HEAD(pohmelfs_config_list);
-static DEFINE_MUTEX(pohmelfs_config_lock);
-
-static inline int pohmelfs_config_eql(struct pohmelfs_ctl *sc, struct pohmelfs_ctl *ctl)
-{
-       if (sc->idx == ctl->idx && sc->type == ctl->type &&
-                       sc->proto == ctl->proto &&
-                       sc->addrlen == ctl->addrlen &&
-                       !memcmp(&sc->addr, &ctl->addr, ctl->addrlen))
-               return 1;
-
-       return 0;
-}
-
-static struct pohmelfs_config_group *pohmelfs_find_config_group(unsigned int idx)
-{
-       struct pohmelfs_config_group *g, *group = NULL;
-
-       list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
-               if (g->idx == idx) {
-                       group = g;
-                       break;
-               }
-       }
-
-       return group;
-}
-
-static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned int idx)
-{
-       struct pohmelfs_config_group *g;
-
-       g = pohmelfs_find_config_group(idx);
-       if (g)
-               return g;
-
-       g = kzalloc(sizeof(struct pohmelfs_config_group), GFP_KERNEL);
-       if (!g)
-               return NULL;
-
-       INIT_LIST_HEAD(&g->config_list);
-       g->idx = idx;
-       g->num_entry = 0;
-
-       list_add_tail(&g->group_entry, &pohmelfs_config_list);
-
-       return g;
-}
-
-static inline void pohmelfs_insert_config_entry(struct pohmelfs_sb *psb, struct pohmelfs_config *dst)
-{
-       struct pohmelfs_config *tmp;
-
-       INIT_LIST_HEAD(&dst->config_entry);
-
-       list_for_each_entry(tmp, &psb->state_list, config_entry) {
-               if (dst->state.ctl.prio > tmp->state.ctl.prio)
-                       list_add_tail(&dst->config_entry, &tmp->config_entry);
-       }
-       if (list_empty(&dst->config_entry))
-               list_add_tail(&dst->config_entry, &psb->state_list);
-}
-
-static int pohmelfs_move_config_entry(struct pohmelfs_sb *psb,
-               struct pohmelfs_config *dst, struct pohmelfs_config *new)
-{
-       if ((dst->state.ctl.prio == new->state.ctl.prio) &&
-               (dst->state.ctl.perm == new->state.ctl.perm))
-               return 0;
-
-       dprintk("%s: dst: prio: %d, perm: %x, new: prio: %d, perm: %d.\n",
-                       __func__, dst->state.ctl.prio, dst->state.ctl.perm,
-                       new->state.ctl.prio, new->state.ctl.perm);
-       dst->state.ctl.prio = new->state.ctl.prio;
-       dst->state.ctl.perm = new->state.ctl.perm;
-
-       list_del_init(&dst->config_entry);
-       pohmelfs_insert_config_entry(psb, dst);
-       return 0;
-}
-
-/*
- * pohmelfs_copy_config() is used to copy new state configs from the
- * config group (controlled by the netlink messages) into the superblock.
- * This happens either at startup time where no transactions can access
- * the list of the configs (and thus list of the network states), or at
- * run-time, where it is protected by the psb->state_lock.
- */
-int pohmelfs_copy_config(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_config *c, *dst;
-       int err = -ENODEV;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_config_group(psb->idx);
-       if (!g)
-               goto out_unlock;
-
-       /*
-        * Run over all entries in given config group and try to create and
-        * initialize those, which do not exist in superblock list.
-        * Skip all existing entries.
-        */
-
-       list_for_each_entry(c, &g->config_list, config_entry) {
-               err = 0;
-               list_for_each_entry(dst, &psb->state_list, config_entry) {
-                       if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) {
-                               err = pohmelfs_move_config_entry(psb, dst, c);
-                               if (!err)
-                                       err = -EEXIST;
-                               break;
-                       }
-               }
-
-               if (err)
-                       continue;
-
-               dst = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
-               if (!dst) {
-                       err = -ENOMEM;
-                       break;
-               }
-
-               memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl));
-
-               pohmelfs_insert_config_entry(psb, dst);
-
-               err = pohmelfs_state_init_one(psb, dst);
-               if (err) {
-                       list_del(&dst->config_entry);
-                       kfree(dst);
-               }
-
-               err = 0;
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-
-       return err;
-}
-
-int pohmelfs_copy_crypto(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config_group *g;
-       int err = -ENOENT;
-
-       mutex_lock(&pohmelfs_config_lock);
-       g = pohmelfs_find_config_group(psb->idx);
-       if (!g)
-               goto err_out_exit;
-
-       if (g->hash_string) {
-               err = -ENOMEM;
-               psb->hash_string = kstrdup(g->hash_string, GFP_KERNEL);
-               if (!psb->hash_string)
-                       goto err_out_exit;
-               psb->hash_strlen = g->hash_strlen;
-       }
-
-       if (g->cipher_string) {
-               psb->cipher_string = kstrdup(g->cipher_string, GFP_KERNEL);
-               if (!psb->cipher_string)
-                       goto err_out_free_hash_string;
-               psb->cipher_strlen = g->cipher_strlen;
-       }
-
-       if (g->hash_keysize) {
-               psb->hash_key = kmemdup(g->hash_key, g->hash_keysize,
-                                       GFP_KERNEL);
-               if (!psb->hash_key)
-                       goto err_out_free_cipher_string;
-               psb->hash_keysize = g->hash_keysize;
-       }
-
-       if (g->cipher_keysize) {
-               psb->cipher_key = kmemdup(g->cipher_key, g->cipher_keysize,
-                                         GFP_KERNEL);
-               if (!psb->cipher_key)
-                       goto err_out_free_hash;
-               psb->cipher_keysize = g->cipher_keysize;
-       }
-
-       mutex_unlock(&pohmelfs_config_lock);
-
-       return 0;
-
-err_out_free_hash:
-       kfree(psb->hash_key);
-err_out_free_cipher_string:
-       kfree(psb->cipher_string);
-err_out_free_hash_string:
-       kfree(psb->hash_string);
-err_out_exit:
-       mutex_unlock(&pohmelfs_config_lock);
-       return err;
-}
-
-static int pohmelfs_send_reply(int err, int msg_num, int action, struct cn_msg *msg, struct pohmelfs_ctl *ctl)
-{
-       struct pohmelfs_cn_ack *ack;
-
-       ack = kzalloc(sizeof(struct pohmelfs_cn_ack), GFP_KERNEL);
-       if (!ack)
-               return -ENOMEM;
-
-       memcpy(&ack->msg, msg, sizeof(struct cn_msg));
-
-       if (action == POHMELFS_CTLINFO_ACK)
-               memcpy(&ack->ctl, ctl, sizeof(struct pohmelfs_ctl));
-
-       ack->msg.len = sizeof(struct pohmelfs_cn_ack) - sizeof(struct cn_msg);
-       ack->msg.ack = msg->ack + 1;
-       ack->error = err;
-       ack->msg_num = msg_num;
-
-       cn_netlink_send(&ack->msg, 0, GFP_KERNEL);
-       kfree(ack);
-       return 0;
-}
-
-static int pohmelfs_cn_disp(struct cn_msg *msg)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0, i = 1;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_config_group(ctl->idx);
-       if (!g) {
-               pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL);
-               goto out_unlock;
-       }
-
-       list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-               struct pohmelfs_ctl *sc = &c->state.ctl;
-               if (pohmelfs_send_reply(err, g->num_entry - i, POHMELFS_CTLINFO_ACK, msg, sc)) {
-                       err = -ENOMEM;
-                       goto out_unlock;
-               }
-               i += 1;
-       }
-
- out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       return err;
-}
-
-static int pohmelfs_cn_dump(struct cn_msg *msg)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0, i = 1;
-       int total_msg = 0;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       list_for_each_entry(g, &pohmelfs_config_list, group_entry)
-               total_msg += g->num_entry;
-       if (total_msg == 0) {
-               if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
-                       err = -ENOMEM;
-               goto out_unlock;
-       }
-
-       list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
-               list_for_each_entry_safe(c, tmp, &g->config_list,
-                                        config_entry) {
-                       struct pohmelfs_ctl *sc = &c->state.ctl;
-                       if (pohmelfs_send_reply(err, total_msg - i,
-                                               POHMELFS_CTLINFO_ACK, msg,
-                                               sc)) {
-                               err = -ENOMEM;
-                               goto out_unlock;
-                       }
-                       i += 1;
-               }
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       return err;
-}
-
-static int pohmelfs_cn_flush(struct cn_msg *msg)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       if (ctl->idx != POHMELFS_NULL_IDX) {
-               g = pohmelfs_find_config_group(ctl->idx);
-
-               if (!g)
-                       goto out_unlock;
-
-               list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-                       list_del(&c->config_entry);
-                       g->num_entry--;
-                       kfree(c);
-               }
-       } else {
-               list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
-                       list_for_each_entry_safe(c, tmp, &g->config_list,
-                                                config_entry) {
-                               list_del(&c->config_entry);
-                               g->num_entry--;
-                               kfree(c);
-                       }
-               }
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       pohmelfs_cn_dump(msg);
-
-       return err;
-}
-
-static int pohmelfs_modify_config(struct pohmelfs_ctl *old, struct pohmelfs_ctl *new)
-{
-       old->perm = new->perm;
-       old->prio = new->prio;
-       return 0;
-}
-
-static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_create_config_group(ctl->idx);
-       if (!g) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
-
-       list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-               struct pohmelfs_ctl *sc = &c->state.ctl;
-
-               if (pohmelfs_config_eql(sc, ctl)) {
-                       if (action == POHMELFS_FLAGS_ADD) {
-                               err = -EEXIST;
-                               goto out_unlock;
-                       } else if (action == POHMELFS_FLAGS_DEL) {
-                               list_del(&c->config_entry);
-                               g->num_entry--;
-                               kfree(c);
-                               goto out_unlock;
-                       } else if (action == POHMELFS_FLAGS_MODIFY) {
-                               err = pohmelfs_modify_config(sc, ctl);
-                               goto out_unlock;
-                       } else {
-                               err = -EEXIST;
-                               goto out_unlock;
-                       }
-               }
-       }
-       if (action == POHMELFS_FLAGS_DEL) {
-               err = -EBADMSG;
-               goto out_unlock;
-       }
-
-       c = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
-       if (!c) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
-       memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl));
-       g->num_entry++;
-
-       list_add_tail(&c->config_entry, &g->config_list);
-
- out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
-               err = -ENOMEM;
-
-       return err;
-}
-
-static int pohmelfs_crypto_hash_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
-{
-       char *algo = (char *)c->data;
-       u8 *key = (u8 *)(algo + c->strlen);
-
-       if (g->hash_string)
-               return -EEXIST;
-
-       g->hash_string = kstrdup(algo, GFP_KERNEL);
-       if (!g->hash_string)
-               return -ENOMEM;
-       g->hash_strlen = c->strlen;
-       g->hash_keysize = c->keysize;
-
-       g->hash_key = kmemdup(key, c->keysize, GFP_KERNEL);
-       if (!g->hash_key) {
-               kfree(g->hash_string);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int pohmelfs_crypto_cipher_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
-{
-       char *algo = (char *)c->data;
-       u8 *key = (u8 *)(algo + c->strlen);
-
-       if (g->cipher_string)
-               return -EEXIST;
-
-       g->cipher_string = kstrdup(algo, GFP_KERNEL);
-       if (!g->cipher_string)
-               return -ENOMEM;
-       g->cipher_strlen = c->strlen;
-       g->cipher_keysize = c->keysize;
-
-       g->cipher_key = kmemdup(key, c->keysize, GFP_KERNEL);
-       if (!g->cipher_key) {
-               kfree(g->cipher_string);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int pohmelfs_cn_crypto(struct cn_msg *msg)
-{
-       struct pohmelfs_crypto *crypto = (struct pohmelfs_crypto *)msg->data;
-       struct pohmelfs_config_group *g;
-       int err = 0;
-
-       dprintk("%s: idx: %u, strlen: %u, type: %u, keysize: %u, algo: %s.\n",
-                       __func__, crypto->idx, crypto->strlen, crypto->type,
-                       crypto->keysize, (char *)crypto->data);
-
-       mutex_lock(&pohmelfs_config_lock);
-       g = pohmelfs_find_create_config_group(crypto->idx);
-       if (!g) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
-
-       switch (crypto->type) {
-       case POHMELFS_CRYPTO_HASH:
-                       err = pohmelfs_crypto_hash_init(g, crypto);
-                       break;
-       case POHMELFS_CRYPTO_CIPHER:
-                       err = pohmelfs_crypto_cipher_init(g, crypto);
-                       break;
-       default:
-                       err = -ENOTSUPP;
-                       break;
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
-               err = -ENOMEM;
-
-       return err;
-}
-
-static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-       int err;
-
-       if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
-               return;
-
-       switch (msg->flags) {
-       case POHMELFS_FLAGS_ADD:
-       case POHMELFS_FLAGS_DEL:
-       case POHMELFS_FLAGS_MODIFY:
-                       err = pohmelfs_cn_ctl(msg, msg->flags);
-                       break;
-       case POHMELFS_FLAGS_FLUSH:
-                       err = pohmelfs_cn_flush(msg);
-                       break;
-       case POHMELFS_FLAGS_SHOW:
-                       err = pohmelfs_cn_disp(msg);
-                       break;
-       case POHMELFS_FLAGS_DUMP:
-                       err = pohmelfs_cn_dump(msg);
-                       break;
-       case POHMELFS_FLAGS_CRYPTO:
-                       err = pohmelfs_cn_crypto(msg);
-                       break;
-       default:
-                       err = -ENOSYS;
-                       break;
-       }
-}
-
-int pohmelfs_config_check(struct pohmelfs_config *config, int idx)
-{
-       struct pohmelfs_ctl *ctl = &config->state.ctl;
-       struct pohmelfs_config *tmp;
-       int err = -ENOENT;
-       struct pohmelfs_ctl *sc;
-       struct pohmelfs_config_group *g;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_config_group(ctl->idx);
-       if (g) {
-               list_for_each_entry(tmp, &g->config_list, config_entry) {
-                       sc = &tmp->state.ctl;
-
-                       if (pohmelfs_config_eql(sc, ctl)) {
-                               err = 0;
-                               break;
-                       }
-               }
-       }
-
-       mutex_unlock(&pohmelfs_config_lock);
-
-       return err;
-}
-
-int __init pohmelfs_config_init(void)
-{
-       /* XXX remove (void *) cast when vanilla connector got synced */
-       return cn_add_callback(&pohmelfs_cn_id, "pohmelfs", (void *)pohmelfs_cn_callback);
-}
-
-void pohmelfs_config_exit(void)
-{
-       struct pohmelfs_config *c, *tmp;
-       struct pohmelfs_config_group *g, *gtmp;
-
-       cn_del_callback(&pohmelfs_cn_id);
-
-       mutex_lock(&pohmelfs_config_lock);
-       list_for_each_entry_safe(g, gtmp, &pohmelfs_config_list, group_entry) {
-               list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-                       list_del(&c->config_entry);
-                       kfree(c);
-               }
-
-               list_del(&g->group_entry);
-
-               kfree(g->hash_string);
-
-               kfree(g->cipher_string);
-
-               kfree(g);
-       }
-       mutex_unlock(&pohmelfs_config_lock);
-}
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
deleted file mode 100644 (file)
index ad92771..0000000
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/crypto.h>
-#include <linux/highmem.h>
-#include <linux/kthread.h>
-#include <linux/pagemap.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-
-#include "netfs.h"
-
-static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb)
-{
-       int err;
-       struct crypto_hash *hash;
-
-       hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hash)) {
-               err = PTR_ERR(hash);
-               dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n",
-                               __func__, psb->idx, psb->hash_string, err);
-               goto err_out_exit;
-       }
-
-       psb->crypto_attached_size = crypto_hash_digestsize(hash);
-
-       if (!psb->hash_keysize)
-               return hash;
-
-       err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize);
-       if (err) {
-               dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n",
-                               __func__, psb->idx, psb->hash_string, err);
-               goto err_out_free;
-       }
-
-       return hash;
-
-err_out_free:
-       crypto_free_hash(hash);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb)
-{
-       int err = -EINVAL;
-       struct crypto_ablkcipher *cipher;
-
-       if (!psb->cipher_keysize)
-               goto err_out_exit;
-
-       cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0);
-       if (IS_ERR(cipher)) {
-               err = PTR_ERR(cipher);
-               dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n",
-                               __func__, psb->idx, psb->cipher_string, err);
-               goto err_out_exit;
-       }
-
-       crypto_ablkcipher_clear_flags(cipher, ~0);
-
-       err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize);
-       if (err) {
-               dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n",
-                               __func__, psb->idx, psb->cipher_string, err);
-               goto err_out_free;
-       }
-
-       return cipher;
-
-err_out_free:
-       crypto_free_ablkcipher(cipher);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
-{
-       int err;
-
-       e->page_num = 0;
-
-       e->size = PAGE_SIZE;
-       e->data = kmalloc(e->size, GFP_KERNEL);
-       if (!e->data) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       if (psb->hash_string) {
-               e->hash = pohmelfs_init_hash(psb);
-               if (IS_ERR(e->hash)) {
-                       err = PTR_ERR(e->hash);
-                       e->hash = NULL;
-                       goto err_out_free;
-               }
-       }
-
-       if (psb->cipher_string) {
-               e->cipher = pohmelfs_init_cipher(psb);
-               if (IS_ERR(e->cipher)) {
-                       err = PTR_ERR(e->cipher);
-                       e->cipher = NULL;
-                       goto err_out_free_hash;
-               }
-       }
-
-       return 0;
-
-err_out_free_hash:
-       crypto_free_hash(e->hash);
-err_out_free:
-       kfree(e->data);
-err_out_exit:
-       return err;
-}
-
-void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e)
-{
-       crypto_free_hash(e->hash);
-       crypto_free_ablkcipher(e->cipher);
-       kfree(e->data);
-}
-
-static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err)
-{
-       struct pohmelfs_crypto_completion *c = req->data;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
-       c->error = err;
-       complete(&c->complete);
-}
-
-static int pohmelfs_crypto_process(struct ablkcipher_request *req,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src,
-               void *iv, int enc, unsigned long timeout)
-{
-       struct pohmelfs_crypto_completion complete;
-       int err;
-
-       init_completion(&complete.complete);
-       complete.error = -EINPROGRESS;
-
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       pohmelfs_crypto_complete, &complete);
-
-       ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
-
-       if (enc)
-               err = crypto_ablkcipher_encrypt(req);
-       else
-               err = crypto_ablkcipher_decrypt(req);
-
-       switch (err) {
-       case -EINPROGRESS:
-       case -EBUSY:
-               err = wait_for_completion_interruptible_timeout(&complete.complete,
-                                       timeout);
-               if (!err)
-                       err = -ETIMEDOUT;
-               else if (err > 0)
-                       err = complete.error;
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv,
-               void *data, struct page *page, unsigned int size)
-{
-       int err;
-       struct scatterlist sg;
-
-       if (!e->cipher && !e->hash)
-               return 0;
-
-       dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n",
-               __func__, e, cmd_iv, data, page, (page) ? page->index : 0, size);
-
-       if (data) {
-               sg_init_one(&sg, data, size);
-       } else {
-               sg_init_table(&sg, 1);
-               sg_set_page(&sg, page, size, 0);
-       }
-
-       if (e->cipher) {
-               struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash);
-               u8 iv[32];
-
-               memset(iv, 0, sizeof(iv));
-               memcpy(iv, &cmd_iv, sizeof(cmd_iv));
-
-               ablkcipher_request_set_tfm(req, e->cipher);
-
-               err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       if (e->hash) {
-               struct hash_desc desc;
-               void *dst = e->data + e->size/2;
-
-               desc.tfm = e->hash;
-               desc.flags = 0;
-
-               err = crypto_hash_init(&desc);
-               if (err)
-                       goto err_out_exit;
-
-               err = crypto_hash_update(&desc, &sg, size);
-               if (err)
-                       goto err_out_exit;
-
-               err = crypto_hash_final(&desc, dst);
-               if (err)
-                       goto err_out_exit;
-
-               err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash));
-
-               if (err) {
-#ifdef CONFIG_POHMELFS_DEBUG
-                       unsigned int i;
-                       unsigned char *recv = e->data, *calc = dst;
-
-                       dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ",
-                                       __func__, e, e->hash, e->cipher, cmd_iv);
-                       for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) {
-#if 0
-                               dprintka("%02x ", recv[i]);
-                               if (recv[i] != calc[i]) {
-                                       dprintka("| calc byte: %02x.\n", calc[i]);
-                                       break;
-                               }
-#else
-                               dprintka("%02x/%02x ", recv[i], calc[i]);
-#endif
-                       }
-                       dprintk("\n");
-#endif
-                       goto err_out_exit;
-               } else {
-                       dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n",
-                                       __func__, e, e->hash, e->cipher);
-               }
-       }
-
-       dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n",
-                       __func__, e, e->size, e->hash, e->cipher);
-
-       return 0;
-
-err_out_exit:
-       dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n",
-                       __func__, e, e->hash, e->cipher, err);
-       return err;
-}
-
-static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e,
-               int (*iterator) (struct pohmelfs_crypto_engine *e,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src))
-{
-       void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size;
-       unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size;
-       struct netfs_cmd *cmd = data;
-       unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx;
-       struct scatterlist sg_src, sg_dst;
-       int err;
-
-       while (size) {
-               cmd = data;
-               cmd_cmd = __be16_to_cpu(cmd->cmd);
-               csize = __be32_to_cpu(cmd->size);
-               cmd->iv = __cpu_to_be64(e->iv);
-
-               if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE)
-                       csize = __be16_to_cpu(cmd->ext);
-
-               sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd);
-
-               dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n",
-                               __func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad));
-
-               data += sz;
-               size -= sz;
-
-               sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd));
-               sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd));
-
-               err = iterator(e, &sg_dst, &sg_src);
-               if (err)
-                       return err;
-       }
-
-       if (!pages)
-               return 0;
-
-       dpage_idx = 0;
-       for (i = 0; i < t->page_num; ++i) {
-               struct page *page = t->pages[i];
-               struct page *dpage = e->pages[dpage_idx];
-
-               if (!page)
-                       continue;
-
-               sg_init_table(&sg_src, 1);
-               sg_init_table(&sg_dst, 1);
-               sg_set_page(&sg_src, page, page_private(page), 0);
-               sg_set_page(&sg_dst, dpage, page_private(page), 0);
-
-               err = iterator(e, &sg_dst, &sg_src);
-               if (err)
-                       return err;
-
-               pages--;
-               if (!pages)
-                       break;
-               dpage_idx++;
-       }
-
-       return 0;
-}
-
-static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       struct ablkcipher_request *req = e->data;
-       u8 iv[32];
-
-       memset(iv, 0, sizeof(iv));
-
-       memcpy(iv, &e->iv, sizeof(e->iv));
-
-       return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout);
-}
-
-static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc)
-{
-       struct netfs_trans *t = tc->trans;
-       struct pohmelfs_crypto_engine *e = &tc->eng;
-       struct ablkcipher_request *req = e->data;
-
-       memset(req, 0, sizeof(struct ablkcipher_request));
-       ablkcipher_request_set_tfm(req, e->cipher);
-
-       e->iv = pohmelfs_gen_iv(t);
-
-       return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator);
-}
-
-static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       return crypto_hash_update(e->data, sg_src, sg_src->length);
-}
-
-static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc)
-{
-       struct pohmelfs_crypto_engine *e = &tc->eng;
-       struct hash_desc *desc = e->data;
-       unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd);
-       int err;
-
-       desc->tfm = e->hash;
-       desc->flags = 0;
-
-       err = crypto_hash_init(desc);
-       if (err)
-               return err;
-
-       err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator);
-       if (err)
-               return err;
-
-       err = crypto_hash_final(desc, dst);
-       if (err)
-               return err;
-
-       {
-               unsigned int i;
-               dprintk("%s: ", __func__);
-               for (i = 0; i < tc->psb->crypto_attached_size; ++i)
-                       dprintka("%02x ", dst[i]);
-               dprintka("\n");
-       }
-
-       return 0;
-}
-
-static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e)
-{
-       unsigned int i;
-
-       for (i = 0; i < e->page_num; ++i)
-               __free_page(e->pages[i]);
-       kfree(e->pages);
-}
-
-static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
-{
-       unsigned int i;
-
-       e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL);
-       if (!e->pages)
-               return -ENOMEM;
-
-       for (i = 0; i < psb->trans_max_pages; ++i) {
-               e->pages[i] = alloc_page(GFP_KERNEL);
-               if (!e->pages[i])
-                       break;
-       }
-
-       e->page_num = i;
-       if (!e->page_num)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       kfree(e->pages);
-       return -ENOMEM;
-}
-
-static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t)
-{
-       struct pohmelfs_sb *psb = t->psb;
-
-       if (t->thread)
-               kthread_stop(t->thread);
-
-       mutex_lock(&psb->crypto_thread_lock);
-       list_del(&t->thread_entry);
-       psb->crypto_thread_num--;
-       mutex_unlock(&psb->crypto_thread_lock);
-
-       pohmelfs_crypto_engine_exit(&t->eng);
-       pohmelfs_crypto_pages_free(&t->eng);
-       kfree(t);
-}
-
-static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err)
-{
-       struct netfs_cmd *cmd = t->iovec.iov_base;
-       netfs_convert_cmd(cmd);
-
-       if (likely(!err))
-               err = netfs_trans_finish_send(t, psb);
-
-       t->result = err;
-       netfs_trans_put(t);
-
-       return err;
-}
-
-void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th)
-{
-       struct pohmelfs_sb *psb = th->psb;
-
-       th->page = NULL;
-       th->trans = NULL;
-
-       mutex_lock(&psb->crypto_thread_lock);
-       list_move_tail(&th->thread_entry, &psb->crypto_ready_list);
-       mutex_unlock(&psb->crypto_thread_lock);
-       wake_up(&psb->wait);
-}
-
-static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t)
-{
-       struct netfs_trans *trans;
-       int err = 0;
-
-       trans = t->trans;
-       trans->eng = NULL;
-
-       if (t->eng.hash) {
-               err = pohmelfs_hash(t);
-               if (err)
-                       goto out_complete;
-       }
-
-       if (t->eng.cipher) {
-               err = pohmelfs_encrypt(t);
-               if (err)
-                       goto out_complete;
-               trans->eng = &t->eng;
-       }
-
-out_complete:
-       t->page = NULL;
-       t->trans = NULL;
-
-       if (!trans->eng)
-               pohmelfs_crypto_thread_make_ready(t);
-
-       pohmelfs_crypto_finish(trans, t->psb, err);
-       return err;
-}
-
-static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t)
-{
-       struct pohmelfs_crypto_engine *e = &t->eng;
-       struct page *page = t->page;
-       int err;
-
-       WARN_ON(!PageChecked(page));
-
-       err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size);
-       if (!err)
-               SetPageUptodate(page);
-       else
-               SetPageError(page);
-       unlock_page(page);
-       page_cache_release(page);
-
-       pohmelfs_crypto_thread_make_ready(t);
-
-       return err;
-}
-
-static int pohmelfs_crypto_thread_func(void *data)
-{
-       struct pohmelfs_crypto_thread *t = data;
-
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(t->wait, kthread_should_stop() ||
-                               t->trans || t->page);
-
-               if (kthread_should_stop())
-                       break;
-
-               if (!t->trans && !t->page)
-                       continue;
-
-               dprintk("%s: thread: %p, trans: %p, page: %p.\n",
-                               __func__, t, t->trans, t->page);
-
-               if (t->trans)
-                       pohmelfs_crypto_thread_trans(t);
-               else if (t->page)
-                       pohmelfs_crypto_thread_page(t);
-       }
-
-       return 0;
-}
-
-static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head)
-{
-       while (!list_empty(head)) {
-               struct pohmelfs_crypto_thread *t = NULL;
-
-               mutex_lock(&psb->crypto_thread_lock);
-               if (!list_empty(head)) {
-                       t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry);
-                       list_del_init(&t->thread_entry);
-               }
-               mutex_unlock(&psb->crypto_thread_lock);
-
-               if (t)
-                       pohmelfs_sys_crypto_exit_one(t);
-       }
-}
-
-static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb)
-{
-       while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) {
-               dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num);
-               pohmelfs_crypto_flush(psb, &psb->crypto_active_list);
-               pohmelfs_crypto_flush(psb, &psb->crypto_ready_list);
-       }
-}
-
-static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb)
-{
-       unsigned int i;
-       struct pohmelfs_crypto_thread *t;
-       struct pohmelfs_config *c;
-       struct netfs_state *st;
-       int err;
-
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               err = pohmelfs_crypto_engine_init(&st->eng, psb);
-               if (err)
-                       goto err_out_exit;
-
-               dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n",
-                               __func__, st, &st->eng, &st->eng.hash, &st->eng.cipher);
-       }
-
-       for (i = 0; i < psb->crypto_thread_num; ++i) {
-               err = -ENOMEM;
-               t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL);
-               if (!t)
-                       goto err_out_free_state_engines;
-
-               init_waitqueue_head(&t->wait);
-
-               t->psb = psb;
-               t->trans = NULL;
-               t->eng.thread = t;
-
-               err = pohmelfs_crypto_engine_init(&t->eng, psb);
-               if (err)
-                       goto err_out_free_state_engines;
-
-               err = pohmelfs_crypto_pages_alloc(&t->eng, psb);
-               if (err)
-                       goto err_out_free;
-
-               t->thread = kthread_run(pohmelfs_crypto_thread_func, t,
-                               "pohmelfs-crypto-%d-%d", psb->idx, i);
-               if (IS_ERR(t->thread)) {
-                       err = PTR_ERR(t->thread);
-                       t->thread = NULL;
-                       goto err_out_free;
-               }
-
-               if (t->eng.cipher)
-                       psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher);
-
-               mutex_lock(&psb->crypto_thread_lock);
-               list_add_tail(&t->thread_entry, &psb->crypto_ready_list);
-               mutex_unlock(&psb->crypto_thread_lock);
-       }
-
-       psb->crypto_thread_num = i;
-       return 0;
-
-err_out_free:
-       pohmelfs_sys_crypto_exit_one(t);
-err_out_free_state_engines:
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-               pohmelfs_crypto_engine_exit(&st->eng);
-       }
-err_out_exit:
-       pohmelfs_sys_crypto_exit(psb);
-       return err;
-}
-
-void pohmelfs_crypto_exit(struct pohmelfs_sb *psb)
-{
-       pohmelfs_sys_crypto_exit(psb);
-
-       kfree(psb->hash_string);
-       kfree(psb->cipher_string);
-}
-
-static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct pohmelfs_sb *psb = private;
-
-       psb->flags = -err;
-       dprintk("%s: err: %d.\n", __func__, err);
-
-       wake_up(&psb->wait);
-
-       return err;
-}
-
-static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb)
-{
-       struct netfs_trans *t;
-       struct netfs_crypto_capabilities *cap;
-       struct netfs_cmd *cmd;
-       char *str;
-       int err = -ENOMEM, size;
-
-       size = sizeof(struct netfs_crypto_capabilities) +
-               psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */
-
-       t = netfs_trans_alloc(psb, size, 0, 0);
-       if (!t)
-               goto err_out_exit;
-
-       t->complete = pohmelfs_crypt_init_complete;
-       t->private = psb;
-
-       cmd = netfs_trans_current(t);
-       cap = (struct netfs_crypto_capabilities *)(cmd + 1);
-       str = (char *)(cap + 1);
-
-       cmd->cmd = NETFS_CAPABILITIES;
-       cmd->id = POHMELFS_CRYPTO_CAPABILITIES;
-       cmd->size = size;
-       cmd->start = 0;
-       cmd->ext = 0;
-       cmd->csize = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, size);
-
-       cap->hash_strlen = psb->hash_strlen;
-       if (cap->hash_strlen) {
-               sprintf(str, "%s", psb->hash_string);
-               str += cap->hash_strlen;
-       }
-
-       cap->cipher_strlen = psb->cipher_strlen;
-       cap->cipher_keysize = psb->cipher_keysize;
-       if (cap->cipher_strlen)
-               sprintf(str, "%s", psb->cipher_string);
-
-       netfs_convert_crypto_capabilities(cap);
-
-       psb->flags = ~0;
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_exit;
-
-       err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0),
-                       psb->wait_on_page_timeout);
-       if (!err)
-               err = -ETIMEDOUT;
-       else if (err > 0)
-               err = -psb->flags;
-
-       if (!err)
-               psb->perform_crypto = 1;
-       psb->flags = 0;
-
-       /*
-        * At this point NETFS_CAPABILITIES response command
-        * should setup superblock in a way, which is acceptable
-        * for both client and server, so if server refuses connection,
-        * it will send error in transaction response.
-        */
-
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-int pohmelfs_crypto_init(struct pohmelfs_sb *psb)
-{
-       int err;
-
-       if (!psb->cipher_string && !psb->hash_string)
-               return 0;
-
-       err = pohmelfs_crypto_init_handshake(psb);
-       if (err)
-               return err;
-
-       err = pohmelfs_sys_crypto_init(psb);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb,
-               int (*action)(struct pohmelfs_crypto_thread *t, void *data), void *data)
-{
-       struct pohmelfs_crypto_thread *t = NULL;
-       int err;
-
-       while (!t) {
-               err = wait_event_interruptible_timeout(psb->wait,
-                               !list_empty(&psb->crypto_ready_list),
-                               psb->wait_on_page_timeout);
-
-               t = NULL;
-               err = 0;
-               mutex_lock(&psb->crypto_thread_lock);
-               if (!list_empty(&psb->crypto_ready_list)) {
-                       t = list_entry(psb->crypto_ready_list.prev,
-                                       struct pohmelfs_crypto_thread,
-                                       thread_entry);
-
-                       list_move_tail(&t->thread_entry,
-                                       &psb->crypto_active_list);
-
-                       action(t, data);
-                       wake_up(&t->wait);
-
-               }
-               mutex_unlock(&psb->crypto_thread_lock);
-       }
-
-       return err;
-}
-
-static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data)
-{
-       struct netfs_trans *trans = data;
-
-       netfs_trans_get(trans);
-       t->trans = trans;
-
-       dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t);
-       return 0;
-}
-
-int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb)
-{
-       if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) {
-               netfs_trans_get(trans);
-               return pohmelfs_crypto_finish(trans, psb, 0);
-       }
-
-       return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans);
-}
-
-struct pohmelfs_crypto_input_action_data {
-       struct page                     *page;
-       struct pohmelfs_crypto_engine   *e;
-       u64                             iv;
-       unsigned int                    size;
-};
-
-static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data)
-{
-       struct pohmelfs_crypto_input_action_data *act = data;
-
-       memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size);
-
-       t->size = act->size;
-       t->eng.iv = act->iv;
-
-       t->page = act->page;
-       return 0;
-}
-
-int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
-               struct page *page, unsigned int size, u64 iv)
-{
-       struct inode *inode = page->mapping->host;
-       struct pohmelfs_crypto_input_action_data act;
-       int err = -ENOENT;
-
-       act.page = page;
-       act.e = e;
-       act.size = size;
-       act.iv = iv;
-
-       err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb),
-                       pohmelfs_crypt_input_page_action, &act);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       SetPageUptodate(page);
-       page_cache_release(page);
-
-       return err;
-}
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
deleted file mode 100644 (file)
index 2ee4491..0000000
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/namei.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-
-#include "netfs.h"
-
-static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash)
-{
-       if (n->hash > hash)
-               return -1;
-       if (n->hash < hash)
-               return 1;
-
-       return 0;
-}
-
-static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash)
-{
-       struct rb_node *n = pi->hash_root.rb_node;
-       struct pohmelfs_name *tmp = NULL;
-       int cmp;
-
-       while (n) {
-               tmp = rb_entry(n, struct pohmelfs_name, hash_node);
-
-               cmp = pohmelfs_cmp_hash(tmp, hash);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else
-                       break;
-
-       }
-
-       return tmp;
-}
-
-struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash)
-{
-       struct pohmelfs_name *tmp;
-
-       tmp = pohmelfs_search_hash_unprecise(pi, hash);
-       if (tmp && (tmp->hash == hash))
-               return tmp;
-
-       return NULL;
-}
-
-static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       rb_erase(&node->hash_node, &parent->hash_root);
-}
-
-/*
- * Remove name cache entry from its caches and free it.
- */
-static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       __pohmelfs_name_del(parent, node);
-       list_del(&node->sync_create_entry);
-       kfree(node);
-}
-
-static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi,
-               struct pohmelfs_name *new)
-{
-       struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL;
-       struct pohmelfs_name *ret = NULL, *tmp;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               tmp = rb_entry(parent, struct pohmelfs_name, hash_node);
-
-               cmp = pohmelfs_cmp_hash(tmp, new->hash);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       if (ret) {
-               printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
-                                       "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
-                               __func__, pi->ino,
-                               ret->ino, ret->hash, ret->len, ret->data,
-                               new->ino, new->hash, new->len, new->data);
-               ret->ino = new->ino;
-               return ret;
-       }
-
-       rb_link_node(&new->hash_node, parent, n);
-       rb_insert_color(&new->hash_node, &pi->hash_root);
-
-       return NULL;
-}
-
-/*
- * Free name cache for given inode.
- */
-void pohmelfs_free_names(struct pohmelfs_inode *parent)
-{
-       struct rb_node *rb_node;
-       struct pohmelfs_name *n;
-
-       for (rb_node = rb_first(&parent->hash_root); rb_node;) {
-               n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
-               rb_node = rb_next(rb_node);
-
-               pohmelfs_name_free(parent, n);
-       }
-}
-
-static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       parent->total_len -= node->len;
-}
-
-/*
- * Free name cache entry helper.
- */
-void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       pohmelfs_fix_offset(parent, node);
-       pohmelfs_name_free(parent, node);
-}
-
-/*
- * Insert new name cache entry into all hash cache.
- */
-static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n)
-{
-       struct pohmelfs_name *name;
-
-       name = pohmelfs_insert_hash(parent, n);
-       if (name)
-               return -EEXIST;
-
-       parent->total_len += n->len;
-       list_add_tail(&n->sync_create_entry, &parent->sync_create_list);
-
-       return 0;
-}
-
-/*
- * Allocate new name cache entry.
- */
-static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len)
-{
-       struct pohmelfs_name *n;
-
-       n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL);
-       if (!n)
-               return NULL;
-
-       INIT_LIST_HEAD(&n->sync_create_entry);
-
-       n->data = (char *)(n+1);
-
-       return n;
-}
-
-/*
- * Add new name entry into directory's cache.
- */
-static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent,
-               struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link)
-{
-       int err = -ENOMEM;
-       struct pohmelfs_name *n;
-
-       n = pohmelfs_name_alloc(str->len + 1);
-       if (!n)
-               goto err_out_exit;
-
-       n->ino = npi->ino;
-       n->mode = mode;
-       n->len = str->len;
-       n->hash = str->hash;
-       sprintf(n->data, "%s", str->name);
-
-       mutex_lock(&parent->offset_lock);
-       err = pohmelfs_insert_name(parent, n);
-       mutex_unlock(&parent->offset_lock);
-
-       if (err) {
-               if (err != -EEXIST)
-                       goto err_out_free;
-               kfree(n);
-       }
-
-       return 0;
-
-err_out_free:
-       kfree(n);
-err_out_exit:
-       return err;
-}
-
-/*
- * Create new inode for given parameters (name, inode info, parent).
- * This does not create object on the server, it will be synced there during writeback.
- */
-struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
-               struct pohmelfs_inode *parent, struct qstr *str,
-               struct netfs_inode_info *info, int link)
-{
-       struct inode *new = NULL;
-       struct pohmelfs_inode *npi;
-       int err = -EEXIST;
-
-       dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
-                       __func__, (parent) ? parent->ino : 0, info->ino, str);
-
-       err = -ENOMEM;
-       new = iget_locked(psb->sb, info->ino);
-       if (!new)
-               goto err_out_exit;
-
-       npi = POHMELFS_I(new);
-       npi->ino = info->ino;
-       err = 0;
-
-       if (new->i_state & I_NEW) {
-               dprintk("%s: filling VFS inode: %lu/%llu.\n",
-                               __func__, new->i_ino, info->ino);
-               pohmelfs_fill_inode(new, info);
-
-               if (S_ISDIR(info->mode)) {
-                       struct qstr s;
-
-                       s.name = ".";
-                       s.len = 1;
-                       s.hash = jhash(s.name, s.len, 0);
-
-                       err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0);
-                       if (err)
-                               goto err_out_put;
-
-                       s.name = "..";
-                       s.len = 2;
-                       s.hash = jhash(s.name, s.len, 0);
-
-                       err = pohmelfs_add_dir(psb, npi, (parent) ? parent : npi, &s,
-                                       (parent) ? parent->vfs_inode.i_mode : npi->vfs_inode.i_mode, 0);
-                       if (err)
-                               goto err_out_put;
-               }
-       }
-
-       if (str) {
-               if (parent) {
-                       err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link);
-
-                       dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
-                                       __func__, (err) ? "unsuccessfully" : "successfully",
-                                       str->name, parent->total_len, info->ino, parent->ino);
-
-                       if (err && err != -EEXIST)
-                               goto err_out_put;
-               }
-       }
-
-       if (new->i_state & I_NEW) {
-               if (parent)
-                       mark_inode_dirty(&parent->vfs_inode);
-               mark_inode_dirty(new);
-       }
-
-       set_bit(NETFS_INODE_OWNED, &npi->state);
-       npi->lock_type = POHMELFS_WRITE_LOCK;
-       unlock_new_inode(new);
-
-       return npi;
-
-err_out_put:
-       printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err);
-       iput(new);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct pohmelfs_inode *pi = private;
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
-       dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
-
-       if (err)
-               pi->error = err;
-       wake_up(&psb->wait);
-       pohmelfs_put_inode(pi);
-
-       return err;
-}
-
-/*
- * Receive directory content from the server.
- * This should be only done for objects, which were not created locally,
- * and which were not synced previously.
- */
-static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi)
-{
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       long ret = psb->wait_on_page_timeout;
-       int err;
-
-       dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
-               __func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state));
-
-       if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state))
-               return 0;
-
-       if (!igrab(inode)) {
-               err = -ENOENT;
-               goto err_out_exit;
-       }
-
-       err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST,
-                       pohmelfs_remote_sync_complete, pi, 0);
-       if (err)
-               goto err_out_exit;
-
-       pi->error = 0;
-       ret = wait_event_interruptible_timeout(psb->wait,
-                       test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret);
-       dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error);
-       if (ret <= 0) {
-               err = ret;
-               if (!err)
-                       err = -ETIMEDOUT;
-               goto err_out_exit;
-       }
-
-       if (pi->error)
-               return pi->error;
-
-       return 0;
-
-err_out_exit:
-       clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
-       return err;
-}
-
-static int pohmelfs_dir_open(struct inode *inode, struct file *file)
-{
-       file->private_data = NULL;
-       return 0;
-}
-
-/*
- * VFS readdir callback. Syncs directory content from server if needed,
- * and provides direntry info to the userspace.
- */
-static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
-       struct inode *inode = file->f_path.dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_name *n;
-       struct rb_node *rb_node;
-       int err = 0, mode;
-       u64 len;
-
-       dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
-                       __func__, pi->ino, (u64)file->f_pos,
-                       (unsigned long)file->private_data);
-#if 0
-       err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
-       if (err)
-               return err;
-#endif
-       err = pohmelfs_sync_remote_dir(pi);
-       if (err)
-               return err;
-
-       if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos))
-               return 0;
-
-       mutex_lock(&pi->offset_lock);
-       n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data);
-
-       while (n) {
-               mode = (n->mode >> 12) & 15;
-
-               dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
-                               "mode: %o/%o, fpos: %llu, hash: %08x.\n",
-                               __func__, file->f_pos, pi->ino, n->data, n->len,
-                               n->ino, n->mode, mode, file->f_pos, n->hash);
-
-               file->private_data = (void *)(unsigned long)n->hash;
-
-               len = n->len;
-               err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode);
-
-               if (err < 0) {
-                       dprintk("%s: err: %d.\n", __func__, err);
-                       err = 0;
-                       break;
-               }
-
-               file->f_pos += len;
-
-               rb_node = rb_next(&n->hash_node);
-
-               if (!rb_node || (rb_node == &n->hash_node)) {
-                       file->private_data = (void *)(unsigned long)file->f_pos;
-                       break;
-               }
-
-               n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
-       }
-       mutex_unlock(&pi->offset_lock);
-
-       return err;
-}
-
-static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin)
-{
-       file->f_pos = offset;
-       file->private_data = NULL;
-       return offset;
-}
-
-const struct file_operations pohmelfs_dir_fops = {
-       .open = pohmelfs_dir_open,
-       .read = generic_read_dir,
-       .llseek = pohmelfs_dir_lseek,
-       .readdir = pohmelfs_readdir,
-};
-
-/*
- * Lookup single object on server.
- */
-static int pohmelfs_lookup_single(struct pohmelfs_inode *parent,
-               struct qstr *str, u64 ino)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb);
-       long ret = msecs_to_jiffies(5000);
-       int err;
-
-       set_bit(NETFS_COMMAND_PENDING, &parent->state);
-       err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP,
-                       (char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino);
-       if (err)
-               goto err_out_exit;
-
-       err = 0;
-       ret = wait_event_interruptible_timeout(psb->wait,
-                       !test_bit(NETFS_COMMAND_PENDING, &parent->state), ret);
-       if (ret <= 0) {
-               err = ret;
-               if (!err)
-                       err = -ETIMEDOUT;
-       }
-
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-
-       printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
-                       __func__, parent->ino, ino, str->name, err);
-
-       return err;
-}
-
-/*
- * VFS lookup callback.
- * We first try to get inode number from local name cache, if we have one,
- * then inode can be found in inode cache. If there is no inode or no object in
- * local cache, try to lookup it on server. This only should be done for directories,
- * which were not created locally, otherwise remote server does not know about dir at all,
- * so no need to try to know that.
- */
-struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-       struct pohmelfs_inode *parent = POHMELFS_I(dir);
-       struct pohmelfs_name *n;
-       struct inode *inode = NULL;
-       unsigned long ino = 0;
-       int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
-       struct qstr str = dentry->d_name;
-
-       if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY)
-               lock_type = POHMELFS_WRITE_LOCK;
-
-       if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
-               if (lock_type == parent->lock_type)
-                       need_lock = 0;
-               if ((lock_type == POHMELFS_READ_LOCK) && (parent->lock_type == POHMELFS_WRITE_LOCK))
-                       need_lock = 0;
-       }
-
-       if ((lock_type == POHMELFS_READ_LOCK) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state))
-               need_lock = 1;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       mutex_lock(&parent->offset_lock);
-       n = pohmelfs_search_hash(parent, str.hash);
-       if (n)
-               ino = n->ino;
-       mutex_unlock(&parent->offset_lock);
-
-       dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
-                       __func__, ino, inode, str.name, str.hash, parent->state, need_lock);
-
-       if (ino) {
-               inode = ilookup(dir->i_sb, ino);
-               if (inode)
-                       goto out;
-       }
-
-       dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
-                       __func__, dir, parent->ino,
-                       str.name, str.len, parent->state, ino);
-
-       if (!ino) {
-               if (!need_lock)
-                       goto out;
-       }
-
-       err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
-       if (err)
-               goto out;
-
-       err = pohmelfs_lookup_single(parent, &str, ino);
-       if (err)
-               goto out;
-
-       if (!ino) {
-               mutex_lock(&parent->offset_lock);
-               n = pohmelfs_search_hash(parent, str.hash);
-               if (n)
-                       ino = n->ino;
-               mutex_unlock(&parent->offset_lock);
-       }
-
-       if (ino) {
-               inode = ilookup(dir->i_sb, ino);
-               dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
-                               __func__, ino, inode, str.name, str.hash);
-               if (!inode) {
-                       dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
-                               __func__, ino, str.name, str.hash);
-                       /* return NULL; */
-                       return ERR_PTR(-EACCES);
-               }
-       } else {
-               printk("%s: No inode number : name: '%s', hash: %x.\n",
-                       __func__, str.name, str.hash);
-       }
-out:
-       return d_splice_alias(inode, dentry);
-}
-
-/*
- * Create new object in local cache. Object will be synced to server
- * during writeback for given inode.
- */
-struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
-       struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode)
-{
-       struct pohmelfs_inode *npi;
-       int err = -ENOMEM;
-       struct netfs_inode_info info;
-
-       dprintk("%s: name: '%s', mode: %ho, start: %llu.\n",
-                       __func__, str->name, mode, start);
-
-       info.mode = mode;
-       info.ino = start;
-
-       if (!start)
-               info.ino = pohmelfs_new_ino(psb);
-
-       info.nlink = S_ISDIR(mode) ? 2 : 1;
-       info.uid = current_fsuid();
-       info.gid = current_fsgid();
-       info.size = 0;
-       info.blocksize = 512;
-       info.blocks = 0;
-       info.rdev = 0;
-       info.version = 0;
-
-       npi = pohmelfs_new_inode(psb, parent, str, &info, !!start);
-       if (IS_ERR(npi)) {
-               err = PTR_ERR(npi);
-               goto err_out_unlock;
-       }
-
-       return npi;
-
-err_out_unlock:
-       dprintk("%s: err: %d.\n", __func__, err);
-       return ERR_PTR(err);
-}
-
-/*
- * Create local object and bind it to dentry.
- */
-static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry,
-                                u64 start, umode_t mode)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
-       struct pohmelfs_inode *npi, *parent;
-       struct qstr str = dentry->d_name;
-       int err;
-
-       parent = POHMELFS_I(dir);
-
-       err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               return err;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode);
-       if (IS_ERR(npi))
-               return PTR_ERR(npi);
-
-       d_instantiate(dentry, &npi->vfs_inode);
-
-       dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
-                       __func__, parent->ino, npi->ino, dentry->d_name.name,
-                       (signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink);
-
-       return 0;
-}
-
-/*
- * VFS create and mkdir callbacks.
- */
-static int pohmelfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
-{
-       return pohmelfs_create_entry(dir, dentry, 0, mode);
-}
-
-static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
-{
-       int err;
-
-       inode_inc_link_count(dir);
-       err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR);
-       if (err)
-               inode_dec_link_count(dir);
-
-       return err;
-}
-
-static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode);
-       struct pohmelfs_name *n;
-       int err = -ENOENT;
-       struct qstr str = dentry->d_name;
-
-       err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               return err;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
-                       __func__, parent->ino, pi->ino,
-                       str.name, (signed)inode->i_nlink);
-
-       BUG_ON(!inode);
-
-       mutex_lock(&parent->offset_lock);
-       n = pohmelfs_search_hash(parent, str.hash);
-       if (n) {
-               pohmelfs_fix_offset(parent, n);
-               if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
-                       pohmelfs_remove_child(pi, n);
-
-               pohmelfs_name_free(parent, n);
-               err = 0;
-       }
-       mutex_unlock(&parent->offset_lock);
-
-       if (!err) {
-               psb->avail_size += inode->i_size;
-
-               pohmelfs_inode_del_inode(psb, pi);
-
-               mark_inode_dirty(dir);
-
-               inode->i_ctime = dir->i_ctime;
-               if (inode->i_nlink)
-                       inode_dec_link_count(inode);
-       }
-
-       return err;
-}
-
-/*
- * Unlink and rmdir VFS callbacks.
- */
-static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry)
-{
-       return pohmelfs_remove_entry(dir, dentry);
-}
-
-static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-       int err;
-       struct inode *inode = dentry->d_inode;
-
-       dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
-                       __func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino,
-                       dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink);
-
-       err = pohmelfs_remove_entry(dir, dentry);
-       if (!err) {
-               inode_dec_link_count(dir);
-               inode_dec_link_count(inode);
-       }
-
-       return err;
-}
-
-/*
- * Link creation is synchronous.
- * I'm lazy.
- * Earth is somewhat round.
- */
-static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj,
-               struct pohmelfs_inode *target, struct qstr *tstr)
-{
-       struct super_block *sb = parent->vfs_inode.i_sb;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       struct netfs_cmd *cmd;
-       struct netfs_trans *t;
-       void *data;
-       int err, parent_len, target_len = 0, cur_len, path_size = 0;
-
-       err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               return err;
-
-       err = sb->s_op->write_inode(&parent->vfs_inode, 0);
-       if (err)
-               goto err_out_exit;
-
-       if (tstr)
-               target_len = tstr->len;
-
-       parent_len = pohmelfs_path_length(parent);
-       if (target)
-               target_len += pohmelfs_path_length(target);
-
-       if (parent_len < 0) {
-               err = parent_len;
-               goto err_out_exit;
-       }
-
-       if (target_len < 0) {
-               err = target_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-       cur_len = netfs_trans_cur_len(t);
-
-       cmd = netfs_trans_current(t);
-       if (IS_ERR(cmd)) {
-               err = PTR_ERR(cmd);
-               goto err_out_free;
-       }
-
-       data = (void *)(cmd + 1);
-       cur_len -= sizeof(struct netfs_cmd);
-
-       err = pohmelfs_construct_path_string(parent, data, parent_len);
-       if (err > 0) {
-               /* Do not place null-byte before the slash */
-               path_size = err - 1;
-               cur_len -= path_size;
-
-               err = snprintf(data + path_size, cur_len, "/%s|", obj->name);
-
-               path_size += err;
-               cur_len -= err;
-
-               cmd->ext = path_size - 1; /* No | symbol */
-
-               if (target) {
-                       err = pohmelfs_construct_path_string(target, data + path_size, target_len);
-                       if (err > 0) {
-                               path_size += err;
-                               cur_len -= err;
-                       }
-               }
-       }
-
-       if (err < 0)
-               goto err_out_free;
-
-       cmd->start = 0;
-
-       if (!target && tstr) {
-               if (tstr->len > cur_len - 1) {
-                       err = -ENAMETOOLONG;
-                       goto err_out_free;
-               }
-
-               err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */
-               path_size += err;
-               cur_len -= err;
-               cmd->start = 1;
-       }
-
-       dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
-                       __func__, parent->ino, obj->name, (target) ? target->ino : 0, (tstr) ? tstr->name : NULL,
-                       (char *)data);
-
-       cmd->cmd = NETFS_LINK;
-       cmd->size = path_size;
-       cmd->id = parent->ino;
-
-       netfs_convert_cmd(cmd);
-
-       netfs_trans_update(cmd, t, path_size);
-
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_free:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       return err;
-}
-
-/*
- *  VFS hard and soft link callbacks.
- */
-static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir,
-       struct dentry *dentry)
-{
-       struct inode *inode = old_dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err;
-       struct qstr str = dentry->d_name;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       err = inode->i_sb->s_op->write_inode(inode, 0);
-       if (err)
-               return err;
-
-       err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL);
-       if (err)
-               return err;
-
-       return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode);
-}
-
-static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
-       struct qstr sym_str;
-       struct qstr str = dentry->d_name;
-       struct inode *inode;
-       int err;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       sym_str.name = symname;
-       sym_str.len = strlen(symname);
-
-       err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str);
-       if (err)
-               goto err_out_exit;
-
-       err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
-       if (err)
-               goto err_out_exit;
-
-       inode = dentry->d_inode;
-
-       err = page_symlink(inode, symname, sym_str.len + 1);
-       if (err)
-               goto err_out_put;
-
-       return 0;
-
-err_out_put:
-       iput(inode);
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent,
-               struct qstr *str)
-{
-       int path_len, err, total_len = 0, inode_len, parent_len;
-       char *path;
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
-       parent_len = pohmelfs_path_length(parent);
-       inode_len = pohmelfs_path_length(pi);
-
-       if (parent_len < 0 || inode_len < 0)
-               return -EINVAL;
-
-       path_len = parent_len + inode_len + str->len + 3;
-
-       t = netfs_trans_alloc(psb, path_len, 0, 0);
-       if (!t)
-               return -ENOMEM;
-
-       cmd = netfs_trans_current(t);
-       path = (char *)(cmd + 1);
-
-       err = pohmelfs_construct_path_string(pi, path, inode_len);
-       if (err < 0)
-               goto err_out_unlock;
-
-       cmd->ext = err;
-
-       path += err;
-       total_len += err;
-       path_len -= err;
-
-       *path = '|';
-       path++;
-       total_len++;
-       path_len--;
-
-       err = pohmelfs_construct_path_string(parent, path, parent_len);
-       if (err < 0)
-               goto err_out_unlock;
-
-       /*
-        * Do not place a null-byte before the final slash and the name.
-        */
-       err--;
-       path += err;
-       total_len += err;
-       path_len -= err;
-
-       err = snprintf(path, path_len - 1, "/%s", str->name);
-
-       total_len += err + 1; /* 0 symbol */
-       path_len -= err + 1;
-
-       cmd->cmd = NETFS_RENAME;
-       cmd->id = pi->ino;
-       cmd->start = parent->ino;
-       cmd->size = total_len;
-
-       netfs_convert_cmd(cmd);
-
-       netfs_trans_update(cmd, t, total_len);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_unlock:
-       netfs_trans_free(t);
-       return err;
-}
-
-static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-                       struct inode *new_dir, struct dentry *new_dentry)
-{
-       struct inode *inode = old_dentry->d_inode;
-       struct pohmelfs_inode *old_parent, *pi, *new_parent;
-       struct qstr str = new_dentry->d_name;
-       struct pohmelfs_name *n;
-       unsigned int old_hash;
-       int err = -ENOENT;
-
-       pi = POHMELFS_I(inode);
-       old_parent = POHMELFS_I(old_dir);
-
-       if (new_dir)
-               new_dir->i_sb->s_op->write_inode(new_dir, 0);
-
-       old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0);
-       str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
-
-       str.len = new_dentry->d_name.len;
-       str.name = new_dentry->d_name.name;
-       str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
-
-       if (new_dir) {
-               new_parent = POHMELFS_I(new_dir);
-               err = -ENOTEMPTY;
-
-               if (S_ISDIR(inode->i_mode) &&
-                               new_parent->total_len <= 3)
-                       goto err_out_exit;
-       } else {
-               new_parent = old_parent;
-       }
-
-       dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
-                       __func__, pi->ino, old_parent->ino, old_dentry->d_name.name,
-                       new_parent->ino, new_dentry->d_name.name, inode->i_size);
-
-       if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) &&
-                       test_bit(NETFS_INODE_OWNED, &pi->state)) {
-               err = pohmelfs_send_rename(pi, new_parent, &str);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       n = pohmelfs_name_alloc(str.len + 1);
-       if (!n)
-               goto err_out_exit;
-
-       mutex_lock(&new_parent->offset_lock);
-       n->ino = pi->ino;
-       n->mode = inode->i_mode;
-       n->len = str.len;
-       n->hash = str.hash;
-       sprintf(n->data, "%s", str.name);
-
-       err = pohmelfs_insert_name(new_parent, n);
-       mutex_unlock(&new_parent->offset_lock);
-
-       if (err)
-               goto err_out_exit;
-
-       mutex_lock(&old_parent->offset_lock);
-       n = pohmelfs_search_hash(old_parent, old_hash);
-       if (n)
-               pohmelfs_name_del(old_parent, n);
-       mutex_unlock(&old_parent->offset_lock);
-
-       mark_inode_dirty(inode);
-       mark_inode_dirty(&new_parent->vfs_inode);
-
-       WARN_ON_ONCE(list_empty(&inode->i_dentry));
-
-       return 0;
-
-err_out_exit:
-
-       clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
-       return err;
-}
-
-/*
- * POHMELFS directory inode operations.
- */
-const struct inode_operations pohmelfs_dir_inode_ops = {
-       .link           = pohmelfs_link,
-       .symlink        = pohmelfs_symlink,
-       .unlink         = pohmelfs_unlink,
-       .mkdir          = pohmelfs_mkdir,
-       .rmdir          = pohmelfs_rmdir,
-       .create         = pohmelfs_create,
-       .lookup         = pohmelfs_lookup,
-       .setattr        = pohmelfs_setattr,
-       .rename         = pohmelfs_rename,
-};
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
deleted file mode 100644 (file)
index 807e3f3..0000000
+++ /dev/null
@@ -1,2055 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/backing-dev.h>
-#include <linux/crypto.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/hash.h>
-#include <linux/ktime.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/pagevec.h>
-#include <linux/parser.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/statfs.h>
-#include <linux/writeback.h>
-#include <linux/prefetch.h>
-
-#include "netfs.h"
-
-#define POHMELFS_MAGIC_NUM     0x504f482e
-
-static struct kmem_cache *pohmelfs_inode_cache;
-static atomic_t psb_bdi_num = ATOMIC_INIT(0);
-
-/*
- * Removes inode from all trees, drops local name cache and removes all queued
- * requests for object removal.
- */
-void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi)
-{
-       mutex_lock(&pi->offset_lock);
-       pohmelfs_free_names(pi);
-       mutex_unlock(&pi->offset_lock);
-
-       dprintk("%s: deleted stuff in ino: %llu.\n", __func__, pi->ino);
-}
-
-/*
- * Sync inode to server.
- * Returns zero in success and negative error value otherwise.
- * It will gather path to root directory into structures containing
- * creation mode, permissions and names, so that the whole path
- * to given inode could be created using only single network command.
- */
-int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans)
-{
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err = -ENOMEM, size;
-       struct netfs_cmd *cmd;
-       void *data;
-       int cur_len = netfs_trans_cur_len(trans);
-
-       if (unlikely(cur_len < 0))
-               return -ETOOSMALL;
-
-       cmd = netfs_trans_current(trans);
-       cur_len -= sizeof(struct netfs_cmd);
-
-       data = (void *)(cmd + 1);
-
-       err = pohmelfs_construct_path_string(pi, data, cur_len);
-       if (err < 0)
-               goto err_out_exit;
-
-       size = err;
-
-       cmd->start = i_size_read(inode);
-       cmd->cmd = NETFS_CREATE;
-       cmd->size = size;
-       cmd->id = pi->ino;
-       cmd->ext = inode->i_mode;
-
-       netfs_convert_cmd(cmd);
-
-       netfs_trans_update(cmd, trans, size);
-
-       return 0;
-
-err_out_exit:
-       printk("%s: completed ino: %llu, err: %d.\n", __func__, pi->ino, err);
-       return err;
-}
-
-static int pohmelfs_write_trans_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       unsigned i;
-
-       dprintk("%s: pages: %lu-%lu, page_num: %u, err: %d.\n",
-                       __func__, pages[0]->index, pages[page_num-1]->index,
-                       page_num, err);
-
-       for (i = 0; i < page_num; i++) {
-               struct page *page = pages[i];
-
-               if (!page)
-                       continue;
-
-               end_page_writeback(page);
-
-               if (err < 0) {
-                       SetPageError(page);
-                       set_page_dirty(page);
-               }
-
-               unlock_page(page);
-               page_cache_release(page);
-
-               /* dprintk("%s: %3u/%u: page: %p.\n", __func__, i, page_num, page); */
-       }
-       return err;
-}
-
-static int pohmelfs_inode_has_dirty_pages(struct address_space *mapping, pgoff_t index)
-{
-       int ret;
-       struct page *page;
-
-       rcu_read_lock();
-       ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
-                               (void **)&page, index, 1, PAGECACHE_TAG_DIRTY);
-       rcu_read_unlock();
-       return ret;
-}
-
-static int pohmelfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
-{
-       struct inode *inode = mapping->host;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       int err = 0;
-       int done = 0;
-       int nr_pages;
-       pgoff_t index;
-       pgoff_t end;            /* Inclusive */
-       int scanned = 0;
-       int range_whole = 0;
-
-       if (wbc->range_cyclic) {
-               index = mapping->writeback_index; /* Start from prev offset */
-               end = -1;
-       } else {
-               index = wbc->range_start >> PAGE_CACHE_SHIFT;
-               end = wbc->range_end >> PAGE_CACHE_SHIFT;
-               if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
-                       range_whole = 1;
-               scanned = 1;
-       }
-retry:
-       while (!done && (index <= end)) {
-               unsigned int i = min(end - index, (pgoff_t)psb->trans_max_pages);
-               int path_len;
-               struct netfs_trans *trans;
-
-               err = pohmelfs_inode_has_dirty_pages(mapping, index);
-               if (!err)
-                       break;
-
-               err = pohmelfs_path_length(pi);
-               if (err < 0)
-                       break;
-
-               path_len = err;
-
-               if (path_len <= 2) {
-                       err = -ENOENT;
-                       break;
-               }
-
-               trans = netfs_trans_alloc(psb, path_len, 0, i);
-               if (!trans) {
-                       err = -ENOMEM;
-                       break;
-               }
-               trans->complete = &pohmelfs_write_trans_complete;
-
-               trans->page_num = nr_pages = find_get_pages_tag(mapping, &index,
-                               PAGECACHE_TAG_DIRTY, trans->page_num,
-                               trans->pages);
-
-               dprintk("%s: t: %p, nr_pages: %u, end: %lu, index: %lu, max: %u.\n",
-                               __func__, trans, nr_pages, end, index, trans->page_num);
-
-               if (!nr_pages)
-                       goto err_out_reset;
-
-               err = pohmelfs_write_inode_create(inode, trans);
-               if (err)
-                       goto err_out_reset;
-
-               err = 0;
-               scanned = 1;
-
-               for (i = 0; i < trans->page_num; i++) {
-                       struct page *page = trans->pages[i];
-
-                       lock_page(page);
-
-                       if (unlikely(page->mapping != mapping))
-                               goto out_continue;
-
-                       if (!wbc->range_cyclic && page->index > end) {
-                               done = 1;
-                               goto out_continue;
-                       }
-
-                       if (wbc->sync_mode != WB_SYNC_NONE)
-                               wait_on_page_writeback(page);
-
-                       if (PageWriteback(page) ||
-                           !clear_page_dirty_for_io(page)) {
-                               dprintk("%s: not clear for io page: %p, writeback: %d.\n",
-                                               __func__, page, PageWriteback(page));
-                               goto out_continue;
-                       }
-
-                       set_page_writeback(page);
-
-                       trans->attached_size += page_private(page);
-                       trans->attached_pages++;
-#if 0
-                       dprintk("%s: %u/%u added trans: %p, gen: %u, page: %p, [High: %d], size: %lu, idx: %lu.\n",
-                                       __func__, i, trans->page_num, trans, trans->gen, page,
-                                       !!PageHighMem(page), page_private(page), page->index);
-#endif
-                       wbc->nr_to_write--;
-
-                       if (wbc->nr_to_write <= 0)
-                               done = 1;
-
-                       continue;
-out_continue:
-                       unlock_page(page);
-                       trans->pages[i] = NULL;
-               }
-
-               err = netfs_trans_finish(trans, psb);
-               if (err)
-                       break;
-
-               continue;
-
-err_out_reset:
-               trans->result = err;
-               netfs_trans_reset(trans);
-               netfs_trans_put(trans);
-               break;
-       }
-
-       if (!scanned && !done) {
-               /*
-                * We hit the last page and there is more work to be done: wrap
-                * back to the start of the file
-                */
-               scanned = 1;
-               index = 0;
-               goto retry;
-       }
-
-       if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
-               mapping->writeback_index = index;
-
-       return err;
-}
-
-/*
- * Inode writeback creation completion callback.
- * Only invoked for just created inodes, which do not have pages attached,
- * like dirs and empty files.
- */
-static int pohmelfs_write_inode_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct inode *inode = private;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       if (inode) {
-               if (err) {
-                       mark_inode_dirty(inode);
-                       clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-               } else {
-                       set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-               }
-
-               pohmelfs_put_inode(pi);
-       }
-
-       return err;
-}
-
-int pohmelfs_write_create_inode(struct pohmelfs_inode *pi)
-{
-       struct netfs_trans *t;
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       int err;
-
-       if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
-               return 0;
-
-       dprintk("%s: started ino: %llu.\n", __func__, pi->ino);
-
-       err = pohmelfs_path_length(pi);
-       if (err < 0)
-               goto err_out_exit;
-
-       t = netfs_trans_alloc(psb, err + 1, 0, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-       t->complete = pohmelfs_write_inode_complete;
-       t->private = igrab(inode);
-       if (!t->private) {
-               err = -ENOENT;
-               goto err_out_put;
-       }
-
-       err = pohmelfs_write_inode_create(inode, t);
-       if (err)
-               goto err_out_put;
-
-       netfs_trans_finish(t, POHMELFS_SB(inode->i_sb));
-
-       return 0;
-
-err_out_put:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       return err;
-}
-
-/*
- * Sync all not-yet-created children in given directory to the server.
- */
-static int pohmelfs_write_inode_create_children(struct inode *inode)
-{
-       struct pohmelfs_inode *parent = POHMELFS_I(inode);
-       struct super_block *sb = inode->i_sb;
-       struct pohmelfs_name *n;
-
-       while (!list_empty(&parent->sync_create_list)) {
-               n = NULL;
-               mutex_lock(&parent->offset_lock);
-               if (!list_empty(&parent->sync_create_list)) {
-                       n = list_first_entry(&parent->sync_create_list,
-                               struct pohmelfs_name, sync_create_entry);
-                       list_del_init(&n->sync_create_entry);
-               }
-               mutex_unlock(&parent->offset_lock);
-
-               if (!n)
-                       break;
-
-               inode = ilookup(sb, n->ino);
-
-               dprintk("%s: parent: %llu, ino: %llu, inode: %p.\n",
-                               __func__, parent->ino, n->ino, inode);
-
-               if (inode && (inode->i_state & I_DIRTY)) {
-                       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-                       pohmelfs_write_create_inode(pi);
-                       /* pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); */
-                       iput(inode);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Removes given child from given inode on server.
- */
-int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n)
-{
-       return pohmelfs_meta_command_data(pi, pi->ino, NETFS_REMOVE, NULL, 0, NULL, NULL, 0);
-}
-
-/*
- * Writeback for given inode.
- */
-static int pohmelfs_write_inode(struct inode *inode,
-                               struct writeback_control *wbc)
-{
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       pohmelfs_write_create_inode(pi);
-       pohmelfs_write_inode_create_children(inode);
-
-       return 0;
-}
-
-/*
- * It is not exported, sorry...
- */
-static inline wait_queue_head_t *page_waitqueue(struct page *page)
-{
-       const struct zone *zone = page_zone(page);
-
-       return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];
-}
-
-static int pohmelfs_wait_on_page_locked(struct page *page)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(page->mapping->host->i_sb);
-       long ret = psb->wait_on_page_timeout;
-       DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
-       int err = 0;
-
-       if (!PageLocked(page))
-               return 0;
-
-       for (;;) {
-               prepare_to_wait(page_waitqueue(page),
-                               &wait.wait, TASK_INTERRUPTIBLE);
-
-               dprintk("%s: page: %p, locked: %d, uptodate: %d, error: %d, flags: %lx.\n",
-                               __func__, page, PageLocked(page), PageUptodate(page),
-                               PageError(page), page->flags);
-
-               if (!PageLocked(page))
-                       break;
-
-               if (!signal_pending(current)) {
-                       ret = schedule_timeout(ret);
-                       if (!ret)
-                               break;
-                       continue;
-               }
-               ret = -ERESTARTSYS;
-               break;
-       }
-       finish_wait(page_waitqueue(page), &wait.wait);
-
-       if (!ret)
-               err = -ETIMEDOUT;
-
-
-       if (!err)
-               SetPageUptodate(page);
-
-       if (err)
-               printk("%s: page: %p, uptodate: %d, locked: %d, err: %d.\n",
-                       __func__, page, PageUptodate(page), PageLocked(page), err);
-
-       return err;
-}
-
-static int pohmelfs_read_page_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct page *page = private;
-
-       if (PageChecked(page))
-               return err;
-
-       if (err < 0) {
-               dprintk("%s: page: %p, err: %d.\n", __func__, page, err);
-               SetPageError(page);
-       }
-
-       unlock_page(page);
-
-       return err;
-}
-
-/*
- * Read a page from remote server.
- * Function will wait until page is unlocked.
- */
-static int pohmelfs_readpage(struct file *file, struct page *page)
-{
-       struct inode *inode = page->mapping->host;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       int err, path_len;
-       void *data;
-       u64 isize;
-
-       err = pohmelfs_data_lock(pi, page->index << PAGE_CACHE_SHIFT,
-                       PAGE_SIZE, POHMELFS_READ_LOCK);
-       if (err)
-               goto err_out_exit;
-
-       isize = i_size_read(inode);
-       if (isize <= page->index << PAGE_CACHE_SHIFT) {
-               SetPageUptodate(page);
-               unlock_page(page);
-               return 0;
-       }
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       t->complete = pohmelfs_read_page_complete;
-       t->private = page;
-
-       cmd = netfs_trans_current(t);
-       data = (void *)(cmd + 1);
-
-       err = pohmelfs_construct_path_string(pi, data, path_len);
-       if (err < 0)
-               goto err_out_free;
-
-       path_len = err;
-
-       cmd->id = pi->ino;
-       cmd->start = page->index;
-       cmd->start <<= PAGE_CACHE_SHIFT;
-       cmd->size = PAGE_CACHE_SIZE + path_len;
-       cmd->cmd = NETFS_READ_PAGE;
-       cmd->ext = path_len;
-
-       dprintk("%s: path: '%s', page: %p, ino: %llu, start: %llu, size: %lu.\n",
-                       __func__, (char *)data, page, pi->ino, cmd->start, PAGE_CACHE_SIZE);
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, path_len);
-
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_return;
-
-       return pohmelfs_wait_on_page_locked(page);
-
-err_out_free:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       SetPageError(page);
-       if (PageLocked(page))
-               unlock_page(page);
-err_out_return:
-       printk("%s: page: %p, start: %lu, size: %lu, err: %d.\n",
-               __func__, page, page->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, err);
-
-       return err;
-}
-
-/*
- * Write begin/end magic.
- * Allocates a page and writes inode if it was not synced to server before.
- */
-static int pohmelfs_write_begin(struct file *file, struct address_space *mapping,
-               loff_t pos, unsigned len, unsigned flags,
-               struct page **pagep, void **fsdata)
-{
-       struct inode *inode = mapping->host;
-       struct page *page;
-       pgoff_t index;
-       unsigned start, end;
-       int err;
-
-       *pagep = NULL;
-
-       index = pos >> PAGE_CACHE_SHIFT;
-       start = pos & (PAGE_CACHE_SIZE - 1);
-       end = start + len;
-
-       page = grab_cache_page(mapping, index);
-#if 0
-       dprintk("%s: page: %p pos: %llu, len: %u, index: %lu, start: %u, end: %u, uptodate: %d.\n",
-                       __func__, page, pos, len, index, start, end, PageUptodate(page));
-#endif
-       if (!page) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       while (!PageUptodate(page)) {
-               if (start && test_bit(NETFS_INODE_REMOTE_SYNCED, &POHMELFS_I(inode)->state)) {
-                       err = pohmelfs_readpage(file, page);
-                       if (err)
-                               goto err_out_exit;
-
-                       lock_page(page);
-                       continue;
-               }
-
-               if (len != PAGE_CACHE_SIZE) {
-                       void *kaddr = kmap_atomic(page, KM_USER0);
-
-                       memset(kaddr + start, 0, PAGE_CACHE_SIZE - start);
-                       flush_dcache_page(page);
-                       kunmap_atomic(kaddr, KM_USER0);
-               }
-               SetPageUptodate(page);
-       }
-
-       set_page_private(page, end);
-
-       *pagep = page;
-
-       return 0;
-
-err_out_exit:
-       page_cache_release(page);
-       *pagep = NULL;
-
-       return err;
-}
-
-static int pohmelfs_write_end(struct file *file, struct address_space *mapping,
-                       loff_t pos, unsigned len, unsigned copied,
-                       struct page *page, void *fsdata)
-{
-       struct inode *inode = mapping->host;
-
-       if (copied != len) {
-               unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-               void *kaddr = kmap_atomic(page, KM_USER0);
-
-               memset(kaddr + from + copied, 0, len - copied);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
-       }
-
-       SetPageUptodate(page);
-       set_page_dirty(page);
-#if 0
-       dprintk("%s: page: %p [U: %d, D: %d, L: %d], pos: %llu, len: %u, copied: %u.\n",
-                       __func__, page,
-                       PageUptodate(page), PageDirty(page), PageLocked(page),
-                       pos, len, copied);
-#endif
-       flush_dcache_page(page);
-
-       unlock_page(page);
-       page_cache_release(page);
-
-       if (pos + copied > inode->i_size) {
-               struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-
-               psb->avail_size -= pos + copied - inode->i_size;
-
-               i_size_write(inode, pos + copied);
-       }
-
-       return copied;
-}
-
-static int pohmelfs_readpages_trans_complete(struct page **__pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct pohmelfs_inode *pi = private;
-       unsigned int i, num;
-       struct page **pages, *page = (struct page *)__pages;
-       loff_t index = page->index;
-
-       pages = kzalloc(sizeof(void *) * page_num, GFP_NOIO);
-       if (!pages)
-               return -ENOMEM;
-
-       num = find_get_pages_contig(pi->vfs_inode.i_mapping, index, page_num, pages);
-       if (num <= 0) {
-               err = num;
-               goto err_out_free;
-       }
-
-       for (i = 0; i < num; ++i) {
-               page = pages[i];
-
-               if (err)
-                       printk("%s: %u/%u: page: %p, index: %lu, uptodate: %d, locked: %d, err: %d.\n",
-                               __func__, i, num, page, page->index,
-                               PageUptodate(page), PageLocked(page), err);
-
-               if (!PageChecked(page)) {
-                       if (err < 0)
-                               SetPageError(page);
-                       unlock_page(page);
-               }
-               page_cache_release(page);
-               page_cache_release(page);
-       }
-
-err_out_free:
-       kfree(pages);
-       return err;
-}
-
-static int pohmelfs_send_readpages(struct pohmelfs_inode *pi, struct page *first, unsigned int num)
-{
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-       int err, path_len;
-       void *data;
-
-       err = pohmelfs_data_lock(pi, first->index << PAGE_CACHE_SHIFT,
-                       num * PAGE_SIZE, POHMELFS_READ_LOCK);
-       if (err)
-               goto err_out_exit;
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       cmd = netfs_trans_current(t);
-       data = (void *)(cmd + 1);
-
-       t->complete = pohmelfs_readpages_trans_complete;
-       t->private = pi;
-       t->page_num = num;
-       t->pages = (struct page **)first;
-
-       err = pohmelfs_construct_path_string(pi, data, path_len);
-       if (err < 0)
-               goto err_out_put;
-
-       path_len = err;
-
-       cmd->cmd = NETFS_READ_PAGES;
-       cmd->start = first->index;
-       cmd->start <<= PAGE_CACHE_SHIFT;
-       cmd->size = (num << 8 | PAGE_CACHE_SHIFT);
-       cmd->id = pi->ino;
-       cmd->ext = path_len;
-
-       dprintk("%s: t: %p, gen: %u, path: '%s', path_len: %u, "
-                       "start: %lu, num: %u.\n",
-                       __func__, t, t->gen, (char *)data, path_len,
-                       first->index, num);
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, path_len);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_put:
-       netfs_trans_free(t);
-err_out_exit:
-       pohmelfs_readpages_trans_complete((struct page **)first, num, pi, err);
-       return err;
-}
-
-#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
-
-static int pohmelfs_readpages(struct file *file, struct address_space *mapping,
-                       struct list_head *pages, unsigned nr_pages)
-{
-       unsigned int page_idx, num = 0;
-       struct page *page = NULL, *first = NULL;
-
-       for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-               page = list_to_page(pages);
-
-               prefetchw(&page->flags);
-               list_del(&page->lru);
-
-               if (!add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
-
-                       if (!num) {
-                               num = 1;
-                               first = page;
-                               continue;
-                       }
-
-                       dprintk("%s: added to lru page: %p, page_index: %lu, first_index: %lu.\n",
-                                       __func__, page, page->index, first->index);
-
-                       if (unlikely(first->index + num != page->index) || (num > 500)) {
-                               pohmelfs_send_readpages(POHMELFS_I(mapping->host),
-                                               first, num);
-                               first = page;
-                               num = 0;
-                       }
-
-                       num++;
-               }
-       }
-       pohmelfs_send_readpages(POHMELFS_I(mapping->host), first, num);
-
-       /*
-        * This will be sync read, so when last page is processed,
-        * all previous are alerady unlocked and ready to be used.
-        */
-       return 0;
-}
-
-/*
- * Small address space operations for POHMELFS.
- */
-const struct address_space_operations pohmelfs_aops = {
-       .readpage               = pohmelfs_readpage,
-       .readpages              = pohmelfs_readpages,
-       .writepages             = pohmelfs_writepages,
-       .write_begin            = pohmelfs_write_begin,
-       .write_end              = pohmelfs_write_end,
-       .set_page_dirty         = __set_page_dirty_nobuffers,
-};
-
-static void pohmelfs_i_callback(struct rcu_head *head)
-{
-       struct inode *inode = container_of(head, struct inode, i_rcu);
-       kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode));
-}
-
-/*
- * ->destroy_inode() callback. Deletes inode from the caches
- *  and frees private data.
- */
-static void pohmelfs_destroy_inode(struct inode *inode)
-{
-       struct super_block *sb = inode->i_sb;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       /* pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); */
-
-       pohmelfs_inode_del_inode(psb, pi);
-
-       dprintk("%s: pi: %p, inode: %p, ino: %llu.\n",
-               __func__, pi, &pi->vfs_inode, pi->ino);
-       atomic_long_dec(&psb->total_inodes);
-       call_rcu(&inode->i_rcu, pohmelfs_i_callback);
-}
-
-/*
- * ->alloc_inode() callback. Allocates inode and initializes private data.
- */
-static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
-{
-       struct pohmelfs_inode *pi;
-
-       pi = kmem_cache_alloc(pohmelfs_inode_cache, GFP_NOIO);
-       if (!pi)
-               return NULL;
-
-       pi->hash_root = RB_ROOT;
-       mutex_init(&pi->offset_lock);
-
-       INIT_LIST_HEAD(&pi->sync_create_list);
-
-       INIT_LIST_HEAD(&pi->inode_entry);
-
-       pi->lock_type = 0;
-       pi->state = 0;
-       pi->total_len = 0;
-       pi->drop_count = 0;
-
-       dprintk("%s: pi: %p, inode: %p.\n", __func__, pi, &pi->vfs_inode);
-
-       atomic_long_inc(&POHMELFS_SB(sb)->total_inodes);
-
-       return &pi->vfs_inode;
-}
-
-/*
- * We want fsync() to work on POHMELFS.
- */
-static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
-       struct inode *inode = file->f_mapping->host;
-       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
-       if (!err) {
-               mutex_lock(&inode->i_mutex);
-               err = sync_inode_metadata(inode, 1);
-               mutex_unlock(&inode->i_mutex);
-       }
-       return err;
-}
-
-ssize_t pohmelfs_write(struct file *file, const char __user *buf,
-               size_t len, loff_t *ppos)
-{
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
-       struct kiocb kiocb;
-       ssize_t ret;
-       loff_t pos = *ppos;
-
-       init_sync_kiocb(&kiocb, file);
-       kiocb.ki_pos = pos;
-       kiocb.ki_left = len;
-
-       dprintk("%s: len: %zu, pos: %llu.\n", __func__, len, pos);
-
-       mutex_lock(&inode->i_mutex);
-       ret = pohmelfs_data_lock(pi, pos, len, POHMELFS_WRITE_LOCK);
-       if (ret)
-               goto err_out_unlock;
-
-       ret = __generic_file_aio_write(&kiocb, &iov, 1, &kiocb.ki_pos);
-       *ppos = kiocb.ki_pos;
-
-       mutex_unlock(&inode->i_mutex);
-       WARN_ON(ret < 0);
-
-       if (ret > 0) {
-               ssize_t err;
-
-               err = generic_write_sync(file, pos, ret);
-               if (err < 0)
-                       ret = err;
-               WARN_ON(ret < 0);
-       }
-
-       return ret;
-
-err_out_unlock:
-       mutex_unlock(&inode->i_mutex);
-       return ret;
-}
-
-static const struct file_operations pohmelfs_file_ops = {
-       .open           = generic_file_open,
-       .fsync          = pohmelfs_fsync,
-
-       .llseek         = generic_file_llseek,
-
-       .read           = do_sync_read,
-       .aio_read       = generic_file_aio_read,
-
-       .mmap           = generic_file_mmap,
-
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = generic_file_splice_write,
-
-       .write          = pohmelfs_write,
-       .aio_write      = generic_file_aio_write,
-};
-
-const struct inode_operations pohmelfs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
-};
-
-int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr)
-{
-       int err;
-
-       err = inode_change_ok(inode, attr);
-       if (err) {
-               dprintk("%s: ino: %llu, inode changes are not allowed.\n", __func__, POHMELFS_I(inode)->ino);
-               goto err_out_exit;
-       }
-
-       if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               err = vmtruncate(inode, attr->ia_size);
-               if (err) {
-                       dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
-                       goto err_out_exit;
-               }
-       }
-
-       setattr_copy(inode, attr);
-       mark_inode_dirty(inode);
-
-       dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n",
-                       __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode,
-                       inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size);
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err;
-
-       err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               goto err_out_exit;
-
-       err = security_inode_setattr(dentry, attr);
-       if (err)
-               goto err_out_exit;
-
-       err = pohmelfs_setattr_raw(inode, attr);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_send_xattr_req(struct pohmelfs_inode *pi, u64 id, u64 start,
-               const char *name, const void *value, size_t attrsize, int command)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-       int err, path_len, namelen = strlen(name) + 1; /* 0-byte */
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       void *data;
-
-       dprintk("%s: id: %llu, start: %llu, name: '%s', attrsize: %zu, cmd: %d.\n",
-                       __func__, id, start, name, attrsize, command);
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, namelen + path_len + attrsize, 0, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       cmd = netfs_trans_current(t);
-       data = cmd + 1;
-
-       path_len = pohmelfs_construct_path_string(pi, data, path_len);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_put;
-       }
-       data += path_len;
-
-       /*
-        * 'name' is a NUL-terminated string already and
-        * 'namelen' includes 0-byte.
-        */
-       memcpy(data, name, namelen);
-       data += namelen;
-
-       memcpy(data, value, attrsize);
-
-       cmd->cmd = command;
-       cmd->id = id;
-       cmd->start = start;
-       cmd->size = attrsize + namelen + path_len;
-       cmd->ext = path_len;
-       cmd->csize = 0;
-       cmd->cpad = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, namelen + path_len + attrsize);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_put:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_setxattr(struct dentry *dentry, const char *name,
-               const void *value, size_t attrsize, int flags)
-{
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-
-       if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
-               return -EOPNOTSUPP;
-
-       return pohmelfs_send_xattr_req(pi, flags, attrsize, name,
-                       value, attrsize, NETFS_XATTR_SET);
-}
-
-static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name,
-               void *value, size_t attrsize)
-{
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct pohmelfs_mcache *m;
-       int err;
-       long timeout = psb->mcache_timeout;
-
-       if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
-               return -EOPNOTSUPP;
-
-       m = pohmelfs_mcache_alloc(psb, 0, attrsize, value);
-       if (IS_ERR(m))
-               return PTR_ERR(m);
-
-       dprintk("%s: ino: %llu, name: '%s', size: %zu.\n",
-                       __func__, pi->ino, name, attrsize);
-
-       err = pohmelfs_send_xattr_req(pi, m->gen, attrsize, name, value, 0, NETFS_XATTR_GET);
-       if (err)
-               goto err_out_put;
-
-       do {
-               err = wait_for_completion_timeout(&m->complete, timeout);
-               if (err) {
-                       err = m->err;
-                       break;
-               }
-
-               /*
-                * This loop is a bit ugly, since it waits until reference counter
-                * hits 1 and then puts the object here. Main goal is to prevent race with
-                * the network thread, when it can start processing the given request, i.e.
-                * increase its reference counter but yet not complete it, while
-                * we will exit from ->getxattr() with timeout, and although request
-                * will not be freed (its reference counter was increased by network
-                * thread), data pointer provided by user may be released, so we will
-                * overwrite an already freed area in the network thread.
-                *
-                * Now after timeout we remove request from the cache, so it can not be
-                * found by network thread, and wait for its reference counter to hit 1,
-                * i.e. if network thread already started to process this request, we wait
-                * for it to finish, and then free object locally. If reference counter is
-                * already 1, i.e. request is not used by anyone else, we can free it without
-                * problem.
-                */
-               err = -ETIMEDOUT;
-               timeout = HZ;
-
-               pohmelfs_mcache_remove_locked(psb, m);
-       } while (atomic_read(&m->refcnt) != 1);
-
-       pohmelfs_mcache_put(psb, m);
-
-       dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
-
-       return err;
-
-err_out_put:
-       pohmelfs_mcache_put(psb, m);
-       return err;
-}
-
-static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
-       struct inode *inode = dentry->d_inode;
-#if 0
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err;
-
-       err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
-       if (err)
-               return err;
-       dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n",
-                       __func__, pi->ino, inode->i_mode, inode->i_uid,
-                       inode->i_gid, inode->i_size);
-#endif
-
-       generic_fillattr(inode, stat);
-       return 0;
-}
-
-const struct inode_operations pohmelfs_file_inode_operations = {
-       .setattr        = pohmelfs_setattr,
-       .getattr        = pohmelfs_getattr,
-       .setxattr       = pohmelfs_setxattr,
-       .getxattr       = pohmelfs_getxattr,
-};
-
-/*
- * Fill inode data: mode, size, operation callbacks and so on...
- */
-void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
-{
-       inode->i_mode = info->mode;
-       set_nlink(inode, info->nlink);
-       inode->i_uid = info->uid;
-       inode->i_gid = info->gid;
-       inode->i_blocks = info->blocks;
-       inode->i_rdev = info->rdev;
-       inode->i_size = info->size;
-       inode->i_version = info->version;
-       inode->i_blkbits = ffs(info->blocksize);
-
-       dprintk("%s: inode: %p, num: %lu/%llu inode is regular: %d, dir: %d, link: %d, mode: %o, size: %llu.\n",
-                       __func__, inode, inode->i_ino, info->ino,
-                       S_ISREG(inode->i_mode), S_ISDIR(inode->i_mode),
-                       S_ISLNK(inode->i_mode), inode->i_mode, inode->i_size);
-
-       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-
-       /*
-        * i_mapping is a pointer to i_data during inode initialization.
-        */
-       inode->i_data.a_ops = &pohmelfs_aops;
-
-       if (S_ISREG(inode->i_mode)) {
-               inode->i_fop = &pohmelfs_file_ops;
-               inode->i_op = &pohmelfs_file_inode_operations;
-       } else if (S_ISDIR(inode->i_mode)) {
-               inode->i_fop = &pohmelfs_dir_fops;
-               inode->i_op = &pohmelfs_dir_inode_ops;
-       } else if (S_ISLNK(inode->i_mode)) {
-               inode->i_op = &pohmelfs_symlink_inode_operations;
-               inode->i_fop = &pohmelfs_file_ops;
-       } else {
-               inode->i_fop = &generic_ro_fops;
-       }
-}
-
-static int pohmelfs_drop_inode(struct inode *inode)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       spin_lock(&psb->ino_lock);
-       list_del_init(&pi->inode_entry);
-       spin_unlock(&psb->ino_lock);
-
-       return generic_drop_inode(inode);
-}
-
-static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb,
-               struct list_head *head, unsigned int *count)
-{
-       struct pohmelfs_inode *pi = NULL;
-
-       spin_lock(&psb->ino_lock);
-       if (!list_empty(head)) {
-               pi = list_entry(head->next, struct pohmelfs_inode,
-                                       inode_entry);
-               list_del_init(&pi->inode_entry);
-               *count = pi->drop_count;
-               pi->drop_count = 0;
-       }
-       spin_unlock(&psb->ino_lock);
-
-       return pi;
-}
-
-static void pohmelfs_flush_transactions(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c;
-
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               pohmelfs_state_flush_transactions(&c->state);
-       }
-       mutex_unlock(&psb->state_lock);
-}
-
-/*
- * ->put_super() callback. Invoked before superblock is destroyed,
- *  so it has to clean all private data.
- */
-static void pohmelfs_put_super(struct super_block *sb)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       struct pohmelfs_inode *pi;
-       unsigned int count = 0;
-       unsigned int in_drop_list = 0;
-       struct inode *inode, *tmp;
-
-       dprintk("%s.\n", __func__);
-
-       /*
-        * Kill pending transactions, which could affect inodes in-flight.
-        */
-       pohmelfs_flush_transactions(psb);
-
-       while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) {
-               inode = &pi->vfs_inode;
-
-               dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
-                               __func__, pi->ino, pi, inode, count);
-
-               if (atomic_read(&inode->i_count) != count) {
-                       printk("%s: ino: %llu, pi: %p, inode: %p, count: %u, i_count: %d.\n",
-                                       __func__, pi->ino, pi, inode, count,
-                                       atomic_read(&inode->i_count));
-                       count = atomic_read(&inode->i_count);
-                       in_drop_list++;
-               }
-
-               while (count--)
-                       iput(&pi->vfs_inode);
-       }
-
-       list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list) {
-               pi = POHMELFS_I(inode);
-
-               dprintk("%s: ino: %llu, pi: %p, inode: %p, i_count: %u.\n",
-                               __func__, pi->ino, pi, inode, atomic_read(&inode->i_count));
-
-               /*
-                * These are special inodes, they were created during
-                * directory reading or lookup, and were not bound to dentry,
-                * so they live here with reference counter being 1 and prevent
-                * umount from succeed since it believes that they are busy.
-                */
-               count = atomic_read(&inode->i_count);
-               if (count) {
-                       list_del_init(&inode->i_sb_list);
-                       while (count--)
-                               iput(&pi->vfs_inode);
-               }
-       }
-
-       psb->trans_scan_timeout = psb->drop_scan_timeout = 0;
-       cancel_delayed_work_sync(&psb->dwork);
-       cancel_delayed_work_sync(&psb->drop_dwork);
-       flush_scheduled_work();
-
-       dprintk("%s: stopped workqueues.\n", __func__);
-
-       pohmelfs_crypto_exit(psb);
-       pohmelfs_state_exit(psb);
-
-       bdi_destroy(&psb->bdi);
-
-       kfree(psb);
-       sb->s_fs_info = NULL;
-}
-
-static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-       struct super_block *sb = dentry->d_sb;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-
-       /*
-        * There are no filesystem size limits yet.
-        */
-       memset(buf, 0, sizeof(struct kstatfs));
-
-       buf->f_type = POHMELFS_MAGIC_NUM; /* 'POH.' */
-       buf->f_bsize = sb->s_blocksize;
-       buf->f_files = psb->ino;
-       buf->f_namelen = 255;
-       buf->f_files = atomic_long_read(&psb->total_inodes);
-       buf->f_bfree = buf->f_bavail = psb->avail_size >> PAGE_SHIFT;
-       buf->f_blocks = psb->total_size >> PAGE_SHIFT;
-
-       dprintk("%s: total: %llu, avail: %llu, inodes: %llu, bsize: %lu.\n",
-               __func__, psb->total_size, psb->avail_size, buf->f_files, sb->s_blocksize);
-
-       return 0;
-}
-
-static int pohmelfs_show_options(struct seq_file *seq, struct dentry *root)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
-
-       seq_printf(seq, ",idx=%u", psb->idx);
-       seq_printf(seq, ",trans_scan_timeout=%u", jiffies_to_msecs(psb->trans_scan_timeout));
-       seq_printf(seq, ",drop_scan_timeout=%u", jiffies_to_msecs(psb->drop_scan_timeout));
-       seq_printf(seq, ",wait_on_page_timeout=%u", jiffies_to_msecs(psb->wait_on_page_timeout));
-       seq_printf(seq, ",trans_retries=%u", psb->trans_retries);
-       seq_printf(seq, ",crypto_thread_num=%u", psb->crypto_thread_num);
-       seq_printf(seq, ",trans_max_pages=%u", psb->trans_max_pages);
-       seq_printf(seq, ",mcache_timeout=%u", jiffies_to_msecs(psb->mcache_timeout));
-       if (psb->crypto_fail_unsupported)
-               seq_printf(seq, ",crypto_fail_unsupported");
-
-       return 0;
-}
-
-enum {
-       pohmelfs_opt_idx,
-       pohmelfs_opt_crypto_thread_num,
-       pohmelfs_opt_trans_max_pages,
-       pohmelfs_opt_crypto_fail_unsupported,
-
-       /* Remountable options */
-       pohmelfs_opt_trans_scan_timeout,
-       pohmelfs_opt_drop_scan_timeout,
-       pohmelfs_opt_wait_on_page_timeout,
-       pohmelfs_opt_trans_retries,
-       pohmelfs_opt_mcache_timeout,
-};
-
-static struct match_token pohmelfs_tokens[] = {
-       {pohmelfs_opt_idx, "idx=%u"},
-       {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"},
-       {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"},
-       {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"},
-       {pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"},
-       {pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"},
-       {pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"},
-       {pohmelfs_opt_trans_retries, "trans_retries=%u"},
-       {pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"},
-};
-
-static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb, int remount)
-{
-       char *p;
-       substring_t args[MAX_OPT_ARGS];
-       int option, err;
-
-       if (!options)
-               return 0;
-
-       while ((p = strsep(&options, ",")) != NULL) {
-               int token;
-               if (!*p)
-                       continue;
-
-               token = match_token(p, pohmelfs_tokens, args);
-
-               err = match_int(&args[0], &option);
-               if (err)
-                       return err;
-
-               if (remount && token <= pohmelfs_opt_crypto_fail_unsupported)
-                       continue;
-
-               switch (token) {
-               case pohmelfs_opt_idx:
-                       psb->idx = option;
-                       break;
-               case pohmelfs_opt_trans_scan_timeout:
-                       psb->trans_scan_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_drop_scan_timeout:
-                       psb->drop_scan_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_wait_on_page_timeout:
-                       psb->wait_on_page_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_mcache_timeout:
-                       psb->mcache_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_trans_retries:
-                       psb->trans_retries = option;
-                       break;
-               case pohmelfs_opt_crypto_thread_num:
-                       psb->crypto_thread_num = option;
-                       break;
-               case pohmelfs_opt_trans_max_pages:
-                       psb->trans_max_pages = option;
-                       break;
-               case pohmelfs_opt_crypto_fail_unsupported:
-                       psb->crypto_fail_unsupported = 1;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-static int pohmelfs_remount(struct super_block *sb, int *flags, char *data)
-{
-       int err;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       unsigned long old_sb_flags = sb->s_flags;
-
-       err = pohmelfs_parse_options(data, psb, 1);
-       if (err)
-               goto err_out_restore;
-
-       if (!(*flags & MS_RDONLY))
-               sb->s_flags &= ~MS_RDONLY;
-       return 0;
-
-err_out_restore:
-       sb->s_flags = old_sb_flags;
-       return err;
-}
-
-static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count)
-{
-       struct inode *inode = &pi->vfs_inode;
-
-       dprintk("%s: %p: ino: %llu, owned: %d.\n",
-               __func__, inode, pi->ino, test_bit(NETFS_INODE_OWNED, &pi->state));
-
-       mutex_lock(&inode->i_mutex);
-       if (test_and_clear_bit(NETFS_INODE_OWNED, &pi->state)) {
-               filemap_fdatawrite(inode->i_mapping);
-               inode->i_sb->s_op->write_inode(inode, 0);
-       }
-
-#ifdef POHMELFS_TRUNCATE_ON_INODE_FLUSH
-       truncate_inode_pages(inode->i_mapping, 0);
-#endif
-
-       pohmelfs_data_unlock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
-       mutex_unlock(&inode->i_mutex);
-}
-
-static void pohmelfs_put_inode_count(struct pohmelfs_inode *pi, unsigned int count)
-{
-       dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
-                       __func__, pi->ino, pi, &pi->vfs_inode, count);
-
-       if (test_and_clear_bit(NETFS_INODE_NEED_FLUSH, &pi->state))
-               pohmelfs_flush_inode(pi, count);
-
-       while (count--)
-               iput(&pi->vfs_inode);
-}
-
-static void pohmelfs_drop_scan(struct work_struct *work)
-{
-       struct pohmelfs_sb *psb =
-               container_of(work, struct pohmelfs_sb, drop_dwork.work);
-       struct pohmelfs_inode *pi;
-       unsigned int count = 0;
-
-       while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count)))
-               pohmelfs_put_inode_count(pi, count);
-
-       pohmelfs_check_states(psb);
-
-       if (psb->drop_scan_timeout)
-               schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
-}
-
-/*
- * Run through all transactions starting from the oldest,
- * drop transaction from current state and try to send it
- * to all remote nodes, which are currently installed.
- */
-static void pohmelfs_trans_scan_state(struct netfs_state *st)
-{
-       struct rb_node *rb_node;
-       struct netfs_trans_dst *dst;
-       struct pohmelfs_sb *psb = st->psb;
-       unsigned int timeout = psb->trans_scan_timeout;
-       struct netfs_trans *t;
-       int err;
-
-       mutex_lock(&st->trans_lock);
-       for (rb_node = rb_first(&st->trans_root); rb_node; ) {
-               dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
-               t = dst->trans;
-
-               if (timeout && time_after(dst->send_time + timeout, jiffies)
-                               && dst->retries == 0)
-                       break;
-
-               dprintk("%s: t: %p, gen: %u, st: %p, retries: %u, max: %u.\n",
-                       __func__, t, t->gen, st, dst->retries, psb->trans_retries);
-               netfs_trans_get(t);
-
-               rb_node = rb_next(rb_node);
-
-               err = -ETIMEDOUT;
-               if (timeout && (++dst->retries < psb->trans_retries))
-                       err = netfs_trans_resend(t, psb);
-
-               if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) {
-                       if (netfs_trans_remove_nolock(dst, st))
-                               netfs_trans_drop_dst_nostate(dst);
-               }
-
-               t->result = err;
-               netfs_trans_put(t);
-       }
-       mutex_unlock(&st->trans_lock);
-}
-
-/*
- * Walk through all installed network states and resend all
- * transactions, which are old enough.
- */
-static void pohmelfs_trans_scan(struct work_struct *work)
-{
-       struct pohmelfs_sb *psb =
-               container_of(work, struct pohmelfs_sb, dwork.work);
-       struct netfs_state *st;
-       struct pohmelfs_config *c;
-
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               pohmelfs_trans_scan_state(st);
-       }
-       mutex_unlock(&psb->state_lock);
-
-       /*
-        * If no timeout specified then system is in the middle of umount process,
-        * so no need to reschedule scanning process again.
-        */
-       if (psb->trans_scan_timeout)
-               schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
-}
-
-int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
-               unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start)
-{
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       int err = 0, sz;
-       struct netfs_trans *t;
-       int path_len, addon_len = 0;
-       void *data;
-       struct netfs_inode_info *info;
-       struct netfs_cmd *cmd;
-
-       dprintk("%s: ino: %llu, cmd: %u, addon: %p.\n", __func__, pi->ino, cmd_op, addon);
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       if (addon)
-               addon_len = strlen(addon) + 1; /* 0-byte */
-       sz = addon_len;
-
-       if (cmd_op == NETFS_INODE_INFO)
-               sz += sizeof(struct netfs_inode_info);
-
-       t = netfs_trans_alloc(psb, sz + path_len, flags, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-       t->complete = complete;
-       t->private = priv;
-
-       cmd = netfs_trans_current(t);
-       data = (void *)(cmd + 1);
-
-       if (cmd_op == NETFS_INODE_INFO) {
-               info = (struct netfs_inode_info *)(cmd + 1);
-               data = (void *)(info + 1);
-
-               /*
-                * We are under i_mutex, can read and change whatever we want...
-                */
-               info->mode = inode->i_mode;
-               info->nlink = inode->i_nlink;
-               info->uid = inode->i_uid;
-               info->gid = inode->i_gid;
-               info->blocks = inode->i_blocks;
-               info->rdev = inode->i_rdev;
-               info->size = inode->i_size;
-               info->version = inode->i_version;
-
-               netfs_convert_inode_info(info);
-       }
-
-       path_len = pohmelfs_construct_path_string(pi, data, path_len);
-       if (path_len < 0)
-               goto err_out_free;
-
-       dprintk("%s: path_len: %d.\n", __func__, path_len);
-
-       if (addon) {
-               path_len--; /* Do not place null-byte before the addon */
-               path_len += sprintf(data + path_len, "/%s", addon) + 1; /* 0 - byte */
-       }
-
-       sz += path_len;
-
-       cmd->cmd = cmd_op;
-       cmd->ext = path_len;
-       cmd->size = sz;
-       cmd->id = id;
-       cmd->start = start;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, sz);
-
-       /*
-        * Note, that it is possible to leak error here: transaction callback will not
-        * be invoked for allocation path failure.
-        */
-       return netfs_trans_finish(t, psb);
-
-err_out_free:
-       netfs_trans_free(t);
-err_out_exit:
-       if (complete)
-               complete(NULL, 0, priv, err);
-       return err;
-}
-
-int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
-               netfs_trans_complete_t complete, void *priv, u64 start)
-{
-       return pohmelfs_meta_command_data(pi, pi->ino, cmd_op, NULL, flags, complete, priv, start);
-}
-
-/*
- * Send request and wait for POHMELFS root capabilities response,
- * which will update server's informaion about size of the export,
- * permissions, number of objects, available size and so on.
- */
-static int pohmelfs_root_handshake(struct pohmelfs_sb *psb)
-{
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       int err = -ENOMEM;
-
-       t = netfs_trans_alloc(psb, 0, 0, 0);
-       if (!t)
-               goto err_out_exit;
-
-       cmd = netfs_trans_current(t);
-
-       cmd->cmd = NETFS_CAPABILITIES;
-       cmd->id = POHMELFS_ROOT_CAPABILITIES;
-       cmd->size = 0;
-       cmd->start = 0;
-       cmd->ext = 0;
-       cmd->csize = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, 0);
-
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_exit;
-
-       psb->flags = ~0;
-       err = wait_event_interruptible_timeout(psb->wait,
-                       (psb->flags != ~0),
-                       psb->wait_on_page_timeout);
-       if (!err)
-               err = -ETIMEDOUT;
-       else if (err > 0)
-               err = -psb->flags;
-
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_show_stats(struct seq_file *m, struct dentry *root)
-{
-       struct netfs_state *st;
-       struct pohmelfs_ctl *ctl;
-       struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
-       struct pohmelfs_config *c;
-
-       mutex_lock(&psb->state_lock);
-
-       seq_printf(m, "\nidx addr(:port) socket_type protocol active priority permissions\n");
-
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-               ctl = &st->ctl;
-
-               seq_printf(m, "%u ", ctl->idx);
-               if (ctl->addr.sa_family == AF_INET) {
-                       struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
-                       seq_printf(m, "%pI4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
-               } else if (ctl->addr.sa_family == AF_INET6) {
-                       struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
-                       seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port));
-               } else {
-                       unsigned int i;
-                       for (i = 0; i < ctl->addrlen; ++i)
-                               seq_printf(m, "%02x.", ctl->addr.addr[i]);
-               }
-
-               seq_printf(m, " %u %u %d %u %x\n",
-                               ctl->type, ctl->proto,
-                               st->socket != NULL,
-                               ctl->prio, ctl->perm);
-       }
-       mutex_unlock(&psb->state_lock);
-
-       return 0;
-}
-
-static const struct super_operations pohmelfs_sb_ops = {
-       .alloc_inode    = pohmelfs_alloc_inode,
-       .destroy_inode  = pohmelfs_destroy_inode,
-       .drop_inode     = pohmelfs_drop_inode,
-       .write_inode    = pohmelfs_write_inode,
-       .put_super      = pohmelfs_put_super,
-       .remount_fs     = pohmelfs_remount,
-       .statfs         = pohmelfs_statfs,
-       .show_options   = pohmelfs_show_options,
-       .show_stats     = pohmelfs_show_stats,
-};
-
-/*
- * Allocate private superblock and create root dir.
- */
-static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
-{
-       struct pohmelfs_sb *psb;
-       int err = -ENOMEM;
-       struct inode *root;
-       struct pohmelfs_inode *npi;
-       struct qstr str;
-
-       psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL);
-       if (!psb)
-               goto err_out_exit;
-
-       err = bdi_init(&psb->bdi);
-       if (err)
-               goto err_out_free_sb;
-
-       err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
-       if (err) {
-               bdi_destroy(&psb->bdi);
-               goto err_out_free_sb;
-       }
-
-       sb->s_fs_info = psb;
-       sb->s_op = &pohmelfs_sb_ops;
-       sb->s_magic = POHMELFS_MAGIC_NUM;
-       sb->s_maxbytes = MAX_LFS_FILESIZE;
-       sb->s_blocksize = PAGE_SIZE;
-       sb->s_bdi = &psb->bdi;
-
-       psb->sb = sb;
-
-       psb->ino = 2;
-       psb->idx = 0;
-       psb->active_state = NULL;
-       psb->trans_retries = 5;
-       psb->trans_data_size = PAGE_SIZE;
-       psb->drop_scan_timeout = msecs_to_jiffies(1000);
-       psb->trans_scan_timeout = msecs_to_jiffies(5000);
-       psb->wait_on_page_timeout = msecs_to_jiffies(5000);
-       init_waitqueue_head(&psb->wait);
-
-       spin_lock_init(&psb->ino_lock);
-
-       INIT_LIST_HEAD(&psb->drop_list);
-
-       mutex_init(&psb->mcache_lock);
-       psb->mcache_root = RB_ROOT;
-       psb->mcache_timeout = msecs_to_jiffies(5000);
-       atomic_long_set(&psb->mcache_gen, 0);
-
-       psb->trans_max_pages = 100;
-
-       psb->crypto_align_size = 16;
-       psb->crypto_attached_size = 0;
-       psb->hash_strlen = 0;
-       psb->cipher_strlen = 0;
-       psb->perform_crypto = 0;
-       psb->crypto_thread_num = 2;
-       psb->crypto_fail_unsupported = 0;
-       mutex_init(&psb->crypto_thread_lock);
-       INIT_LIST_HEAD(&psb->crypto_ready_list);
-       INIT_LIST_HEAD(&psb->crypto_active_list);
-
-       atomic_set(&psb->trans_gen, 1);
-       atomic_long_set(&psb->total_inodes, 0);
-
-       mutex_init(&psb->state_lock);
-       INIT_LIST_HEAD(&psb->state_list);
-
-       err = pohmelfs_parse_options((char *) data, psb, 0);
-       if (err)
-               goto err_out_free_bdi;
-
-       err = pohmelfs_copy_crypto(psb);
-       if (err)
-               goto err_out_free_bdi;
-
-       err = pohmelfs_state_init(psb);
-       if (err)
-               goto err_out_free_strings;
-
-       err = pohmelfs_crypto_init(psb);
-       if (err)
-               goto err_out_state_exit;
-
-       err = pohmelfs_root_handshake(psb);
-       if (err)
-               goto err_out_crypto_exit;
-
-       str.name = "/";
-       str.hash = jhash("/", 1, 0);
-       str.len = 1;
-
-       npi = pohmelfs_create_entry_local(psb, NULL, &str, 0, 0755|S_IFDIR);
-       if (IS_ERR(npi)) {
-               err = PTR_ERR(npi);
-               goto err_out_crypto_exit;
-       }
-       set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
-       clear_bit(NETFS_INODE_OWNED, &npi->state);
-
-       root = &npi->vfs_inode;
-
-       sb->s_root = d_alloc_root(root);
-       if (!sb->s_root)
-               goto err_out_put_root;
-
-       INIT_DELAYED_WORK(&psb->drop_dwork, pohmelfs_drop_scan);
-       schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
-
-       INIT_DELAYED_WORK(&psb->dwork, pohmelfs_trans_scan);
-       schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
-
-       return 0;
-
-err_out_put_root:
-       iput(root);
-err_out_crypto_exit:
-       pohmelfs_crypto_exit(psb);
-err_out_state_exit:
-       pohmelfs_state_exit(psb);
-err_out_free_strings:
-       kfree(psb->cipher_string);
-       kfree(psb->hash_string);
-err_out_free_bdi:
-       bdi_destroy(&psb->bdi);
-err_out_free_sb:
-       kfree(psb);
-err_out_exit:
-
-       dprintk("%s: err: %d.\n", __func__, err);
-       return err;
-}
-
-/*
- * Some VFS magic here...
- */
-static struct dentry *pohmelfs_mount(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
-{
-       return mount_nodev(fs_type, flags, data, pohmelfs_fill_super);
-}
-
-/*
- * We need this to sync all inodes earlier, since when writeback
- * is invoked from the umount/mntput path dcache is already shrunk,
- * see generic_shutdown_super(), and no inodes can access the path.
- */
-static void pohmelfs_kill_super(struct super_block *sb)
-{
-       sync_inodes_sb(sb);
-       kill_anon_super(sb);
-}
-
-static struct file_system_type pohmel_fs_type = {
-       .owner          = THIS_MODULE,
-       .name           = "pohmel",
-       .mount          = pohmelfs_mount,
-       .kill_sb        = pohmelfs_kill_super,
-};
-
-/*
- * Cache and module initializations and freeing routings.
- */
-static void pohmelfs_init_once(void *data)
-{
-       struct pohmelfs_inode *pi = data;
-
-       inode_init_once(&pi->vfs_inode);
-}
-
-static int __init pohmelfs_init_inodecache(void)
-{
-       pohmelfs_inode_cache = kmem_cache_create("pohmelfs_inode_cache",
-                               sizeof(struct pohmelfs_inode),
-                               0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
-                               pohmelfs_init_once);
-       if (!pohmelfs_inode_cache)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void pohmelfs_destroy_inodecache(void)
-{
-       kmem_cache_destroy(pohmelfs_inode_cache);
-}
-
-static int __init init_pohmel_fs(void)
-{
-       int err;
-
-       err = pohmelfs_config_init();
-       if (err)
-               goto err_out_exit;
-
-       err = pohmelfs_init_inodecache();
-       if (err)
-               goto err_out_config_exit;
-
-       err = pohmelfs_mcache_init();
-       if (err)
-               goto err_out_destroy;
-
-       err = netfs_trans_init();
-       if (err)
-               goto err_out_mcache_exit;
-
-       err = register_filesystem(&pohmel_fs_type);
-       if (err)
-               goto err_out_trans;
-
-       return 0;
-
-err_out_trans:
-       netfs_trans_exit();
-err_out_mcache_exit:
-       pohmelfs_mcache_exit();
-err_out_destroy:
-       pohmelfs_destroy_inodecache();
-err_out_config_exit:
-       pohmelfs_config_exit();
-err_out_exit:
-       return err;
-}
-
-static void __exit exit_pohmel_fs(void)
-{
-       unregister_filesystem(&pohmel_fs_type);
-       pohmelfs_destroy_inodecache();
-       pohmelfs_mcache_exit();
-       pohmelfs_config_exit();
-       netfs_trans_exit();
-}
-
-module_init(init_pohmel_fs);
-module_exit(exit_pohmel_fs);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
-MODULE_DESCRIPTION("Pohmel filesystem");
diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c
deleted file mode 100644 (file)
index 6710114..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/backing-dev.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/mempool.h>
-
-#include "netfs.h"
-
-static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi,
-               u64 id, u64 start, u32 size, int type)
-{
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       int path_len, err;
-       void *data;
-       struct netfs_lock *l;
-       int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info);
-
-       err = pohmelfs_path_length(pi);
-       if (err < 0)
-               goto err_out_exit;
-
-       path_len = err;
-
-       err = -ENOMEM;
-       t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize,
-                       NETFS_TRANS_SINGLE_DST, 0);
-       if (!t)
-               goto err_out_exit;
-
-       cmd = netfs_trans_current(t);
-       data = cmd + 1;
-
-       err = pohmelfs_construct_path_string(pi, data, path_len);
-       if (err < 0)
-               goto err_out_free;
-       path_len = err;
-
-       l = data + path_len;
-
-       l->start = start;
-       l->size = size;
-       l->type = type;
-       l->ino = pi->ino;
-
-       cmd->cmd = NETFS_LOCK;
-       cmd->start = 0;
-       cmd->id = id;
-       cmd->size = sizeof(struct netfs_lock) + path_len + isize;
-       cmd->ext = path_len;
-       cmd->csize = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_convert_lock(l);
-
-       if (isize) {
-               struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1);
-
-               info->mode = inode->i_mode;
-               info->nlink = inode->i_nlink;
-               info->uid = inode->i_uid;
-               info->gid = inode->i_gid;
-               info->blocks = inode->i_blocks;
-               info->rdev = inode->i_rdev;
-               info->size = inode->i_size;
-               info->version = inode->i_version;
-
-               netfs_convert_inode_info(info);
-       }
-
-       netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_free:
-       netfs_trans_free(t);
-err_out_exit:
-       printk("%s: err: %d.\n", __func__, err);
-       return err;
-}
-
-int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-       struct pohmelfs_mcache *m;
-       int err = -ENOMEM;
-       struct iattr iattr;
-       struct inode *inode = &pi->vfs_inode;
-
-       dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
-                       "type: %d, locked as: %d, owned: %d.\n",
-                       __func__, &pi->vfs_inode, pi->ino,
-                       start, size, type, pi->lock_type,
-                       !!test_bit(NETFS_INODE_OWNED, &pi->state));
-
-       if (!pohmelfs_need_lock(pi, type))
-               return 0;
-
-       m = pohmelfs_mcache_alloc(psb, start, size, NULL);
-       if (IS_ERR(m))
-               return PTR_ERR(m);
-
-       err = pohmelfs_send_lock_trans(pi, m->gen, start, size,
-                       type | POHMELFS_LOCK_GRAB);
-       if (err)
-               goto err_out_put;
-
-       err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout);
-       if (err)
-               err = m->err;
-       else
-               err = -ETIMEDOUT;
-
-       if (err) {
-               printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
-                       __func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err);
-       }
-
-       if (err && (err != -ENOENT))
-               goto err_out_put;
-
-       if (!err) {
-               netfs_convert_inode_info(&m->info);
-
-               iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME;
-               iattr.ia_mode = m->info.mode;
-               iattr.ia_uid = m->info.uid;
-               iattr.ia_gid = m->info.gid;
-               iattr.ia_size = m->info.size;
-               iattr.ia_atime = CURRENT_TIME;
-
-               dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
-                       __func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size);
-
-               err = pohmelfs_setattr_raw(inode, &iattr);
-               if (!err) {
-                       struct dentry *dentry = d_find_alias(inode);
-                       if (dentry) {
-                               fsnotify_change(dentry, iattr.ia_valid);
-                               dput(dentry);
-                       }
-               }
-       }
-
-       pi->lock_type = type;
-       set_bit(NETFS_INODE_OWNED, &pi->state);
-
-       pohmelfs_mcache_put(psb, m);
-
-       return 0;
-
-err_out_put:
-       pohmelfs_mcache_put(psb, m);
-       return err;
-}
-
-int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
-{
-       dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n",
-                       __func__, &pi->vfs_inode, pi->ino, start, size, type);
-       pi->lock_type = 0;
-       clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state);
-       clear_bit(NETFS_INODE_OWNED, &pi->state);
-       return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type);
-}
diff --git a/drivers/staging/pohmelfs/mcache.c b/drivers/staging/pohmelfs/mcache.c
deleted file mode 100644 (file)
index e22665c..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-
-#include "netfs.h"
-
-static struct kmem_cache *pohmelfs_mcache_cache;
-static mempool_t *pohmelfs_mcache_pool;
-
-static inline int pohmelfs_mcache_cmp(u64 gen, u64 new)
-{
-       if (gen < new)
-               return 1;
-       if (gen > new)
-               return -1;
-       return 0;
-}
-
-struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen)
-{
-       struct rb_root *root = &psb->mcache_root;
-       struct rb_node *n = root->rb_node;
-       struct pohmelfs_mcache *tmp, *ret = NULL;
-       int cmp;
-
-       while (n) {
-               tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry);
-
-               cmp = pohmelfs_mcache_cmp(tmp->gen, gen);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else {
-                       ret = tmp;
-                       pohmelfs_mcache_get(ret);
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       struct rb_root *root = &psb->mcache_root;
-       struct rb_node **n = &root->rb_node, *parent = NULL;
-       struct pohmelfs_mcache *ret = NULL, *tmp;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry);
-
-               cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       if (ret)
-               return -EEXIST;
-
-       rb_link_node(&m->mcache_entry, parent, n);
-       rb_insert_color(&m->mcache_entry, root);
-
-       return 0;
-}
-
-static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       if (m && m->mcache_entry.rb_parent_color) {
-               rb_erase(&m->mcache_entry, &psb->mcache_root);
-               m->mcache_entry.rb_parent_color = 0;
-               return 1;
-       }
-       return 0;
-}
-
-void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       mutex_lock(&psb->mcache_lock);
-       pohmelfs_mcache_remove(psb, m);
-       mutex_unlock(&psb->mcache_lock);
-}
-
-struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
-               unsigned int size, void *data)
-{
-       struct pohmelfs_mcache *m;
-       int err = -ENOMEM;
-
-       m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL);
-       if (!m)
-               goto err_out_exit;
-
-       init_completion(&m->complete);
-       m->err = 0;
-       atomic_set(&m->refcnt, 1);
-       m->data = data;
-       m->start = start;
-       m->size = size;
-       m->gen = atomic_long_inc_return(&psb->mcache_gen);
-
-       mutex_lock(&psb->mcache_lock);
-       err = pohmelfs_mcache_insert(psb, m);
-       mutex_unlock(&psb->mcache_lock);
-       if (err)
-               goto err_out_free;
-
-       return m;
-
-err_out_free:
-       mempool_free(m, pohmelfs_mcache_pool);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       pohmelfs_mcache_remove_locked(psb, m);
-
-       mempool_free(m, pohmelfs_mcache_pool);
-}
-
-int __init pohmelfs_mcache_init(void)
-{
-       pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache",
-                               sizeof(struct pohmelfs_mcache),
-                               0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL);
-       if (!pohmelfs_mcache_cache)
-               goto err_out_exit;
-
-       pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache);
-       if (!pohmelfs_mcache_pool)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       kmem_cache_destroy(pohmelfs_mcache_cache);
-err_out_exit:
-       return -ENOMEM;
-}
-
-void pohmelfs_mcache_exit(void)
-{
-       mempool_destroy(pohmelfs_mcache_pool);
-       kmem_cache_destroy(pohmelfs_mcache_cache);
-}
diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
deleted file mode 100644 (file)
index b2e9186..0000000
+++ /dev/null
@@ -1,1209 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/fsnotify.h>
-#include <linux/jhash.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/kthread.h>
-#include <linux/pagemap.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/syscalls.h>
-#include <linux/vmalloc.h>
-
-#include "netfs.h"
-
-/*
- * Async machinery lives here.
- * All commands being sent to server do _not_ require sync reply,
- * instead, if it is really needed, like readdir or readpage, caller
- * sleeps waiting for data, which will be placed into provided buffer
- * and caller will be awakened.
- *
- * Every command response can come without some listener. For example
- * readdir response will add new objects into cache without appropriate
- * request from userspace. This is used in cache coherency.
- *
- * If object is not found for given data, it is discarded.
- *
- * All requests are received by dedicated kernel thread.
- */
-
-/*
- * Basic network sending/receiving functions.
- * Blocked mode is used.
- */
-static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       BUG_ON(!size);
-
-       iov.iov_base = buf;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_DONTWAIT;
-
-       err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len,
-                       msg.msg_flags);
-       if (err <= 0) {
-               printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err);
-               if (err == 0)
-                       err = -ECONNRESET;
-       }
-
-       return err;
-}
-
-static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size)
-{
-       unsigned int revents = 0;
-       unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
-       unsigned int mask = err_mask | POLLIN;
-       int err = 0;
-
-       while (size && !err) {
-               revents = netfs_state_poll(st);
-
-               if (!(revents & mask)) {
-                       DEFINE_WAIT(wait);
-
-                       for (;;) {
-                               prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE);
-                               if (kthread_should_stop())
-                                       break;
-
-                               revents = netfs_state_poll(st);
-
-                               if (revents & mask)
-                                       break;
-
-                               if (signal_pending(current))
-                                       break;
-
-                               schedule();
-                               continue;
-                       }
-                       finish_wait(&st->thread_wait, &wait);
-               }
-
-               err = 0;
-               netfs_state_lock(st);
-               if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) {
-                       err = netfs_data_recv(st, data, size);
-                       if (err > 0) {
-                               data += err;
-                               size -= err;
-                               err = 0;
-                       } else if (err == 0)
-                               err = -ECONNRESET;
-               }
-
-               if (revents & err_mask) {
-                       printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
-                                       __func__, revents, st->socket, size, err);
-                       err = -ECONNRESET;
-               }
-               netfs_state_unlock(st);
-
-               if (err < 0) {
-                       if (netfs_state_trylock_send(st)) {
-                               netfs_state_exit(st);
-                               err = netfs_state_init(st);
-                               if (!err)
-                                       err = -EAGAIN;
-                               netfs_state_unlock_send(st);
-                       } else {
-                               st->need_reset = 1;
-                       }
-               }
-
-               if (kthread_should_stop())
-                       err = -ENODEV;
-
-               if (err)
-                       printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
-                                       "should_stop: %d, size: %u, err: %d.\n",
-                               __func__, st->socket, st->read_socket,
-                               revents, revents & err_mask, kthread_should_stop(), size, err);
-       }
-
-       return err;
-}
-
-int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       int err;
-
-       err = pohmelfs_data_recv(st, data, size);
-       if (err)
-               return err;
-
-       return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size);
-}
-
-/*
- * Polling machinery.
- */
-
-struct netfs_poll_helper {
-       poll_table              pt;
-       struct netfs_state      *st;
-};
-
-static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-       struct netfs_state *st = container_of(wait, struct netfs_state, wait);
-
-       wake_up(&st->thread_wait);
-       return 1;
-}
-
-static void netfs_queue_func(struct file *file, wait_queue_head_t *whead,
-                                poll_table *pt)
-{
-       struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st;
-
-       st->whead = whead;
-       init_waitqueue_func_entry(&st->wait, netfs_queue_wake);
-       add_wait_queue(whead, &st->wait);
-}
-
-static void netfs_poll_exit(struct netfs_state *st)
-{
-       if (st->whead) {
-               remove_wait_queue(st->whead, &st->wait);
-               st->whead = NULL;
-       }
-}
-
-static int netfs_poll_init(struct netfs_state *st)
-{
-       struct netfs_poll_helper ph;
-
-       ph.st = st;
-       init_poll_funcptr(&ph.pt, &netfs_queue_func);
-
-       st->socket->ops->poll(NULL, st->socket, &ph.pt);
-       return 0;
-}
-
-/*
- * Get response for readpage command. We search inode and page in its mapping
- * and copy data into. If it was async request, then we queue page into shared
- * data and wakeup listener, who will copy it to userspace.
- *
- * There is a work in progress of allowing to call copy_to_user() directly from
- * async receiving kernel thread.
- */
-static int pohmelfs_read_page_response(struct netfs_state *st)
-{
-       struct pohmelfs_sb *psb = st->psb;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct inode *inode;
-       struct page *page;
-       int err = 0;
-
-       if (cmd->size > PAGE_CACHE_SIZE) {
-               err = -EINVAL;
-               goto err_out_exit;
-       }
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
-               err = -ENOENT;
-               goto err_out_exit;
-       }
-
-       page = find_get_page(inode->i_mapping, cmd->start >> PAGE_CACHE_SHIFT);
-       if (!page || !PageLocked(page)) {
-               printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
-                               __func__, page, cmd->id, cmd->start, cmd->start >> PAGE_CACHE_SHIFT);
-
-               while (cmd->size) {
-                       unsigned int sz = min(cmd->size, st->size);
-
-                       err = pohmelfs_data_recv(st, st->data, sz);
-                       if (err)
-                               break;
-
-                       cmd->size -= sz;
-               }
-
-               err = -ENODEV;
-               if (page)
-                       goto err_out_page_put;
-               goto err_out_put;
-       }
-
-       if (cmd->size) {
-               void *addr;
-
-               addr = kmap(page);
-               err = pohmelfs_data_recv(st, addr, cmd->size);
-               kunmap(page);
-
-               if (err)
-                       goto err_out_page_unlock;
-       }
-
-       dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
-               __func__, page, cmd->start, cmd->size, PageLocked(page));
-
-       SetPageChecked(page);
-       if ((psb->hash_string || psb->cipher_string) && psb->perform_crypto && cmd->size) {
-               err = pohmelfs_crypto_process_input_page(&st->eng, page, cmd->size, cmd->iv);
-               if (err < 0)
-                       goto err_out_page_unlock;
-       } else {
-               SetPageUptodate(page);
-               unlock_page(page);
-               page_cache_release(page);
-       }
-
-       pohmelfs_put_inode(POHMELFS_I(inode));
-       wake_up(&st->psb->wait);
-
-       return 0;
-
-err_out_page_unlock:
-       SetPageError(page);
-       unlock_page(page);
-err_out_page_put:
-       page_cache_release(page);
-err_out_put:
-       pohmelfs_put_inode(POHMELFS_I(inode));
-err_out_exit:
-       wake_up(&st->psb->wait);
-       return err;
-}
-
-static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str,
-               struct netfs_inode_info *info)
-{
-       struct inode *inode;
-       struct pohmelfs_name *n;
-       int err = 0;
-       u64 ino = 0;
-
-       mutex_lock(&parent->offset_lock);
-       n = pohmelfs_search_hash(parent, str->hash);
-       if (n)
-               ino = n->ino;
-       mutex_unlock(&parent->offset_lock);
-
-       if (!ino)
-               goto out;
-
-       inode = ilookup(parent->vfs_inode.i_sb, ino);
-       if (!inode)
-               goto out;
-
-       dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino);
-
-       pohmelfs_fill_inode(inode, info);
-       pohmelfs_put_inode(POHMELFS_I(inode));
-       err = -EEXIST;
-out:
-       return err;
-}
-
-/*
- * Readdir response from server. If special field is set, we wakeup
- * listener (readdir() call), which will copy data to userspace.
- */
-static int pohmelfs_readdir_response(struct netfs_state *st)
-{
-       struct inode *inode;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_inode_info *info;
-       struct pohmelfs_inode *parent = NULL, *npi;
-       int err = 0, last = cmd->ext;
-       struct qstr str;
-
-       if (cmd->size > st->size)
-               return -EINVAL;
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-       parent = POHMELFS_I(inode);
-
-       if (!cmd->size && cmd->start) {
-               err = -cmd->start;
-               goto out;
-       }
-
-       if (cmd->size) {
-               char *name;
-
-               err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
-               if (err)
-                       goto err_out_put;
-
-               info = (struct netfs_inode_info *)(st->data);
-
-               name = (char *)(info + 1);
-               str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
-               name[str.len] = 0;
-               str.name = name;
-               str.hash = jhash(str.name, str.len, 0);
-
-               netfs_convert_inode_info(info);
-
-               if (parent) {
-                       err = pohmelfs_check_name(parent, &str, info);
-                       if (err) {
-                               if (err == -EEXIST)
-                                       err = 0;
-                               goto out;
-                       }
-               }
-
-               info->ino = cmd->start;
-               if (!info->ino)
-                       info->ino = pohmelfs_new_ino(st->psb);
-
-               dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
-                               __func__, parent->ino, info->ino, str.name, str.hash, str.len,
-                               info->mode);
-
-               npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
-               if (IS_ERR(npi)) {
-                       err = PTR_ERR(npi);
-
-                       if (err != -EEXIST)
-                               goto err_out_put;
-               } else {
-                       struct dentry *dentry, *alias, *pd;
-
-                       set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
-                       clear_bit(NETFS_INODE_OWNED, &npi->state);
-
-                       pd = d_find_alias(&parent->vfs_inode);
-                       if (pd) {
-                               str.hash = full_name_hash(str.name, str.len);
-                               dentry = d_alloc(pd, &str);
-                               if (dentry) {
-                                       alias = d_materialise_unique(dentry, &npi->vfs_inode);
-                                       if (alias)
-                                               dput(alias);
-                               }
-
-                               dput(dentry);
-                               dput(pd);
-                       }
-               }
-       }
-out:
-       if (last) {
-               set_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
-               set_bit(NETFS_INODE_REMOTE_SYNCED, &parent->state);
-               wake_up(&st->psb->wait);
-       }
-       pohmelfs_put_inode(parent);
-
-       return err;
-
-err_out_put:
-       clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
-       printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__, parent->ino, cmd->start, cmd->id);
-       pohmelfs_put_inode(parent);
-       wake_up(&st->psb->wait);
-       return err;
-}
-
-/*
- * Lookup command response.
- * It searches for inode to be looked at (if it exists) and substitutes
- * its inode information (size, permission, mode and so on), if inode does
- * not exist, new one will be created and inserted into caches.
- */
-static int pohmelfs_lookup_response(struct netfs_state *st)
-{
-       struct inode *inode = NULL;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_inode_info *info;
-       struct pohmelfs_inode *parent = NULL, *npi;
-       int err = -EINVAL;
-       char *name;
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
-                               __func__, cmd->id, cmd->start, cmd->size);
-               err = -ENOENT;
-               goto err_out_exit;
-       }
-       parent = POHMELFS_I(inode);
-
-       if (!cmd->size) {
-               err = -cmd->start;
-               goto err_out_put;
-       }
-
-       if (cmd->size < sizeof(struct netfs_inode_info)) {
-               printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
-                               __func__, cmd->id, cmd->start, cmd->size);
-               err = -EINVAL;
-               goto err_out_put;
-       }
-
-       err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
-       if (err)
-               goto err_out_put;
-
-       info = (struct netfs_inode_info *)(st->data);
-       name = (char *)(info + 1);
-
-       netfs_convert_inode_info(info);
-
-       info->ino = cmd->start;
-       if (!info->ino)
-               info->ino = pohmelfs_new_ino(st->psb);
-
-       dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
-                       __func__, parent->ino, info->ino, name, cmd->start);
-
-       if (cmd->start)
-               npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0);
-       else {
-               struct qstr str;
-
-               str.name = name;
-               str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
-               str.hash = jhash(name, str.len, 0);
-
-               npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
-       }
-       if (IS_ERR(npi)) {
-               err = PTR_ERR(npi);
-
-               if (err != -EEXIST)
-                       goto err_out_put;
-       } else {
-               set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
-               clear_bit(NETFS_INODE_OWNED, &npi->state);
-       }
-
-       clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-       pohmelfs_put_inode(parent);
-
-       wake_up(&st->psb->wait);
-
-       return 0;
-
-err_out_put:
-       pohmelfs_put_inode(parent);
-err_out_exit:
-       clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-       wake_up(&st->psb->wait);
-       printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
-                       __func__, inode, cmd->id, cmd->start, cmd->size, err);
-       return err;
-}
-
-/*
- * Create response, just marks local inode as 'created', so that writeback
- * for any of its children (or own) would not try to sync it again.
- */
-static int pohmelfs_create_response(struct netfs_state *st)
-{
-       struct inode *inode;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct pohmelfs_inode *pi;
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu, start: %llu.\n",
-                               __func__, cmd->id, cmd->start);
-               goto err_out_exit;
-       }
-
-       pi = POHMELFS_I(inode);
-
-       /*
-        * To lock or not to lock?
-        * We actually do not care if it races...
-        */
-       if (cmd->start)
-               make_bad_inode(inode);
-       set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
-       pohmelfs_put_inode(pi);
-
-       wake_up(&st->psb->wait);
-       return 0;
-
-err_out_exit:
-       wake_up(&st->psb->wait);
-       return -ENOENT;
-}
-
-/*
- * Object remove response. Just says that remove request has been received.
- * Used in cache coherency protocol.
- */
-static int pohmelfs_remove_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       int err;
-
-       err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
-       if (err)
-               return err;
-
-       dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data);
-
-       return 0;
-}
-
-/*
- * Transaction reply processing.
- *
- * Find transaction based on its generation number, bump its reference counter,
- * so that none could free it under us, drop from the trees and lists and
- * drop reference counter. When it hits zero (when all destinations replied
- * and all timeout handled by async scanning code), completion will be called
- * and transaction will be freed.
- */
-static int pohmelfs_transaction_response(struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst;
-       struct netfs_trans *t = NULL;
-       struct netfs_cmd *cmd = &st->cmd;
-       short err = (signed)cmd->ext;
-
-       mutex_lock(&st->trans_lock);
-       dst = netfs_trans_search(st, cmd->start);
-       if (dst) {
-               netfs_trans_remove_nolock(dst, st);
-               t = dst->trans;
-       }
-       mutex_unlock(&st->trans_lock);
-
-       if (!t) {
-               printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
-                               __func__, cmd->start, cmd->id, cmd->size, cmd->ext);
-               err = -EINVAL;
-               goto out;
-       }
-
-       t->result = err;
-       netfs_trans_drop_dst_nostate(dst);
-
-out:
-       wake_up(&st->psb->wait);
-       return err;
-}
-
-/*
- * Inode metadata cache coherency message.
- */
-static int pohmelfs_page_cache_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       struct inode *inode;
-
-       dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size);
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-
-       set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state);
-       pohmelfs_put_inode(POHMELFS_I(inode));
-
-       return 0;
-}
-
-/*
- * Root capabilities response: export statistics
- * like used and available size, number of files and dirs,
- * permissions.
- */
-static int pohmelfs_root_cap_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_root_capabilities *cap;
-       struct pohmelfs_sb *psb = st->psb;
-
-       if (cmd->size != sizeof(struct netfs_root_capabilities)) {
-               psb->flags = EPROTO;
-               wake_up(&psb->wait);
-               return -EPROTO;
-       }
-
-       cap = st->data;
-
-       netfs_convert_root_capabilities(cap);
-
-       if (psb->total_size < cap->used + cap->avail)
-               psb->total_size = cap->used + cap->avail;
-       if (cap->avail)
-               psb->avail_size = cap->avail;
-       psb->state_flags = cap->flags;
-
-       if (psb->state_flags & POHMELFS_FLAGS_RO) {
-               psb->sb->s_flags |= MS_RDONLY;
-               printk(KERN_INFO "Mounting POHMELFS (%d) read-only.\n", psb->idx);
-       }
-
-       if (psb->state_flags & POHMELFS_FLAGS_XATTR)
-               printk(KERN_INFO "Mounting POHMELFS (%d) "
-                       "with extended attributes support.\n", psb->idx);
-
-       if (atomic_long_read(&psb->total_inodes) <= 1)
-               atomic_long_set(&psb->total_inodes, cap->nr_files);
-
-       dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
-               __func__, psb->total_size, psb->avail_size, psb->state_flags, cap->nr_files);
-
-       psb->flags = 0;
-       wake_up(&psb->wait);
-       return 0;
-}
-
-/*
- * Crypto capabilities of the server, where it says that
- * it supports or does not requested hash/cipher algorithms.
- */
-static int pohmelfs_crypto_cap_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_crypto_capabilities *cap;
-       struct pohmelfs_sb *psb = st->psb;
-       int err = 0;
-
-       if (cmd->size != sizeof(struct netfs_crypto_capabilities)) {
-               psb->flags = EPROTO;
-               wake_up(&psb->wait);
-               return -EPROTO;
-       }
-
-       cap = st->data;
-
-       dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
-                       __func__,
-                       psb->cipher_string, (cap->cipher_strlen) ? "SUPPORTED" : "NOT SUPPORTED",
-                       psb->hash_string, (cap->hash_strlen) ? "SUPPORTED" : "NOT SUPPORTED");
-
-       if (!cap->hash_strlen) {
-               if (psb->hash_strlen && psb->crypto_fail_unsupported)
-                       err = -ENOTSUPP;
-               psb->hash_strlen = 0;
-               kfree(psb->hash_string);
-               psb->hash_string = NULL;
-       }
-
-       if (!cap->cipher_strlen) {
-               if (psb->cipher_strlen && psb->crypto_fail_unsupported)
-                       err = -ENOTSUPP;
-               psb->cipher_strlen = 0;
-               kfree(psb->cipher_string);
-               psb->cipher_string = NULL;
-       }
-
-       return err;
-}
-
-/*
- * Capabilities handshake response.
- */
-static int pohmelfs_capabilities_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       int err = 0;
-
-       err = pohmelfs_data_recv(st, st->data, cmd->size);
-       if (err)
-               return err;
-
-       switch (cmd->id) {
-       case POHMELFS_CRYPTO_CAPABILITIES:
-                       return pohmelfs_crypto_cap_response(st);
-       case POHMELFS_ROOT_CAPABILITIES:
-                       return pohmelfs_root_cap_response(st);
-       default:
-                       break;
-       }
-       return -EINVAL;
-}
-
-/*
- * Receiving extended attribute.
- * Does not work properly if received size is more than requested one,
- * it should not happen with current request/reply model though.
- */
-static int pohmelfs_getxattr_response(struct netfs_state *st)
-{
-       struct pohmelfs_sb *psb = st->psb;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct pohmelfs_mcache *m;
-       short error = (signed short)cmd->ext, err;
-       unsigned int sz, total_size;
-
-       m = pohmelfs_mcache_search(psb, cmd->id);
-
-       dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
-               __func__, cmd->id, (m) ? m->gen : 0, error);
-
-       if (!m) {
-               printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-
-       if (cmd->size) {
-               sz = min_t(unsigned int, cmd->size, m->size);
-               err = pohmelfs_data_recv_and_check(st, m->data, sz);
-               if (err) {
-                       error = err;
-                       goto out;
-               }
-
-               m->size = sz;
-               total_size = cmd->size - sz;
-
-               while (total_size) {
-                       sz = min(total_size, st->size);
-
-                       err = pohmelfs_data_recv_and_check(st, st->data, sz);
-                       if (err) {
-                               error = err;
-                               break;
-                       }
-
-                       total_size -= sz;
-               }
-       }
-
-out:
-       m->err = error;
-       complete(&m->complete);
-       pohmelfs_mcache_put(psb, m);
-
-       return error;
-}
-
-int pohmelfs_data_lock_response(struct netfs_state *st)
-{
-       struct pohmelfs_sb *psb = st->psb;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct pohmelfs_mcache *m;
-       short err = (signed short)cmd->ext;
-       u64 id = cmd->id;
-
-       m = pohmelfs_mcache_search(psb, id);
-
-       dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
-               __func__, cmd->id, (m) ? m->gen : 0, err);
-
-       if (!m) {
-               pohmelfs_data_recv(st, st->data, cmd->size);
-               printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-
-       if (cmd->size)
-               err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size);
-
-       m->err = err;
-       complete(&m->complete);
-       pohmelfs_mcache_put(psb, m);
-
-       return err;
-}
-
-static void __inline__ netfs_state_reset(struct netfs_state *st)
-{
-       netfs_state_lock_send(st);
-       netfs_state_exit(st);
-       netfs_state_init(st);
-       netfs_state_unlock_send(st);
-}
-
-/*
- * Main receiving function, called from dedicated kernel thread.
- */
-static int pohmelfs_recv(void *data)
-{
-       int err = -EINTR;
-       struct netfs_state *st = data;
-       struct netfs_cmd *cmd = &st->cmd;
-
-       while (!kthread_should_stop()) {
-               /*
-                * If socket will be reset after this statement, then
-                * pohmelfs_data_recv() will just fail and loop will
-                * start again, so it can be done without any locks.
-                *
-                * st->read_socket is needed to prevents state machine
-                * breaking between this data reading and subsequent one
-                * in protocol specific functions during connection reset.
-                * In case of reset we have to read next command and do
-                * not expect data for old command to magically appear in
-                * new connection.
-                */
-               st->read_socket = st->socket;
-               err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd));
-               if (err) {
-                       msleep(1000);
-                       continue;
-               }
-
-               netfs_convert_cmd(cmd);
-
-               dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
-                               "ext: %u, csize: %u, cpad: %u.\n",
-                               __func__, cmd->cmd, cmd->id, cmd->start,
-                               cmd->size, cmd->ext, cmd->csize, cmd->cpad);
-
-               if (cmd->csize) {
-                       struct pohmelfs_crypto_engine *e = &st->eng;
-
-                       if (unlikely(cmd->csize > e->size/2)) {
-                               netfs_state_reset(st);
-                               continue;
-                       }
-
-                       if (e->hash && unlikely(cmd->csize != st->psb->crypto_attached_size)) {
-                               dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
-                                               "csize: %u != digest size %u.\n",
-                                               __func__, cmd->cmd, cmd->id, cmd->start, cmd->size,
-                                               cmd->csize, st->psb->crypto_attached_size);
-                               netfs_state_reset(st);
-                               continue;
-                       }
-
-                       err = pohmelfs_data_recv(st, e->data, cmd->csize);
-                       if (err) {
-                               netfs_state_reset(st);
-                               continue;
-                       }
-
-#ifdef CONFIG_POHMELFS_DEBUG
-                       {
-                               unsigned int i;
-                               unsigned char *hash = e->data;
-
-                               dprintk("%s: received hash: ", __func__);
-                               for (i = 0; i < cmd->csize; ++i)
-                                       printk("%02x ", hash[i]);
-
-                               printk("\n");
-                       }
-#endif
-                       cmd->size -= cmd->csize;
-               }
-
-               /*
-                * This should catch protocol breakage and random garbage instead of commands.
-                */
-               if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) {
-                       netfs_state_reset(st);
-                       continue;
-               }
-
-               switch (cmd->cmd) {
-               case NETFS_READ_PAGE:
-                               err = pohmelfs_read_page_response(st);
-                               break;
-               case NETFS_READDIR:
-                               err = pohmelfs_readdir_response(st);
-                               break;
-               case NETFS_LOOKUP:
-                               err = pohmelfs_lookup_response(st);
-                               break;
-               case NETFS_CREATE:
-                               err = pohmelfs_create_response(st);
-                               break;
-               case NETFS_REMOVE:
-                               err = pohmelfs_remove_response(st);
-                               break;
-               case NETFS_TRANS:
-                               err = pohmelfs_transaction_response(st);
-                               break;
-               case NETFS_PAGE_CACHE:
-                               err = pohmelfs_page_cache_response(st);
-                               break;
-               case NETFS_CAPABILITIES:
-                               err = pohmelfs_capabilities_response(st);
-                               break;
-               case NETFS_LOCK:
-                               err = pohmelfs_data_lock_response(st);
-                               break;
-               case NETFS_XATTR_GET:
-                               err = pohmelfs_getxattr_response(st);
-                               break;
-               default:
-                               printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
-                                       __func__, cmd->cmd, cmd->id, cmd->start, cmd->size, cmd->ext);
-                               netfs_state_reset(st);
-                               break;
-               }
-       }
-
-       while (!kthread_should_stop())
-               schedule_timeout_uninterruptible(msecs_to_jiffies(10));
-
-       return err;
-}
-
-int netfs_state_init(struct netfs_state *st)
-{
-       int err;
-       struct pohmelfs_ctl *ctl = &st->ctl;
-
-       err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket);
-       if (err) {
-               printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
-                               __func__, ctl->addr.sa_family, ctl->type, ctl->proto, err);
-               goto err_out_exit;
-       }
-
-       st->socket->sk->sk_allocation = GFP_NOIO;
-       st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
-
-       err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0);
-       if (err) {
-               printk("%s: failed to connect to server: idx: %u, err: %d.\n",
-                               __func__, st->psb->idx, err);
-               goto err_out_release;
-       }
-       st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
-
-       err = netfs_poll_init(st);
-       if (err)
-               goto err_out_release;
-
-       if (st->socket->ops->family == AF_INET) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)&ctl->addr;
-               printk(KERN_INFO "%s: (re)connected to peer %pi4:%d.\n", __func__,
-                       &sin->sin_addr.s_addr, ntohs(sin->sin_port));
-       } else if (st->socket->ops->family == AF_INET6) {
-               struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&ctl->addr;
-               printk(KERN_INFO "%s: (re)connected to peer %pi6:%d", __func__,
-                               &sin->sin6_addr, ntohs(sin->sin6_port));
-       }
-
-       return 0;
-
-err_out_release:
-       sock_release(st->socket);
-err_out_exit:
-       st->socket = NULL;
-       return err;
-}
-
-void netfs_state_exit(struct netfs_state *st)
-{
-       if (st->socket) {
-               netfs_poll_exit(st);
-               st->socket->ops->shutdown(st->socket, 2);
-
-               if (st->socket->ops->family == AF_INET) {
-                       struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
-                       printk(KERN_INFO "%s: disconnected from peer %pi4:%d.\n", __func__,
-                               &sin->sin_addr.s_addr, ntohs(sin->sin_port));
-               } else if (st->socket->ops->family == AF_INET6) {
-                       struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
-                       printk(KERN_INFO "%s: disconnected from peer %pi6:%d", __func__,
-                               &sin->sin6_addr, ntohs(sin->sin6_port));
-               }
-
-               sock_release(st->socket);
-               st->socket = NULL;
-               st->read_socket = NULL;
-               st->need_reset = 0;
-       }
-}
-
-int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf)
-{
-       struct netfs_state *st = &conf->state;
-       int err = -ENOMEM;
-
-       mutex_init(&st->__state_lock);
-       mutex_init(&st->__state_send_lock);
-       init_waitqueue_head(&st->thread_wait);
-
-       st->psb = psb;
-       st->trans_root = RB_ROOT;
-       mutex_init(&st->trans_lock);
-
-       st->size = psb->trans_data_size;
-       st->data = kmalloc(st->size, GFP_KERNEL);
-       if (!st->data)
-               goto err_out_exit;
-
-       if (psb->perform_crypto) {
-               err = pohmelfs_crypto_engine_init(&st->eng, psb);
-               if (err)
-                       goto err_out_free_data;
-       }
-
-       err = netfs_state_init(st);
-       if (err)
-               goto err_out_free_engine;
-
-       st->thread = kthread_run(pohmelfs_recv, st, "pohmelfs/%u", psb->idx);
-       if (IS_ERR(st->thread)) {
-               err = PTR_ERR(st->thread);
-               goto err_out_netfs_exit;
-       }
-
-       if (!psb->active_state)
-               psb->active_state = conf;
-
-       dprintk("%s: conf: %p, st: %p, socket: %p.\n",
-                       __func__, conf, st, st->socket);
-       return 0;
-
-err_out_netfs_exit:
-       netfs_state_exit(st);
-err_out_free_engine:
-       pohmelfs_crypto_engine_exit(&st->eng);
-err_out_free_data:
-       kfree(st->data);
-err_out_exit:
-       return err;
-
-}
-
-void pohmelfs_state_flush_transactions(struct netfs_state *st)
-{
-       struct rb_node *rb_node;
-       struct netfs_trans_dst *dst;
-
-       mutex_lock(&st->trans_lock);
-       for (rb_node = rb_first(&st->trans_root); rb_node; ) {
-               dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
-               rb_node = rb_next(rb_node);
-
-               dst->trans->result = -EINVAL;
-               netfs_trans_remove_nolock(dst, st);
-               netfs_trans_drop_dst_nostate(dst);
-       }
-       mutex_unlock(&st->trans_lock);
-}
-
-static void pohmelfs_state_exit_one(struct pohmelfs_config *c)
-{
-       struct netfs_state *st = &c->state;
-
-       dprintk("%s: exiting, st: %p.\n", __func__, st);
-       if (st->thread) {
-               kthread_stop(st->thread);
-               st->thread = NULL;
-       }
-
-       netfs_state_lock_send(st);
-       netfs_state_exit(st);
-       netfs_state_unlock_send(st);
-
-       pohmelfs_state_flush_transactions(st);
-
-       pohmelfs_crypto_engine_exit(&st->eng);
-       kfree(st->data);
-
-       kfree(c);
-}
-
-/*
- * Initialize network stack. It searches for given ID in global
- * configuration table, this contains information of the remote server
- * (address (any supported by socket interface) and port, protocol and so on).
- */
-int pohmelfs_state_init(struct pohmelfs_sb *psb)
-{
-       int err = -ENOMEM;
-
-       err = pohmelfs_copy_config(psb);
-       if (err) {
-               pohmelfs_state_exit(psb);
-               return err;
-       }
-
-       return 0;
-}
-
-void pohmelfs_state_exit(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c, *tmp;
-
-       list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
-               list_del(&c->config_entry);
-               pohmelfs_state_exit_one(c);
-       }
-}
-
-void pohmelfs_switch_active(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c = psb->active_state;
-
-       if (!list_empty(&psb->state_list)) {
-               if (c->config_entry.next != &psb->state_list) {
-                       psb->active_state = list_entry(c->config_entry.next,
-                               struct pohmelfs_config, config_entry);
-               } else {
-                       psb->active_state = list_entry(psb->state_list.next,
-                               struct pohmelfs_config, config_entry);
-               }
-
-               dprintk("%s: empty: %d, active %p -> %p.\n",
-                       __func__, list_empty(&psb->state_list), c,
-                       psb->active_state);
-       } else
-               psb->active_state = NULL;
-}
-
-void pohmelfs_check_states(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c, *tmp;
-       LIST_HEAD(delete_list);
-
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
-               if (pohmelfs_config_check(c, psb->idx)) {
-
-                       if (psb->active_state == c)
-                               pohmelfs_switch_active(psb);
-                       list_move(&c->config_entry, &delete_list);
-               }
-       }
-       pohmelfs_copy_config(psb);
-       mutex_unlock(&psb->state_lock);
-
-       list_for_each_entry_safe(c, tmp, &delete_list, config_entry) {
-               list_del(&c->config_entry);
-               pohmelfs_state_exit_one(c);
-       }
-}
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
deleted file mode 100644 (file)
index f26894f..0000000
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __NETFS_H
-#define __NETFS_H
-
-#include <linux/types.h>
-#include <linux/connector.h>
-#include <linux/backing-dev.h>
-
-#define POHMELFS_CN_IDX                        5
-#define POHMELFS_CN_VAL                        0
-
-#define POHMELFS_CTLINFO_ACK           1
-#define POHMELFS_NOINFO_ACK            2
-
-#define POHMELFS_NULL_IDX              65535
-
-/*
- * Network command structure.
- * Will be extended.
- */
-struct netfs_cmd {
-       __u16                   cmd;    /* Command number */
-       __u16                   csize;  /* Attached crypto information size */
-       __u16                   cpad;   /* Attached padding size */
-       __u16                   ext;    /* External flags */
-       __u32                   size;   /* Size of the attached data */
-       __u32                   trans;  /* Transaction id */
-       __u64                   id;     /* Object ID to operate on. Used for feedback.*/
-       __u64                   start;  /* Start of the object. */
-       __u64                   iv;     /* IV sequence */
-       __u8                    data[0];
-};
-
-static inline void netfs_convert_cmd(struct netfs_cmd *cmd)
-{
-       cmd->id = __be64_to_cpu(cmd->id);
-       cmd->start = __be64_to_cpu(cmd->start);
-       cmd->iv = __be64_to_cpu(cmd->iv);
-       cmd->cmd = __be16_to_cpu(cmd->cmd);
-       cmd->ext = __be16_to_cpu(cmd->ext);
-       cmd->csize = __be16_to_cpu(cmd->csize);
-       cmd->cpad = __be16_to_cpu(cmd->cpad);
-       cmd->size = __be32_to_cpu(cmd->size);
-}
-
-#define NETFS_TRANS_SINGLE_DST         (1<<0)
-
-enum {
-       NETFS_READDIR   = 1,    /* Read directory for given inode number */
-       NETFS_READ_PAGE,        /* Read data page from the server */
-       NETFS_WRITE_PAGE,       /* Write data page to the server */
-       NETFS_CREATE,           /* Create directory entry */
-       NETFS_REMOVE,           /* Remove directory entry */
-
-       NETFS_LOOKUP,           /* Lookup single object */
-       NETFS_LINK,             /* Create a link */
-       NETFS_TRANS,            /* Transaction */
-       NETFS_OPEN,             /* Open intent */
-       NETFS_INODE_INFO,       /* Metadata cache coherency synchronization message */
-
-       NETFS_PAGE_CACHE,       /* Page cache invalidation message */
-       NETFS_READ_PAGES,       /* Read multiple contiguous pages in one go */
-       NETFS_RENAME,           /* Rename object */
-       NETFS_CAPABILITIES,     /* Capabilities of the client, for example supported crypto */
-       NETFS_LOCK,             /* Distributed lock message */
-
-       NETFS_XATTR_SET,        /* Set extended attribute */
-       NETFS_XATTR_GET,        /* Get extended attribute */
-       NETFS_CMD_MAX
-};
-
-enum {
-       POHMELFS_FLAGS_ADD = 0, /* Network state control message for ADD */
-       POHMELFS_FLAGS_DEL,     /* Network state control message for DEL */
-       POHMELFS_FLAGS_SHOW,    /* Network state control message for SHOW */
-       POHMELFS_FLAGS_CRYPTO,  /* Crypto data control message */
-       POHMELFS_FLAGS_MODIFY,  /* Network state modification message */
-       POHMELFS_FLAGS_DUMP,    /* Network state control message for SHOW ALL */
-       POHMELFS_FLAGS_FLUSH,   /* Network state control message for FLUSH */
-};
-
-/*
- * Always wanted to copy it from socket headers into public one,
- * since they are __KERNEL__ protected there.
- */
-#define _K_SS_MAXSIZE  128
-
-struct saddr {
-       unsigned short          sa_family;
-       char                    addr[_K_SS_MAXSIZE];
-};
-
-enum {
-       POHMELFS_CRYPTO_HASH = 0,
-       POHMELFS_CRYPTO_CIPHER,
-};
-
-struct pohmelfs_crypto {
-       unsigned int            idx;            /* Config index */
-       unsigned short          strlen;         /* Size of the attached crypto string including 0-byte
-                                                * "cbc(aes)" for example */
-       unsigned short          type;           /* HMAC, cipher, both */
-       unsigned int            keysize;        /* Key size */
-       unsigned char           data[0];        /* Algorithm string, key and IV */
-};
-
-#define POHMELFS_IO_PERM_READ          (1<<0)
-#define POHMELFS_IO_PERM_WRITE         (1<<1)
-
-/*
- * Configuration command used to create table of different remote servers.
- */
-struct pohmelfs_ctl {
-       __u32                   idx;            /* Config index */
-       __u32                   type;           /* Socket type */
-       __u32                   proto;          /* Socket protocol */
-       __u16                   addrlen;        /* Size of the address */
-       __u16                   perm;           /* IO permission */
-       __u16                   prio;           /* IO priority */
-       struct saddr            addr;           /* Remote server address */
-};
-
-/*
- * Ack for userspace about requested command.
- */
-struct pohmelfs_cn_ack {
-       struct cn_msg           msg;
-       int                     error;
-       int                     msg_num;
-       int                     unused[3];
-       struct pohmelfs_ctl     ctl;
-};
-
-/*
- * Inode info structure used to sync with server.
- * Check what stat() returns.
- */
-struct netfs_inode_info {
-       unsigned int            mode;
-       unsigned int            nlink;
-       unsigned int            uid;
-       unsigned int            gid;
-       unsigned int            blocksize;
-       unsigned int            padding;
-       __u64                   ino;
-       __u64                   blocks;
-       __u64                   rdev;
-       __u64                   size;
-       __u64                   version;
-};
-
-static inline void netfs_convert_inode_info(struct netfs_inode_info *info)
-{
-       info->mode = __cpu_to_be32(info->mode);
-       info->nlink = __cpu_to_be32(info->nlink);
-       info->uid = __cpu_to_be32(info->uid);
-       info->gid = __cpu_to_be32(info->gid);
-       info->blocksize = __cpu_to_be32(info->blocksize);
-       info->blocks = __cpu_to_be64(info->blocks);
-       info->rdev = __cpu_to_be64(info->rdev);
-       info->size = __cpu_to_be64(info->size);
-       info->version = __cpu_to_be64(info->version);
-       info->ino = __cpu_to_be64(info->ino);
-}
-
-/*
- * Cache state machine.
- */
-enum {
-       NETFS_COMMAND_PENDING = 0,      /* Command is being executed */
-       NETFS_INODE_REMOTE_SYNCED,      /* Inode was synced to server */
-       NETFS_INODE_REMOTE_DIR_SYNCED,  /* Inode (directory) was synced from the server */
-       NETFS_INODE_OWNED,              /* Inode is owned by given host */
-       NETFS_INODE_NEED_FLUSH,         /* Inode has to be flushed to the server */
-};
-
-/*
- * POHMELFS capabilities: information about supported
- * crypto operations (hash/cipher, modes, key sizes and so on),
- * root information (used/available size, number of objects, permissions)
- */
-enum pohmelfs_capabilities {
-       POHMELFS_CRYPTO_CAPABILITIES = 0,
-       POHMELFS_ROOT_CAPABILITIES,
-};
-
-/* Read-only mount */
-#define POHMELFS_FLAGS_RO              (1<<0)
-/* Extended attributes support on/off */
-#define POHMELFS_FLAGS_XATTR           (1<<1)
-
-struct netfs_root_capabilities {
-       __u64                   nr_files;
-       __u64                   used, avail;
-       __u64                   flags;
-};
-
-static inline void netfs_convert_root_capabilities(struct netfs_root_capabilities *cap)
-{
-       cap->nr_files = __cpu_to_be64(cap->nr_files);
-       cap->used = __cpu_to_be64(cap->used);
-       cap->avail = __cpu_to_be64(cap->avail);
-       cap->flags = __cpu_to_be64(cap->flags);
-}
-
-struct netfs_crypto_capabilities {
-       unsigned short          hash_strlen;    /* Hash string length, like "hmac(sha1) including 0 byte "*/
-       unsigned short          cipher_strlen;  /* Cipher string length with the same format */
-       unsigned int            cipher_keysize; /* Cipher key size */
-};
-
-static inline void netfs_convert_crypto_capabilities(struct netfs_crypto_capabilities *cap)
-{
-       cap->hash_strlen = __cpu_to_be16(cap->hash_strlen);
-       cap->cipher_strlen = __cpu_to_be16(cap->cipher_strlen);
-       cap->cipher_keysize = __cpu_to_be32(cap->cipher_keysize);
-}
-
-enum pohmelfs_lock_type {
-       POHMELFS_LOCK_GRAB      = (1<<15),
-
-       POHMELFS_READ_LOCK      = 0,
-       POHMELFS_WRITE_LOCK,
-};
-
-struct netfs_lock {
-       __u64                   start;
-       __u64                   ino;
-       __u32                   size;
-       __u32                   type;
-};
-
-static inline void netfs_convert_lock(struct netfs_lock *lock)
-{
-       lock->start = __cpu_to_be64(lock->start);
-       lock->ino = __cpu_to_be64(lock->ino);
-       lock->size = __cpu_to_be32(lock->size);
-       lock->type = __cpu_to_be32(lock->type);
-}
-
-#ifdef __KERNEL__
-
-#include <linux/kernel.h>
-#include <linux/completion.h>
-#include <linux/rbtree.h>
-#include <linux/net.h>
-#include <linux/poll.h>
-
-/*
- * Private POHMELFS cache of objects in directory.
- */
-struct pohmelfs_name {
-       struct rb_node          hash_node;
-
-       struct list_head        sync_create_entry;
-
-       u64                     ino;
-
-       u32                     hash;
-       u32                     mode;
-       u32                     len;
-
-       char                    *data;
-};
-
-/*
- * POHMELFS inode. Main object.
- */
-struct pohmelfs_inode {
-       struct list_head        inode_entry;            /* Entry in superblock list.
-                                                        * Objects which are not bound to dentry require to be dropped
-                                                        * in ->put_super()
-                                                        */
-       struct rb_root          hash_root;              /* The same, but indexed by name hash and len */
-       struct mutex            offset_lock;            /* Protect both above trees */
-
-       struct list_head        sync_create_list;       /* List of created but not yet synced to the server children */
-
-       unsigned int            drop_count;
-
-       int                     lock_type;              /* How this inode is locked: read or write */
-
-       int                     error;                  /* Transaction error for given inode */
-
-       long                    state;                  /* State machine above */
-
-       u64                     ino;                    /* Inode number */
-       u64                     total_len;              /* Total length of all children names, used to create offsets */
-
-       struct inode            vfs_inode;
-};
-
-struct netfs_trans;
-typedef int (*netfs_trans_complete_t)(struct page **pages, unsigned int page_num,
-               void *private, int err);
-
-struct netfs_state;
-struct pohmelfs_sb;
-
-struct netfs_trans {
-       /*
-        * Transaction header and attached contiguous data live here.
-        */
-       struct iovec                    iovec;
-
-       /*
-        * Pages attached to transaction.
-        */
-       struct page                     **pages;
-
-       /*
-        * List and protecting lock for transaction destination
-        * network states.
-        */
-       spinlock_t                      dst_lock;
-       struct list_head                dst_list;
-
-       /*
-        * Number of users for given transaction.
-        * For example each network state attached to transaction
-        * via dst_list increases it.
-        */
-       atomic_t                        refcnt;
-
-       /*
-        * Number of pages attached to given transaction.
-        * Some slots in above page array can be NULL, since
-        * for example page can be under writeback already,
-        * so we skip it in this transaction.
-        */
-       unsigned int                    page_num;
-
-       /*
-        * Transaction flags: single dst or broadcast and so on.
-        */
-       unsigned int                    flags;
-
-       /*
-        * Size of the data, which can be placed into
-        * iovec.iov_base area.
-        */
-       unsigned int                    total_size;
-
-       /*
-        * Number of pages to be sent to remote server.
-        * Usually equal to above page_num, but in case of partial
-        * writeback it can accumulate only pages already completed
-        * previous writeback.
-        */
-       unsigned int                    attached_pages;
-
-       /*
-        * Attached number of bytes in all above pages.
-        */
-       unsigned int                    attached_size;
-
-       /*
-        * Unique transacton generation number.
-        * Used as identity in the network state tree of transactions.
-        */
-       unsigned int                    gen;
-
-       /*
-        * Transaction completion status.
-        */
-       int                             result;
-
-       /*
-        * Superblock this transaction belongs to
-        */
-       struct pohmelfs_sb              *psb;
-
-       /*
-        * Crypto engine, which processed this transaction.
-        * Can be not NULL only if crypto engine holds encrypted pages.
-        */
-       struct pohmelfs_crypto_engine   *eng;
-
-       /* Private data */
-       void                            *private;
-
-       /* Completion callback, invoked just before transaction is destroyed */
-       netfs_trans_complete_t          complete;
-};
-
-static inline int netfs_trans_cur_len(struct netfs_trans *t)
-{
-       return (signed)(t->total_size - t->iovec.iov_len);
-}
-
-static inline void *netfs_trans_current(struct netfs_trans *t)
-{
-       return t->iovec.iov_base + t->iovec.iov_len;
-}
-
-struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
-               unsigned int flags, unsigned int nr);
-void netfs_trans_free(struct netfs_trans *t);
-int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb);
-int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb);
-
-static inline void netfs_trans_reset(struct netfs_trans *t)
-{
-       t->complete = NULL;
-}
-
-struct netfs_trans_dst {
-       struct list_head                trans_entry;
-       struct rb_node                  state_entry;
-
-       unsigned long                   send_time;
-
-       /*
-        * Times this transaction was resent to its old or new,
-        * depending on flags, destinations. When it reaches maximum
-        * allowed number, specified in superblock->trans_retries,
-        * transaction will be freed with ETIMEDOUT error.
-        */
-       unsigned int                    retries;
-
-       struct netfs_trans              *trans;
-       struct netfs_state              *state;
-};
-
-struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen);
-void netfs_trans_drop_dst(struct netfs_trans_dst *dst);
-void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst);
-void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st);
-void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st);
-int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb);
-int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st);
-
-int netfs_trans_init(void);
-void netfs_trans_exit(void);
-
-struct pohmelfs_crypto_engine {
-       u64                             iv;             /* Crypto IV for current operation */
-       unsigned long                   timeout;        /* Crypto waiting timeout */
-       unsigned int                    size;           /* Size of crypto scratchpad */
-       void                            *data;          /* Temporal crypto scratchpad */
-       /*
-        * Crypto operations performed on objects.
-        */
-       struct crypto_hash              *hash;
-       struct crypto_ablkcipher        *cipher;
-
-       struct pohmelfs_crypto_thread   *thread;        /* Crypto thread which hosts this engine */
-
-       struct page                     **pages;
-       unsigned int                    page_num;
-};
-
-struct pohmelfs_crypto_thread {
-       struct list_head                thread_entry;
-
-       struct task_struct              *thread;
-       struct pohmelfs_sb              *psb;
-
-       struct pohmelfs_crypto_engine   eng;
-
-       struct netfs_trans              *trans;
-
-       wait_queue_head_t               wait;
-       int                             error;
-
-       unsigned int                    size;
-       struct page                     *page;
-};
-
-void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th);
-
-/*
- * Network state, attached to one server.
- */
-struct netfs_state {
-       struct mutex            __state_lock;           /* Can not allow to use the same socket simultaneously */
-       struct mutex            __state_send_lock;
-       struct netfs_cmd        cmd;                    /* Cached command */
-       struct netfs_inode_info info;                   /* Cached inode info */
-
-       void                    *data;                  /* Cached some data */
-       unsigned int            size;                   /* Size of that data */
-
-       struct pohmelfs_sb      *psb;                   /* Superblock */
-
-       struct task_struct      *thread;                /* Async receiving thread */
-
-       /* Waiting/polling machinery */
-       wait_queue_t            wait;
-       wait_queue_head_t       *whead;
-       wait_queue_head_t       thread_wait;
-
-       struct mutex            trans_lock;
-       struct rb_root          trans_root;
-
-       struct pohmelfs_ctl     ctl;                    /* Remote peer */
-
-       struct socket           *socket;                /* Socket object */
-       struct socket           *read_socket;           /* Cached pointer to socket object.
-                                                        * Used to determine if between lock drops socket was changed.
-                                                        * Never used to read data or any kind of access.
-                                                        */
-       /*
-        * Crypto engines to process incoming data.
-        */
-       struct pohmelfs_crypto_engine   eng;
-
-       int                     need_reset;
-};
-
-int netfs_state_init(struct netfs_state *st);
-void netfs_state_exit(struct netfs_state *st);
-
-static inline void netfs_state_lock_send(struct netfs_state *st)
-{
-       mutex_lock(&st->__state_send_lock);
-}
-
-static inline int netfs_state_trylock_send(struct netfs_state *st)
-{
-       return mutex_trylock(&st->__state_send_lock);
-}
-
-static inline void netfs_state_unlock_send(struct netfs_state *st)
-{
-       BUG_ON(!mutex_is_locked(&st->__state_send_lock));
-
-       mutex_unlock(&st->__state_send_lock);
-}
-
-static inline void netfs_state_lock(struct netfs_state *st)
-{
-       mutex_lock(&st->__state_lock);
-}
-
-static inline void netfs_state_unlock(struct netfs_state *st)
-{
-       BUG_ON(!mutex_is_locked(&st->__state_lock));
-
-       mutex_unlock(&st->__state_lock);
-}
-
-static inline unsigned int netfs_state_poll(struct netfs_state *st)
-{
-       unsigned int revents = POLLHUP | POLLERR;
-
-       netfs_state_lock(st);
-       if (st->socket)
-               revents = st->socket->ops->poll(NULL, st->socket, NULL);
-       netfs_state_unlock(st);
-
-       return revents;
-}
-
-struct pohmelfs_config;
-
-struct pohmelfs_sb {
-       struct rb_root          mcache_root;
-       struct mutex            mcache_lock;
-       atomic_long_t           mcache_gen;
-       unsigned long           mcache_timeout;
-
-       unsigned int            idx;
-
-       unsigned int            trans_retries;
-
-       atomic_t                trans_gen;
-
-       unsigned int            crypto_attached_size;
-       unsigned int            crypto_align_size;
-
-       unsigned int            crypto_fail_unsupported;
-
-       unsigned int            crypto_thread_num;
-       struct list_head        crypto_active_list, crypto_ready_list;
-       struct mutex            crypto_thread_lock;
-
-       unsigned int            trans_max_pages;
-       unsigned long           trans_data_size;
-       unsigned long           trans_timeout;
-
-       unsigned long           drop_scan_timeout;
-       unsigned long           trans_scan_timeout;
-
-       unsigned long           wait_on_page_timeout;
-
-       struct list_head        flush_list;
-       struct list_head        drop_list;
-       spinlock_t              ino_lock;
-       u64                     ino;
-
-       /*
-        * Remote nodes POHMELFS connected to.
-        */
-       struct list_head        state_list;
-       struct mutex            state_lock;
-
-       /*
-        * Currently active state to request data from.
-        */
-       struct pohmelfs_config  *active_state;
-
-
-       wait_queue_head_t       wait;
-
-       /*
-        * Timed checks: stale transactions, inodes to be freed and so on.
-        */
-       struct delayed_work     dwork;
-       struct delayed_work     drop_dwork;
-
-       struct super_block      *sb;
-
-       struct backing_dev_info bdi;
-
-       /*
-        * Algorithm strings.
-        */
-       char                    *hash_string;
-       char                    *cipher_string;
-
-       u8                      *hash_key;
-       u8                      *cipher_key;
-
-       /*
-        * Algorithm string lengths.
-        */
-       unsigned int            hash_strlen;
-       unsigned int            cipher_strlen;
-       unsigned int            hash_keysize;
-       unsigned int            cipher_keysize;
-
-       /*
-        * Controls whether to perfrom crypto processing or not.
-        */
-       int                     perform_crypto;
-
-       /*
-        * POHMELFS statistics.
-        */
-       u64                     total_size;
-       u64                     avail_size;
-       atomic_long_t           total_inodes;
-
-       /*
-        * Xattr support, read-only and so on.
-        */
-       u64                     state_flags;
-
-       /*
-        * Temporary storage to detect changes in the wait queue.
-        */
-       long                    flags;
-};
-
-static inline void netfs_trans_update(struct netfs_cmd *cmd,
-               struct netfs_trans *t, unsigned int size)
-{
-       unsigned int sz = ALIGN(size, t->psb->crypto_align_size);
-
-       t->iovec.iov_len += sizeof(struct netfs_cmd) + sz;
-       cmd->cpad = __cpu_to_be16(sz - size);
-}
-
-static inline struct pohmelfs_sb *POHMELFS_SB(struct super_block *sb)
-{
-       return sb->s_fs_info;
-}
-
-static inline struct pohmelfs_inode *POHMELFS_I(struct inode *inode)
-{
-       return container_of(inode, struct pohmelfs_inode, vfs_inode);
-}
-
-static inline u64 pohmelfs_new_ino(struct pohmelfs_sb *psb)
-{
-       u64 ino;
-
-       spin_lock(&psb->ino_lock);
-       ino = psb->ino++;
-       spin_unlock(&psb->ino_lock);
-
-       return ino;
-}
-
-static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
-       spin_lock(&psb->ino_lock);
-       list_move_tail(&pi->inode_entry, &psb->drop_list);
-       pi->drop_count++;
-       spin_unlock(&psb->ino_lock);
-}
-
-struct pohmelfs_config {
-       struct list_head        config_entry;
-
-       struct netfs_state      state;
-};
-
-struct pohmelfs_config_group {
-       /*
-        * Entry in the global config group list.
-        */
-       struct list_head        group_entry;
-
-       /*
-        * Index of the current group.
-        */
-       unsigned int            idx;
-       /*
-        * Number of config_list entries in this group entry.
-        */
-       unsigned int            num_entry;
-       /*
-        * Algorithm strings.
-        */
-       char                    *hash_string;
-       char                    *cipher_string;
-
-       /*
-        * Algorithm string lengths.
-        */
-       unsigned int            hash_strlen;
-       unsigned int            cipher_strlen;
-
-       /*
-        * Key and its size.
-        */
-       unsigned int            hash_keysize;
-       unsigned int            cipher_keysize;
-       u8                      *hash_key;
-       u8                      *cipher_key;
-
-       /*
-        * List of config entries (network state info) for given idx.
-        */
-       struct list_head        config_list;
-};
-
-int __init pohmelfs_config_init(void);
-void pohmelfs_config_exit(void);
-int pohmelfs_copy_config(struct pohmelfs_sb *psb);
-int pohmelfs_copy_crypto(struct pohmelfs_sb *psb);
-int pohmelfs_config_check(struct pohmelfs_config *config, int idx);
-int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf);
-
-extern const struct file_operations pohmelfs_dir_fops;
-extern const struct inode_operations pohmelfs_dir_inode_ops;
-
-int pohmelfs_state_init(struct pohmelfs_sb *psb);
-void pohmelfs_state_exit(struct pohmelfs_sb *psb);
-void pohmelfs_state_flush_transactions(struct netfs_state *st);
-
-void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info);
-
-void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
-void pohmelfs_free_names(struct pohmelfs_inode *parent);
-struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash);
-
-void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi);
-
-struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
-       struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode);
-
-int pohmelfs_write_create_inode(struct pohmelfs_inode *pi);
-
-int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans);
-int pohmelfs_remove_child(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
-
-struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
-               struct pohmelfs_inode *parent, struct qstr *str,
-               struct netfs_inode_info *info, int link);
-
-int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr);
-int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr);
-
-int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
-               netfs_trans_complete_t complete, void *priv, u64 start);
-int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
-               unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start);
-
-void pohmelfs_check_states(struct pohmelfs_sb *psb);
-void pohmelfs_switch_active(struct pohmelfs_sb *psb);
-
-int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len);
-int pohmelfs_path_length(struct pohmelfs_inode *pi);
-
-struct pohmelfs_crypto_completion {
-       struct completion       complete;
-       int                     error;
-};
-
-int pohmelfs_trans_crypt(struct netfs_trans *t, struct pohmelfs_sb *psb);
-void pohmelfs_crypto_exit(struct pohmelfs_sb *psb);
-int pohmelfs_crypto_init(struct pohmelfs_sb *psb);
-
-int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb);
-void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e);
-
-int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 iv,
-               void *data, struct page *page, unsigned int size);
-int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
-               struct page *page, unsigned int size, u64 iv);
-
-static inline u64 pohmelfs_gen_iv(struct netfs_trans *t)
-{
-       u64 iv = t->gen;
-
-       iv <<= 32;
-       iv |= ((unsigned long)t) & 0xffffffff;
-
-       return iv;
-}
-
-int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
-int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
-int pohmelfs_data_lock_response(struct netfs_state *st);
-
-static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type)
-{
-       if (test_bit(NETFS_INODE_OWNED, &pi->state)) {
-               if (type == pi->lock_type)
-                       return 0;
-               if ((type == POHMELFS_READ_LOCK) && (pi->lock_type == POHMELFS_WRITE_LOCK))
-                       return 0;
-       }
-
-       if (!test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
-               return 0;
-
-       return 1;
-}
-
-int __init pohmelfs_mcache_init(void);
-void pohmelfs_mcache_exit(void);
-
-/* #define CONFIG_POHMELFS_DEBUG */
-
-#ifdef CONFIG_POHMELFS_DEBUG
-#define dprintka(f, a...) printk(f, ##a)
-#define dprintk(f, a...) printk("%d: " f, task_pid_vnr(current), ##a)
-#else
-#define dprintka(f, a...) do {} while (0)
-#define dprintk(f, a...) do {} while (0)
-#endif
-
-static inline void netfs_trans_get(struct netfs_trans *t)
-{
-       atomic_inc(&t->refcnt);
-}
-
-static inline void netfs_trans_put(struct netfs_trans *t)
-{
-       if (atomic_dec_and_test(&t->refcnt)) {
-               dprintk("%s: t: %p, gen: %u, err: %d.\n",
-                       __func__, t, t->gen, t->result);
-               if (t->complete)
-                       t->complete(t->pages, t->page_num,
-                               t->private, t->result);
-               netfs_trans_free(t);
-       }
-}
-
-struct pohmelfs_mcache {
-       struct rb_node                  mcache_entry;
-       struct completion               complete;
-
-       atomic_t                        refcnt;
-
-       u64                             gen;
-
-       void                            *data;
-       u64                             start;
-       u32                             size;
-       int                             err;
-
-       struct netfs_inode_info         info;
-};
-
-struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
-               unsigned int size, void *data);
-void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
-struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen);
-void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
-
-static inline void pohmelfs_mcache_get(struct pohmelfs_mcache *m)
-{
-       atomic_inc(&m->refcnt);
-}
-
-static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb,
-               struct pohmelfs_mcache *m)
-{
-       if (atomic_dec_and_test(&m->refcnt))
-               pohmelfs_mcache_free(psb, m);
-}
-
-/*#define POHMELFS_TRUNCATE_ON_INODE_FLUSH
- */
-
-#endif /* __KERNEL__*/
-
-#endif /* __NETFS_H */
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c
deleted file mode 100644 (file)
index 400a9fc..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/ktime.h>
-#include <linux/fs_struct.h>
-#include <linux/pagemap.h>
-#include <linux/writeback.h>
-#include <linux/mount.h>
-#include <linux/mm.h>
-
-#include "netfs.h"
-
-#define UNHASHED_OBSCURE_STRING_SIZE           sizeof(" (deleted)")
-
-/*
- * Create path from root for given inode.
- * Path is formed as set of stuctures, containing name of the object
- * and its inode data (mode, permissions and so on).
- */
-int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len)
-{
-       struct path path;
-       struct dentry *d;
-       char *ptr;
-       int err = 0, strlen, reduce = 0;
-
-       d = d_find_alias(&pi->vfs_inode);
-       if (!d) {
-               printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry));
-               return -ENOENT;
-       }
-
-       spin_lock(&current->fs->lock);
-       path.mnt = mntget(current->fs->root.mnt);
-       spin_unlock(&current->fs->lock);
-
-       path.dentry = d;
-
-       if (!IS_ROOT(d) && d_unhashed(d))
-               reduce = 1;
-
-       ptr = d_path(&path, data, len);
-       if (IS_ERR(ptr)) {
-               err = PTR_ERR(ptr);
-               goto out;
-       }
-
-       if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) {
-               char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE;
-               *end = '\0';
-       }
-
-       strlen = len - (ptr - (char *)data);
-       memmove(data, ptr, strlen);
-       ptr = data;
-
-       err = strlen;
-
-       dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n",
-                       __func__, d->d_name.name, d->d_name.len, len, ptr, strlen);
-
-out:
-       dput(d);
-       mntput(path.mnt);
-
-       return err;
-}
-
-int pohmelfs_path_length(struct pohmelfs_inode *pi)
-{
-       struct dentry *d, *root, *first;
-       int len;
-       unsigned seq;
-
-       first = d_find_alias(&pi->vfs_inode);
-       if (!first) {
-               dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
-               return -ENOENT;
-       }
-
-       spin_lock(&current->fs->lock);
-       root = dget(current->fs->root.dentry);
-       spin_unlock(&current->fs->lock);
-
-rename_retry:
-       len = 1; /* Root slash */
-       d = first;
-       seq = read_seqbegin(&rename_lock);
-       rcu_read_lock();
-
-       if (!IS_ROOT(d) && d_unhashed(d))
-               len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */
-
-       while (d && d != root && !IS_ROOT(d)) {
-               len += d->d_name.len + 1; /* Plus slash */
-               d = d->d_parent;
-       }
-       rcu_read_unlock();
-       if (read_seqretry(&rename_lock, seq))
-               goto rename_retry;
-
-       dput(root);
-       dput(first);
-
-       return len + 1; /* Including zero-byte */
-}
diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
deleted file mode 100644 (file)
index 06c1a74..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/crypto.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/hash.h>
-#include <linux/ktime.h>
-#include <linux/mempool.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/parser.h>
-#include <linux/poll.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/statfs.h>
-#include <linux/writeback.h>
-
-#include "netfs.h"
-
-static struct kmem_cache *netfs_trans_dst;
-static mempool_t *netfs_trans_dst_pool;
-
-static void netfs_trans_init_static(struct netfs_trans *t, int num, int size)
-{
-       t->page_num = num;
-       t->total_size = size;
-       atomic_set(&t->refcnt, 1);
-
-       spin_lock_init(&t->dst_lock);
-       INIT_LIST_HEAD(&t->dst_list);
-}
-
-static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st)
-{
-       int err = 0;
-       unsigned int i, attached_pages = t->attached_pages, ci;
-       struct msghdr msg;
-       struct page **pages = (t->eng) ? t->eng->pages : t->pages;
-       struct page *p;
-       unsigned int size;
-
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_WAITALL | MSG_MORE;
-
-       ci = 0;
-       for (i = 0; i < t->page_num; ++i) {
-               struct page *page = pages[ci];
-               struct netfs_cmd cmd;
-               struct iovec io;
-
-               p = t->pages[i];
-
-               if (!p)
-                       continue;
-
-               size = page_private(p);
-
-               io.iov_base = &cmd;
-               io.iov_len = sizeof(struct netfs_cmd);
-
-               cmd.cmd = NETFS_WRITE_PAGE;
-               cmd.ext = 0;
-               cmd.id = 0;
-               cmd.size = size;
-               cmd.start = p->index;
-               cmd.start <<= PAGE_CACHE_SHIFT;
-               cmd.csize = 0;
-               cmd.cpad = 0;
-               cmd.iv = pohmelfs_gen_iv(t);
-
-               netfs_convert_cmd(&cmd);
-
-               msg.msg_iov = &io;
-               msg.msg_iovlen = 1;
-               msg.msg_flags = MSG_WAITALL | MSG_MORE;
-
-               err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd));
-               if (err <= 0) {
-                       printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n",
-                                       __func__, i, t->page_num, t, t->gen, err);
-                       if (err == 0)
-                               err = -ECONNRESET;
-                       goto err_out;
-               }
-
-               msg.msg_flags = MSG_WAITALL | (attached_pages == 1 ? 0 :
-                               MSG_MORE);
-
-               err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags);
-               if (err <= 0) {
-                       printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n",
-                                       __func__, i, t->page_num, t, t->gen, size, err);
-                       if (err == 0)
-                               err = -ECONNRESET;
-                       goto err_out;
-               }
-
-               dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n",
-                       __func__, i, t->page_num, t, t->gen, page, p, size);
-
-               err = 0;
-               attached_pages--;
-               if (!attached_pages)
-                       break;
-               ci++;
-
-               continue;
-
-err_out:
-               printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err);
-               netfs_state_exit(st);
-               break;
-       }
-
-       return err;
-}
-
-int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
-{
-       int err;
-       struct msghdr msg;
-
-       BUG_ON(!t->iovec.iov_len);
-       BUG_ON(t->iovec.iov_len > 1024*1024*1024);
-
-       netfs_state_lock_send(st);
-       if (!st->socket) {
-               err = netfs_state_init(st);
-               if (err)
-                       goto err_out_unlock_return;
-       }
-
-       msg.msg_iov = &t->iovec;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_WAITALL;
-
-       if (t->attached_pages)
-               msg.msg_flags |= MSG_MORE;
-
-       err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len);
-       if (err <= 0) {
-               printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n",
-                               __func__, t, t->gen, t->iovec.iov_len, err);
-               if (err == 0)
-                       err = -ECONNRESET;
-               goto err_out_unlock_return;
-       }
-
-       dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n",
-                       __func__, (t->page_num) ? "partial" : "full",
-                       t, t->gen, t->iovec.iov_len, t->page_num);
-
-       err = 0;
-       if (t->attached_pages)
-               err = netfs_trans_send_pages(t, st);
-
-err_out_unlock_return:
-
-       if (st->need_reset)
-               netfs_state_exit(st);
-
-       netfs_state_unlock_send(st);
-
-       dprintk("%s: t: %p, gen: %u, err: %d.\n",
-               __func__, t, t->gen, err);
-
-       t->result = err;
-       return err;
-}
-
-static inline int netfs_trans_cmp(unsigned int gen, unsigned int new)
-{
-       if (gen < new)
-               return 1;
-       if (gen > new)
-               return -1;
-       return 0;
-}
-
-struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen)
-{
-       struct rb_root *root = &st->trans_root;
-       struct rb_node *n = root->rb_node;
-       struct netfs_trans_dst *tmp, *ret = NULL;
-       struct netfs_trans *t;
-       int cmp;
-
-       while (n) {
-               tmp = rb_entry(n, struct netfs_trans_dst, state_entry);
-               t = tmp->trans;
-
-               cmp = netfs_trans_cmp(t->gen, gen);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st)
-{
-       struct rb_root *root = &st->trans_root;
-       struct rb_node **n = &root->rb_node, *parent = NULL;
-       struct netfs_trans_dst *ret = NULL, *tmp;
-       struct netfs_trans *t = NULL, *new = ndst->trans;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               tmp = rb_entry(parent, struct netfs_trans_dst, state_entry);
-               t = tmp->trans;
-
-               cmp = netfs_trans_cmp(t->gen, new->gen);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       if (ret) {
-               printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, "
-                               "new: gen: %u, flags: %x, send_time: %lu.\n",
-                       __func__, t->gen, t->flags, ret->send_time,
-                       new->gen, new->flags, ndst->send_time);
-               return -EEXIST;
-       }
-
-       rb_link_node(&ndst->state_entry, parent, n);
-       rb_insert_color(&ndst->state_entry, root);
-       ndst->send_time = jiffies;
-
-       return 0;
-}
-
-int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st)
-{
-       if (dst && dst->state_entry.rb_parent_color) {
-               rb_erase(&dst->state_entry, &st->trans_root);
-               dst->state_entry.rb_parent_color = 0;
-               return 1;
-       }
-       return 0;
-}
-
-static int netfs_trans_remove_state(struct netfs_trans_dst *dst)
-{
-       int ret;
-       struct netfs_state *st = dst->state;
-
-       mutex_lock(&st->trans_lock);
-       ret = netfs_trans_remove_nolock(dst, st);
-       mutex_unlock(&st->trans_lock);
-
-       return ret;
-}
-
-/*
- * Create new destination for given transaction associated with given network state.
- * Transaction's reference counter is bumped and will be dropped when either
- * reply is received or when async timeout detection task will fail resending
- * and drop transaction.
- */
-static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst;
-       int err;
-
-       dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL);
-       if (!dst)
-               return -ENOMEM;
-
-       dst->retries = 0;
-       dst->send_time = 0;
-       dst->state = st;
-       dst->trans = t;
-       netfs_trans_get(t);
-
-       mutex_lock(&st->trans_lock);
-       err = netfs_trans_insert(dst, st);
-       mutex_unlock(&st->trans_lock);
-
-       if (err)
-               goto err_out_free;
-
-       spin_lock(&t->dst_lock);
-       list_add_tail(&dst->trans_entry, &t->dst_list);
-       spin_unlock(&t->dst_lock);
-
-       return 0;
-
-err_out_free:
-       t->result = err;
-       netfs_trans_put(t);
-       mempool_free(dst, netfs_trans_dst_pool);
-       return err;
-}
-
-static void netfs_trans_free_dst(struct netfs_trans_dst *dst)
-{
-       netfs_trans_put(dst->trans);
-       mempool_free(dst, netfs_trans_dst_pool);
-}
-
-static void netfs_trans_remove_dst(struct netfs_trans_dst *dst)
-{
-       if (netfs_trans_remove_state(dst))
-               netfs_trans_free_dst(dst);
-}
-
-/*
- * Drop destination transaction entry when we know it.
- */
-void netfs_trans_drop_dst(struct netfs_trans_dst *dst)
-{
-       struct netfs_trans *t = dst->trans;
-
-       spin_lock(&t->dst_lock);
-       list_del_init(&dst->trans_entry);
-       spin_unlock(&t->dst_lock);
-
-       netfs_trans_remove_dst(dst);
-}
-
-/*
- * Drop destination transaction entry when we know it and when we
- * already removed dst from state tree.
- */
-void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst)
-{
-       struct netfs_trans *t = dst->trans;
-
-       spin_lock(&t->dst_lock);
-       list_del_init(&dst->trans_entry);
-       spin_unlock(&t->dst_lock);
-
-       netfs_trans_free_dst(dst);
-}
-
-/*
- * This drops destination transaction entry from appropriate network state
- * tree and drops related reference counter. It is possible that transaction
- * will be freed here if its reference counter hits zero.
- * Destination transaction entry will be freed.
- */
-void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst, *tmp, *ret = NULL;
-
-       spin_lock(&t->dst_lock);
-       list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
-               if (dst->state == st) {
-                       ret = dst;
-                       list_del(&dst->trans_entry);
-                       break;
-               }
-       }
-       spin_unlock(&t->dst_lock);
-
-       if (ret)
-               netfs_trans_remove_dst(ret);
-}
-
-/*
- * This drops destination transaction entry from appropriate network state
- * tree and drops related reference counter. It is possible that transaction
- * will be freed here if its reference counter hits zero.
- * Destination transaction entry will be freed.
- */
-void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst, *tmp, *ret;
-
-       spin_lock(&t->dst_lock);
-       ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry);
-       if (ret->state != st) {
-               ret = NULL;
-               list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
-                       if (dst->state == st) {
-                               ret = dst;
-                               list_del_init(&dst->trans_entry);
-                               break;
-                       }
-               }
-       } else {
-               list_del(&ret->trans_entry);
-       }
-       spin_unlock(&t->dst_lock);
-
-       if (ret)
-               netfs_trans_remove_dst(ret);
-}
-
-static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st)
-{
-       int err;
-
-       err = netfs_trans_push_dst(t, st);
-       if (err)
-               return err;
-
-       err = netfs_trans_send(t, st);
-       if (err)
-               goto err_out_free;
-
-       if (t->flags & NETFS_TRANS_SINGLE_DST)
-               pohmelfs_switch_active(st->psb);
-
-       return 0;
-
-err_out_free:
-       t->result = err;
-       netfs_trans_drop_last(t, st);
-
-       return err;
-}
-
-int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c;
-       int err = -ENODEV;
-       struct netfs_state *st;
-#if 0
-       dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n",
-               __func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state);
-#endif
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               if (t->flags & NETFS_TRANS_SINGLE_DST) {
-                       if (!(st->ctl.perm & POHMELFS_IO_PERM_READ))
-                               continue;
-               } else {
-                       if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE))
-                               continue;
-               }
-
-               if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio) &&
-                               (t->flags & NETFS_TRANS_SINGLE_DST))
-                       st = &psb->active_state->state;
-
-               err = netfs_trans_push(t, st);
-               if (!err && (t->flags & NETFS_TRANS_SINGLE_DST))
-                       break;
-       }
-
-       mutex_unlock(&psb->state_lock);
-#if 0
-       dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n",
-               __func__, t, t->gen, t->iovec.iov_len, t->page_num, err);
-#endif
-       if (err)
-               t->result = err;
-       return err;
-}
-
-int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
-       int err;
-       struct netfs_cmd *cmd = t->iovec.iov_base;
-
-       t->gen = atomic_inc_return(&psb->trans_gen);
-
-       cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) +
-               t->attached_size + t->attached_pages * sizeof(struct netfs_cmd);
-       cmd->cmd = NETFS_TRANS;
-       cmd->start = t->gen;
-       cmd->id = 0;
-
-       if (psb->perform_crypto) {
-               cmd->ext = psb->crypto_attached_size;
-               cmd->csize = psb->crypto_attached_size;
-       }
-
-       dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n",
-                       __func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages);
-       err = pohmelfs_trans_crypt(t, psb);
-       if (err) {
-               t->result = err;
-               netfs_convert_cmd(cmd);
-               dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n",
-                       __func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err);
-       }
-       netfs_trans_put(t);
-       return err;
-}
-
-/*
- * Resend transaction to remote server(s).
- * If new servers were added into superblock, we can try to send data
- * to them too.
- *
- * It is called under superblock's state_lock, so we can safely
- * dereference psb->state_list. Also, transaction's reference counter is
- * bumped, so it can not go away under us, thus we can safely access all
- * its members. State is locked.
- *
- * This function returns 0 if transaction was successfully sent to at
- * least one destination target.
- */
-int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
-       struct netfs_trans_dst *dst;
-       struct netfs_state *st;
-       struct pohmelfs_config *c;
-       int err, exist, error = -ENODEV;
-
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               exist = 0;
-               spin_lock(&t->dst_lock);
-               list_for_each_entry(dst, &t->dst_list, trans_entry) {
-                       if (st == dst->state) {
-                               exist = 1;
-                               break;
-                       }
-               }
-               spin_unlock(&t->dst_lock);
-
-               if (exist) {
-                       if (!(t->flags & NETFS_TRANS_SINGLE_DST) ||
-                                       (c->config_entry.next == &psb->state_list)) {
-                               dprintk("%s: resending st: %p, t: %p, gen: %u.\n",
-                                               __func__, st, t, t->gen);
-                               err = netfs_trans_send(t, st);
-                               if (!err)
-                                       error = 0;
-                       }
-                       continue;
-               }
-
-               dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n",
-                               __func__, st, t, t->gen);
-               err = netfs_trans_push(t, st);
-               if (err)
-                       continue;
-               error = 0;
-               if (t->flags & NETFS_TRANS_SINGLE_DST)
-                       break;
-       }
-
-       t->result = error;
-       return error;
-}
-
-void *netfs_trans_add(struct netfs_trans *t, unsigned int size)
-{
-       struct iovec *io = &t->iovec;
-       void *ptr;
-
-       if (size > t->total_size) {
-               ptr = ERR_PTR(-EINVAL);
-               goto out;
-       }
-
-       if (io->iov_len + size > t->total_size) {
-               dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n",
-                               __func__, t, t->gen, io->iov_len, size, t->total_size);
-               ptr = ERR_PTR(-E2BIG);
-               goto out;
-       }
-
-       ptr = io->iov_base + io->iov_len;
-       io->iov_len += size;
-
-out:
-       dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n",
-               __func__, t, t->gen, size, io->iov_len);
-       return ptr;
-}
-
-void netfs_trans_free(struct netfs_trans *t)
-{
-       if (t->eng)
-               pohmelfs_crypto_thread_make_ready(t->eng->thread);
-       kfree(t);
-}
-
-struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
-               unsigned int flags, unsigned int nr)
-{
-       struct netfs_trans *t;
-       unsigned int num, cont, pad, size_no_trans;
-       unsigned int crypto_added = 0;
-       struct netfs_cmd *cmd;
-
-       if (psb->perform_crypto)
-               crypto_added = psb->crypto_attached_size;
-
-       /*
-        * |sizeof(struct netfs_trans)|
-        * |sizeof(struct netfs_cmd)| - transaction header
-        * |size| - buffer with requested size
-        * |padding| - crypto padding, zero bytes
-        * |nr * sizeof(struct page *)| - array of page pointers
-        *
-        * Overall size should be less than PAGE_SIZE for guaranteed allocation.
-        */
-
-       cont = size;
-       size = ALIGN(size, psb->crypto_align_size);
-       pad = size - cont;
-
-       size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added;
-
-       cont = sizeof(struct netfs_trans) + size_no_trans;
-
-       num = (PAGE_SIZE - cont)/sizeof(struct page *);
-
-       if (nr > num)
-               nr = num;
-
-       t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO);
-       if (!t)
-               goto err_out_exit;
-
-       t->iovec.iov_base = (void *)(t + 1);
-       t->pages = (struct page **)(t->iovec.iov_base + size_no_trans);
-
-       /*
-        * Reserving space for transaction header.
-        */
-       t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added;
-
-       netfs_trans_init_static(t, nr, size_no_trans);
-
-       t->flags = flags;
-       t->psb = psb;
-
-       cmd = (struct netfs_cmd *)t->iovec.iov_base;
-
-       cmd->size = size;
-       cmd->cpad = pad;
-       cmd->csize = crypto_added;
-
-       dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, "
-                       "page_num: %u, base: %p, pages: %p.\n",
-                       __func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr,
-                       t->iovec.iov_base, t->pages);
-
-       return t;
-
-err_out_exit:
-       return NULL;
-}
-
-int netfs_trans_init(void)
-{
-       int err = -ENOMEM;
-
-       netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst),
-                       0, 0, NULL);
-       if (!netfs_trans_dst)
-               goto err_out_exit;
-
-       netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst);
-       if (!netfs_trans_dst_pool)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       kmem_cache_destroy(netfs_trans_dst);
-err_out_exit:
-       return err;
-}
-
-void netfs_trans_exit(void)
-{
-       mempool_destroy(netfs_trans_dst_pool);
-       kmem_cache_destroy(netfs_trans_dst);
-}
index 9b5d771e650ca240d99bd625fcd3ec33b090914f..ed85b4415207fcc397ae437dd4c6a98253f6a1cc 100644 (file)
@@ -37,6 +37,8 @@ struct _adapter;
 #include "wlan_bssdef.h"
 #include "rtl8712_spec.h"
 #include "rtl8712_hal.h"
+#include <linux/mutex.h>
+#include <linux/completion.h>
 
 enum _NIC_VERSION {
        RTL8711_NIC,
@@ -168,6 +170,7 @@ struct _adapter {
        s32     bSurpriseRemoved;
        u32     IsrContent;
        u32     ImrContent;
+       bool    fw_found;
        u8      EepromAddressSize;
        u8      hw_init_completed;
        struct task_struct *cmdThread;
@@ -184,6 +187,10 @@ struct _adapter {
        _workitem wkFilterRxFF0;
        u8 blnEnableRxFF0Filter;
        spinlock_t lockRxFF0Filter;
+       const struct firmware *fw;
+       struct usb_interface *pusb_intf;
+       struct mutex mutex_start;
+       struct completion rtl8712_fw_ready;
 };
 
 static inline u8 *myid(struct eeprom_priv *peepriv)
index d0029aa4cd3cefedacc5c2531363e4e3c46d5111..cc893c0f5ad3153f8c17c72947f948aa167bbf6d 100644 (file)
 #define FWBUFF_ALIGN_SZ 512
 #define MAX_DUMP_FWSZ  49152 /*default = 49152 (48k)*/
 
-static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl,
-                   const u8 **ppmappedfw)
+static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
 {
+       struct _adapter *padapter = context;
+
+       complete(&padapter->rtl8712_fw_ready);
+       if (!firmware) {
+               struct usb_device *udev = padapter->dvobjpriv.pusbdev;
+               struct usb_interface *pusb_intf = padapter->pusb_intf;
+               printk(KERN_ERR "r8712u: Firmware request failed\n");
+               padapter->fw_found = false;
+               usb_put_dev(udev);
+               usb_set_intfdata(pusb_intf, NULL);
+               return;
+       }
+       padapter->fw = firmware;
+       padapter->fw_found = true;
+       /* firmware available - start netdev */
+       register_netdev(padapter->pnetdev);
+}
+
+static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+
+int rtl871x_load_fw(struct _adapter *padapter)
+{
+       struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
        int rc;
-       const char firmware_file[] = "rtlwifi/rtl8712u.bin";
-       const struct firmware **praw = (const struct firmware **)
-                                      (pphfwfile_hdl);
-       struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
-                                       (&padapter->dvobjpriv);
-       struct usb_device *pusbdev = pdvobjpriv->pusbdev;
 
+       init_completion(&padapter->rtl8712_fw_ready);
        printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",
               firmware_file);
-       rc = request_firmware(praw, firmware_file, &pusbdev->dev);
-       if (rc < 0) {
-               printk(KERN_ERR "r8712u: Unable to load firmware\n");
-               printk(KERN_ERR "r8712u: Install latest linux-firmware\n");
+       rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
+                                    GFP_KERNEL, padapter, rtl871x_load_fw_cb);
+       if (rc)
+               printk(KERN_ERR "r8712u: Firmware request error %d\n", rc);
+       return rc;
+}
+MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
+
+static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw)
+{
+       const struct firmware **praw = &padapter->fw;
+
+       if (padapter->fw->size > 200000) {
+               printk(KERN_ERR "r8172u: Badfw->size of %d\n",
+                      (int)padapter->fw->size);
                return 0;
        }
        *ppmappedfw = (u8 *)((*praw)->data);
        return (*praw)->size;
 }
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
 
 static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
 {
@@ -142,18 +169,17 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
        uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
        struct fw_hdr fwhdr;
        u32 ulfilelength;       /* FW file size */
-       void *phfwfile_hdl = NULL;
        const u8 *pmappedfw = NULL;
        u8 *ptmpchar = NULL, *ppayload, *ptr;
        struct tx_desc *ptx_desc;
        u32 txdscp_sz = sizeof(struct tx_desc);
        u8 ret = _FAIL;
 
-       ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw);
+       ulfilelength = rtl871x_open_fw(padapter, &pmappedfw);
        if (pmappedfw && (ulfilelength > 0)) {
                update_fwhdr(&fwhdr, pmappedfw);
                if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
-                       goto firmware_rel;
+                       return ret;
                fill_fwpriv(padapter, &fwhdr.fwpriv);
                /* firmware check ok */
                maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
@@ -161,7 +187,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
                maxlen += txdscp_sz;
                ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ);
                if (ptmpchar == NULL)
-                       goto firmware_rel;
+                       return ret;
 
                ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ -
                            ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1)));
@@ -297,8 +323,6 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
 
 exit_fail:
        kfree(ptmpchar);
-firmware_rel:
-       release_firmware((struct firmware *)phfwfile_hdl);
        return ret;
 }
 
index 9a75c6dbe505e4b02eb7dc4d591bef31c78528e7..98a3d684f9b2c03e7717fb1bbe3b5a350d182c90 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
+#include <linux/firmware.h>
 #include "osdep_service.h"
 #include "drv_types.h"
 #include "xmit_osdep.h"
@@ -264,12 +265,12 @@ static void start_drv_timers(struct _adapter *padapter)
 void r8712_stop_drv_timers(struct _adapter *padapter)
 {
        _cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
-       _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
-                        sitesurvey_ctrl_timer);
        _cancel_timer_ex(&padapter->securitypriv.tkip_timer);
        _cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
        _cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);
        _cancel_timer_ex(&padapter->mlmepriv.wdg_timer);
+       _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
+                        sitesurvey_ctrl_timer);
 }
 
 static u8 init_default_value(struct _adapter *padapter)
@@ -347,7 +348,8 @@ u8 r8712_free_drv_sw(struct _adapter *padapter)
        r8712_free_mlme_priv(&padapter->mlmepriv);
        r8712_free_io_queue(padapter);
        _free_xmit_priv(&padapter->xmitpriv);
-       _r8712_free_sta_priv(&padapter->stapriv);
+       if (padapter->fw_found)
+               _r8712_free_sta_priv(&padapter->stapriv);
        _r8712_free_recv_priv(&padapter->recvpriv);
        mp871xdeinit(padapter);
        if (pnetdev)
@@ -388,6 +390,7 @@ static int netdev_open(struct net_device *pnetdev)
 {
        struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
 
+       mutex_lock(&padapter->mutex_start);
        if (padapter->bup == false) {
                padapter->bDriverStopped = false;
                padapter->bSurpriseRemoved = false;
@@ -435,11 +438,13 @@ static int netdev_open(struct net_device *pnetdev)
        /* start driver mlme relation timer */
        start_drv_timers(padapter);
        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
+       mutex_unlock(&padapter->mutex_start);
        return 0;
 netdev_open_error:
        padapter->bup = false;
        netif_carrier_off(pnetdev);
        netif_stop_queue(pnetdev);
+       mutex_unlock(&padapter->mutex_start);
        return -1;
 }
 
@@ -473,6 +478,9 @@ static int netdev_close(struct net_device *pnetdev)
        r8712_free_network_queue(padapter);
        /* The interface is no longer Up: */
        padapter->bup = false;
+       release_firmware(padapter->fw);
+       /* never exit with a firmware callback pending */
+       wait_for_completion(&padapter->rtl8712_fw_ready);
        return 0;
 }
 
index 665e71838172f0794a91c6d20fce02a7585c70f5..d19865a5a50c5ecba1fdf58bdc71d72d89b511ca 100644 (file)
@@ -145,5 +145,6 @@ struct hal_priv {
 };
 
 uint    rtl8712_hal_init(struct _adapter *padapter);
+int rtl871x_load_fw(struct _adapter *padapter);
 
 #endif
index 64f569618839669824b2c32dd2626943ea04d5bc..81bde803c59f40da22ad6873fec6d69367f5af09 100644 (file)
@@ -43,6 +43,7 @@ static void _init_stainfo(struct sta_info *psta)
        _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
        _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
 #ifdef CONFIG_R8712_AP
+       _init_listhead(&psta->asoc_list);
        _init_listhead(&psta->auth_list);
 #endif
 }
index 5385da2e9cdbcdf23186738a787a7b8dba2e553a..9bade184883bdd28a32bbe8f1e21fe365ef09993 100644 (file)
@@ -89,6 +89,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
        {USB_DEVICE(0x0DF6, 0x0045)},
        {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */
        {USB_DEVICE(0x0DF6, 0x004B)},
+       {USB_DEVICE(0x0DF6, 0x005B)},
        {USB_DEVICE(0x0DF6, 0x005D)},
        {USB_DEVICE(0x0DF6, 0x0063)},
        /* Sweex */
@@ -389,6 +390,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
        pdvobjpriv = &padapter->dvobjpriv;
        pdvobjpriv->padapter = padapter;
        padapter->dvobjpriv.pusbdev = udev;
+       padapter->pusb_intf = pusb_intf;
        usb_set_intfdata(pusb_intf, pnetdev);
        SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
        /* step 2. */
@@ -595,10 +597,11 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
                               "%pM\n", mac);
                memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
        }
-       /* step 6. Tell the network stack we exist */
-       if (register_netdev(pnetdev) != 0)
+       /* step 6. Load the firmware asynchronously */
+       if (rtl871x_load_fw(padapter))
                goto error;
        spin_lock_init(&padapter->lockRxFF0Filter);
+       mutex_init(&padapter->mutex_start);
        return 0;
 error:
        usb_put_dev(udev);
@@ -629,7 +632,8 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
                flush_scheduled_work();
                udelay(1);
                /*Stop driver mlme relation timer */
-               r8712_stop_drv_timers(padapter);
+               if (padapter->fw_found)
+                       r8712_stop_drv_timers(padapter);
                r871x_dev_unload(padapter);
                r8712_free_drv_sw(padapter);
        }
index e1c4492a71052970c76f3592041cb5f37a80fcbe..dde559d06c43740be42b32add7f71e7b89f61379 100644 (file)
@@ -1046,8 +1046,6 @@ static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt)
 
        /* Free the driver's device context: */
        kfree(drv_datap->base_img);
-       kfree(drv_datap);
-       dev_set_drvdata(bridge, NULL);
        kfree((void *)dev_ctxt);
        return status;
 }
index 76cfc6edecd9e26d46f7c3b37fbbf6d81cebdcd3..385740bad0de7250bba9ec69bd311e5e5b2866e6 100644 (file)
@@ -410,6 +410,9 @@ static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev)
                DBC_ASSERT(ret == true);
        }
 
+       kfree(drv_datap);
+       dev_set_drvdata(bridge, NULL);
+
 func_cont:
        mem_ext_phys_pool_release();
 
@@ -500,35 +503,42 @@ static int bridge_open(struct inode *ip, struct file *filp)
        }
 #endif
        pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL);
-       if (pr_ctxt) {
-               pr_ctxt->res_state = PROC_RES_ALLOCATED;
-               spin_lock_init(&pr_ctxt->dmm_map_lock);
-               INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
-               spin_lock_init(&pr_ctxt->dmm_rsv_lock);
-               INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
-
-               pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
-               if (pr_ctxt->node_id) {
-                       idr_init(pr_ctxt->node_id);
-               } else {
-                       status = -ENOMEM;
-                       goto err;
-               }
+       if (!pr_ctxt)
+               return -ENOMEM;
+
+       pr_ctxt->res_state = PROC_RES_ALLOCATED;
+       spin_lock_init(&pr_ctxt->dmm_map_lock);
+       INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
+       spin_lock_init(&pr_ctxt->dmm_rsv_lock);
+       INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
 
-               pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
-               if (pr_ctxt->stream_id)
-                       idr_init(pr_ctxt->stream_id);
-               else
-                       status = -ENOMEM;
-       } else {
+       pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
+       if (!pr_ctxt->node_id) {
                status = -ENOMEM;
+               goto err1;
        }
-err:
+
+       idr_init(pr_ctxt->node_id);
+
+       pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
+       if (!pr_ctxt->stream_id) {
+               status = -ENOMEM;
+               goto err2;
+       }
+
+       idr_init(pr_ctxt->stream_id);
+
        filp->private_data = pr_ctxt;
+
 #ifdef CONFIG_TIDSPBRIDGE_RECOVERY
-       if (!status)
-               atomic_inc(&bridge_cref);
+       atomic_inc(&bridge_cref);
 #endif
+       return 0;
+
+err2:
+       kfree(pr_ctxt->node_id);
+err1:
+       kfree(pr_ctxt);
        return status;
 }
 
@@ -550,6 +560,8 @@ static int bridge_release(struct inode *ip, struct file *filp)
        flush_signals(current);
        drv_remove_all_resources(pr_ctxt);
        proc_detach(pr_ctxt);
+       kfree(pr_ctxt->node_id);
+       kfree(pr_ctxt->stream_id);
        kfree(pr_ctxt);
 
        filp->private_data = NULL;
index 2d6317850064aea62cca1119e054f1d79f0e0c0a..705a9e530a19c378fd16d3db39033bfea7342dce 100644 (file)
@@ -246,8 +246,9 @@ static int __init usbip_host_init(void)
 {
        int ret;
 
-       stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
+       init_busid_table();
 
+       stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
        if (!stub_priv_cache) {
                pr_err("kmem_cache_create failed\n");
                return -ENOMEM;
@@ -266,7 +267,6 @@ static int __init usbip_host_init(void)
                goto err_create_file;
        }
 
-       init_busid_table();
        pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
        return ret;
 
index 642840c612ac9a2e179bee7af972b432d0736848..ef7c52bb1df9f014d853d8a221dd15077efbc340 100644 (file)
@@ -358,8 +358,8 @@ static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id,
        if (unlikely(zbpg == NULL))
                goto out;
        /* ok, have a page, now compress the data before taking locks */
-       spin_lock(&zbpg->lock);
        spin_lock(&zbud_budlists_spinlock);
+       spin_lock(&zbpg->lock);
        list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list);
        zbud_unbuddied[nchunks].count++;
        zh = &zbpg->buddy[0];
@@ -389,12 +389,11 @@ init_zh:
        zh->oid = *oid;
        zh->pool_id = pool_id;
        zh->client_id = client_id;
-       /* can wait to copy the data until the list locks are dropped */
-       spin_unlock(&zbud_budlists_spinlock);
-
        to = zbud_data(zh, size);
        memcpy(to, cdata, size);
        spin_unlock(&zbpg->lock);
+       spin_unlock(&zbud_budlists_spinlock);
+
        zbud_cumul_chunk_counts[nchunks]++;
        atomic_inc(&zcache_zbud_curr_zpages);
        zcache_zbud_cumul_zpages++;
@@ -655,8 +654,8 @@ static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7;
  */
 static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5;
 
-static unsigned long zv_curr_dist_counts[NCHUNKS];
-static unsigned long zv_cumul_dist_counts[NCHUNKS];
+static atomic_t zv_curr_dist_counts[NCHUNKS];
+static atomic_t zv_cumul_dist_counts[NCHUNKS];
 
 static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
                                struct tmem_oid *oid, uint32_t index,
@@ -675,8 +674,8 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
                        &page, &offset, ZCACHE_GFP_MASK);
        if (unlikely(ret))
                goto out;
-       zv_curr_dist_counts[chunks]++;
-       zv_cumul_dist_counts[chunks]++;
+       atomic_inc(&zv_curr_dist_counts[chunks]);
+       atomic_inc(&zv_cumul_dist_counts[chunks]);
        zv = kmap_atomic(page, KM_USER0) + offset;
        zv->index = index;
        zv->oid = *oid;
@@ -698,7 +697,7 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)
 
        ASSERT_SENTINEL(zv, ZVH);
        BUG_ON(chunks >= NCHUNKS);
-       zv_curr_dist_counts[chunks]--;
+       atomic_dec(&zv_curr_dist_counts[chunks]);
        size -= sizeof(*zv);
        BUG_ON(size == 0);
        INVERT_SENTINEL(zv, ZVH);
@@ -738,7 +737,7 @@ static int zv_curr_dist_counts_show(char *buf)
        char *p = buf;
 
        for (i = 0; i < NCHUNKS; i++) {
-               n = zv_curr_dist_counts[i];
+               n = atomic_read(&zv_curr_dist_counts[i]);
                p += sprintf(p, "%lu ", n);
                chunks += n;
                sum_total_chunks += i * n;
@@ -754,7 +753,7 @@ static int zv_cumul_dist_counts_show(char *buf)
        char *p = buf;
 
        for (i = 0; i < NCHUNKS; i++) {
-               n = zv_cumul_dist_counts[i];
+               n = atomic_read(&zv_cumul_dist_counts[i]);
                p += sprintf(p, "%lu ", n);
                chunks += n;
                sum_total_chunks += i * n;
@@ -1782,9 +1781,9 @@ static int zcache_frontswap_poolid = -1;
  * Swizzling increases objects per swaptype, increasing tmem concurrency
  * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS
  * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from
- * frontswap_get_page()
+ * frontswap_get_page(), but has side-effects. Hence using 8.
  */
-#define SWIZ_BITS              27
+#define SWIZ_BITS              8
 #define SWIZ_MASK              ((1 << SWIZ_BITS) - 1)
 #define _oswiz(_type, _ind)    ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
 #define iswiz(_ind)            (_ind >> SWIZ_BITS)
index 8599545cdf9e6d6c90a07510844f6290ab0a1be6..44262908def547557e5c3fe0a8a8cd34a00dfbd7 100644 (file)
@@ -27,8 +27,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_parameters.h"
@@ -284,8 +283,8 @@ static struct iscsi_np *iscsit_get_np(
                        sock_in6 = (struct sockaddr_in6 *)sockaddr;
                        sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
 
-                       if (!memcmp((void *)&sock_in6->sin6_addr.in6_u,
-                                   (void *)&sock_in6_e->sin6_addr.in6_u,
+                       if (!memcmp(&sock_in6->sin6_addr.in6_u,
+                                   &sock_in6_e->sin6_addr.in6_u,
                                    sizeof(struct in6_addr)))
                                ip_match = 1;
 
@@ -1062,7 +1061,7 @@ attach_cmd:
        if (ret < 0)
                return iscsit_add_reject_from_cmd(
                                ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 1, buf, cmd);
+                               1, 0, buf, cmd);
        /*
         * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
         * the Immediate Bit is not set, and no Immediate
@@ -1225,7 +1224,7 @@ static void iscsit_do_crypto_hash_buf(
 
        crypto_hash_init(hash);
 
-       sg_init_one(&sg, (u8 *)buf, payload_length);
+       sg_init_one(&sg, buf, payload_length);
        crypto_hash_update(hash, &sg, payload_length);
 
        if (padding) {
@@ -1603,7 +1602,7 @@ static int iscsit_handle_nop_out(
                /*
                 * Attach ping data to struct iscsi_cmd->buf_ptr.
                 */
-               cmd->buf_ptr = (void *)ping_data;
+               cmd->buf_ptr = ping_data;
                cmd->buf_ptr_size = payload_length;
 
                pr_debug("Got %u bytes of NOPOUT ping"
@@ -3165,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(
        return 0;
 }
 
+static bool iscsit_check_inaddr_any(struct iscsi_np *np)
+{
+       bool ret = false;
+
+       if (np->np_sockaddr.ss_family == AF_INET6) {
+               const struct sockaddr_in6 sin6 = {
+                       .sin6_addr = IN6ADDR_ANY_INIT };
+               struct sockaddr_in6 *sock_in6 =
+                        (struct sockaddr_in6 *)&np->np_sockaddr;
+
+               if (!memcmp(sock_in6->sin6_addr.s6_addr,
+                               sin6.sin6_addr.s6_addr, 16))
+                       ret = true;
+       } else {
+               struct sockaddr_in * sock_in =
+                       (struct sockaddr_in *)&np->np_sockaddr;
+
+               if (sock_in->sin_addr.s_addr == INADDR_ANY)
+                       ret = true;
+       }
+
+       return ret;
+}
+
 static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
 {
        char *payload = NULL;
@@ -3197,7 +3220,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                        end_of_buf = 1;
                        goto eob;
                }
-               memcpy((void *)payload + payload_len, buf, len);
+               memcpy(payload + payload_len, buf, len);
                payload_len += len;
 
                spin_lock(&tiqn->tiqn_tpg_lock);
@@ -3214,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                        spin_lock(&tpg->tpg_np_lock);
                        list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
                                                tpg_np_list) {
+                               struct iscsi_np *np = tpg_np->tpg_np;
+                               bool inaddr_any = iscsit_check_inaddr_any(np);
+
                                len = sprintf(buf, "TargetAddress="
                                        "%s%s%s:%hu,%hu",
-                                       (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
-                                       "[" : "", tpg_np->tpg_np->np_ip,
-                                       (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
-                                       "]" : "", tpg_np->tpg_np->np_port,
+                                       (np->np_sockaddr.ss_family == AF_INET6) ?
+                                       "[" : "", (inaddr_any == false) ?
+                                               np->np_ip : conn->local_ip,
+                                       (np->np_sockaddr.ss_family == AF_INET6) ?
+                                       "]" : "", (inaddr_any == false) ?
+                                               np->np_port : conn->local_port,
                                        tpg->tpgt);
                                len += 1;
 
@@ -3229,7 +3257,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                                        end_of_buf = 1;
                                        goto eob;
                                }
-                               memcpy((void *)payload + payload_len, buf, len);
+                               memcpy(payload + payload_len, buf, len);
                                payload_len += len;
                        }
                        spin_unlock(&tpg->tpg_np_lock);
@@ -3486,7 +3514,7 @@ int iscsi_target_tx_thread(void *arg)
        struct iscsi_conn *conn;
        struct iscsi_queue_req *qr = NULL;
        struct se_cmd *se_cmd;
-       struct iscsi_thread_set *ts = (struct iscsi_thread_set *)arg;
+       struct iscsi_thread_set *ts = arg;
        /*
         * Allow ourselves to be interrupted by SIGINT so that a
         * connection recovery / failure event can be triggered externally.
@@ -3775,7 +3803,7 @@ int iscsi_target_rx_thread(void *arg)
        u8 buffer[ISCSI_HDR_LEN], opcode;
        u32 checksum = 0, digest = 0;
        struct iscsi_conn *conn = NULL;
-       struct iscsi_thread_set *ts = (struct iscsi_thread_set *)arg;
+       struct iscsi_thread_set *ts = arg;
        struct kvec iov;
        /*
         * Allow ourselves to be interrupted by SIGINT so that a
index 1cd6ce373b83508fd396f82b80290b91372c9e96..db0cf7c8adde04db2b272660a6047297fa848a78 100644 (file)
@@ -82,7 +82,7 @@ static void chap_gen_challenge(
        unsigned int *c_len)
 {
        unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
-       struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+       struct iscsi_chap *chap = conn->auth_protocol;
 
        memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
 
@@ -120,7 +120,7 @@ static struct iscsi_chap *chap_server_open(
        if (!conn->auth_protocol)
                return NULL;
 
-       chap = (struct iscsi_chap *) conn->auth_protocol;
+       chap = conn->auth_protocol;
        /*
         * We only support MD5 MDA presently.
         */
@@ -165,14 +165,15 @@ static int chap_server_compute_md5(
        unsigned int *nr_out_len)
 {
        char *endptr;
-       unsigned char id, digest[MD5_SIGNATURE_SIZE];
+       unsigned long id;
+       unsigned char digest[MD5_SIGNATURE_SIZE];
        unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2];
        unsigned char identifier[10], *challenge = NULL;
        unsigned char *challenge_binhex = NULL;
        unsigned char client_digest[MD5_SIGNATURE_SIZE];
        unsigned char server_digest[MD5_SIGNATURE_SIZE];
        unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
-       struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+       struct iscsi_chap *chap = conn->auth_protocol;
        struct crypto_hash *tfm;
        struct hash_desc desc;
        struct scatterlist sg;
@@ -246,7 +247,7 @@ static int chap_server_compute_md5(
                goto out;
        }
 
-       sg_init_one(&sg, (void *)&chap->id, 1);
+       sg_init_one(&sg, &chap->id, 1);
        ret = crypto_hash_update(&desc, &sg, 1);
        if (ret < 0) {
                pr_err("crypto_hash_update() failed for id\n");
@@ -254,7 +255,7 @@ static int chap_server_compute_md5(
                goto out;
        }
 
-       sg_init_one(&sg, (void *)&auth->password, strlen(auth->password));
+       sg_init_one(&sg, &auth->password, strlen(auth->password));
        ret = crypto_hash_update(&desc, &sg, strlen(auth->password));
        if (ret < 0) {
                pr_err("crypto_hash_update() failed for password\n");
@@ -262,7 +263,7 @@ static int chap_server_compute_md5(
                goto out;
        }
 
-       sg_init_one(&sg, (void *)chap->challenge, CHAP_CHALLENGE_LENGTH);
+       sg_init_one(&sg, chap->challenge, CHAP_CHALLENGE_LENGTH);
        ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH);
        if (ret < 0) {
                pr_err("crypto_hash_update() failed for challenge\n");
@@ -305,14 +306,17 @@ static int chap_server_compute_md5(
        }
 
        if (type == HEX)
-               id = (unsigned char)simple_strtoul((char *)&identifier[2],
-                                       &endptr, 0);
+               id = simple_strtoul(&identifier[2], &endptr, 0);
        else
-               id = (unsigned char)simple_strtoul(identifier, &endptr, 0);
+               id = simple_strtoul(identifier, &endptr, 0);
+       if (id > 255) {
+               pr_err("chap identifier: %lu greater than 255\n", id);
+               goto out;
+       }
        /*
         * RFC 1994 says Identifier is no more than octet (8 bits).
         */
-       pr_debug("[server] Got CHAP_I=%d\n", id);
+       pr_debug("[server] Got CHAP_I=%lu\n", id);
        /*
         * Get CHAP_C.
         */
@@ -351,7 +355,7 @@ static int chap_server_compute_md5(
                goto out;
        }
 
-       sg_init_one(&sg, (void *)&id, 1);
+       sg_init_one(&sg, &id, 1);
        ret = crypto_hash_update(&desc, &sg, 1);
        if (ret < 0) {
                pr_err("crypto_hash_update() failed for id\n");
@@ -359,7 +363,7 @@ static int chap_server_compute_md5(
                goto out;
        }
 
-       sg_init_one(&sg, (void *)auth->password_mutual,
+       sg_init_one(&sg, auth->password_mutual,
                                strlen(auth->password_mutual));
        ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual));
        if (ret < 0) {
@@ -371,7 +375,7 @@ static int chap_server_compute_md5(
        /*
         * Convert received challenge to binary hex.
         */
-       sg_init_one(&sg, (void *)challenge_binhex, challenge_len);
+       sg_init_one(&sg, challenge_binhex, challenge_len);
        ret = crypto_hash_update(&desc, &sg, challenge_len);
        if (ret < 0) {
                pr_err("crypto_hash_update() failed for ma challenge\n");
@@ -414,7 +418,7 @@ static int chap_got_response(
        char *nr_out_ptr,
        unsigned int *nr_out_len)
 {
-       struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+       struct iscsi_chap *chap = conn->auth_protocol;
 
        switch (chap->digest_type) {
        case CHAP_DIGEST_MD5:
@@ -437,7 +441,7 @@ u32 chap_main_loop(
        int *in_len,
        int *out_len)
 {
-       struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+       struct iscsi_chap *chap = conn->auth_protocol;
 
        if (!chap) {
                chap = chap_server_open(conn, auth, in_text, out_text, out_len);
index db327845e46b46fc04d6f2be7a21d68d9aa53d53..6b35b37988edef2015df364158baad734a119e93 100644 (file)
 
 #include <linux/configfs.h>
 #include <linux/export.h>
+#include <linux/inet.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_fabric_configfs.h>
-#include <target/target_core_fabric_lib.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
@@ -56,8 +53,7 @@ struct iscsi_portal_group *lio_get_tpg_from_tpg_item(
 {
        struct se_portal_group *se_tpg = container_of(to_config_group(item),
                                        struct se_portal_group, tpg_group);
-       struct iscsi_portal_group *tpg =
-                       (struct iscsi_portal_group *)se_tpg->se_tpg_fabric_ptr;
+       struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
        int ret;
 
        if (!tpg) {
@@ -1225,7 +1221,7 @@ struct se_portal_group *lio_target_tiqn_addtpg(
 
        ret = core_tpg_register(
                        &lio_target_fabric_configfs->tf_ops,
-                       wwn, &tpg->tpg_se_tpg, (void *)tpg,
+                       wwn, &tpg->tpg_se_tpg, tpg,
                        TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0)
                return NULL;
index f1a02dad05a02855b4ef59a6341e4bb61660ef30..0ec3b77a0c272e39066fdd8104771a88f59cce08 100644 (file)
@@ -508,6 +508,7 @@ struct iscsi_conn {
        u16                     cid;
        /* Remote TCP Port */
        u16                     login_port;
+       u16                     local_port;
        int                     net_size;
        u32                     auth_id;
 #define CONNFLAG_SCTP_STRUCT_FILE                      0x01
@@ -527,6 +528,7 @@ struct iscsi_conn {
        unsigned char           bad_hdr[ISCSI_HDR_LEN];
 #define IPV6_ADDRESS_SPACE                             48
        unsigned char           login_ip[IPV6_ADDRESS_SPACE];
+       unsigned char           local_ip[IPV6_ADDRESS_SPACE];
        int                     conn_usage_count;
        int                     conn_waiting_on_uc;
        atomic_t                check_immediate_queue;
@@ -561,8 +563,8 @@ struct iscsi_conn {
        struct hash_desc        conn_tx_hash;
        /* Used for scheduling TX and RX connection kthreads */
        cpumask_var_t           conn_cpumask;
-       int                     conn_rx_reset_cpumask:1;
-       int                     conn_tx_reset_cpumask:1;
+       unsigned int            conn_rx_reset_cpumask:1;
+       unsigned int            conn_tx_reset_cpumask:1;
        /* list_head of struct iscsi_cmd for this connection */
        struct list_head        conn_cmd_list;
        struct list_head        immed_queue_list;
index a19fa5eea88e8edcd3db9ab57bc399ad150dd15d..f63ea35bc4ae7737c7ad16b443b2a6ea9c017e2e 100644 (file)
@@ -21,8 +21,7 @@
 
 #include <scsi/scsi_device.h>
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_device.h"
index b7ffc3cd40cca0141ac02441894a1bd018fc2f0e..478451167b62b4c1b3b443e08b1bb6c06ff10cad 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_seq_pdu_list.h"
index 101b1beb3bca205aed7611ec4424f54cc5b20671..27901e37c1256c9daad677824e5931cc41485da1 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/list.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_seq_pdu_list.h"
@@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
 {
        struct iscsi_conn *conn = cmd->conn;
        struct iscsi_session *sess = conn->sess;
-       struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+       struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
 
        spin_lock_bh(&cmd->dataout_timeout_lock);
        if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
@@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(
        struct iscsi_conn *conn)
 {
        struct iscsi_session *sess = conn->sess;
-       struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+       struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
 
        if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
                return;
index 0b8404c30125256a99bff82082516c324ff16364..1af1f21af21fd01735eab9cec3f2369246e69bd4 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_datain_values.h"
index d734bdec24f9cf2b451a7f905b07fab421a19b3b..38cb7ce8469ed36084eb739bd7336f4376f03cbd 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/crypto.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_tq.h"
@@ -143,7 +143,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
        list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
                        sess_list) {
 
-               sess_p = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess_p = se_sess->fabric_sess_ptr;
                spin_lock(&sess_p->conn_lock);
                if (atomic_read(&sess_p->session_fall_back_to_erl0) ||
                    atomic_read(&sess_p->session_logout) ||
@@ -151,9 +151,9 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
                        spin_unlock(&sess_p->conn_lock);
                        continue;
                }
-               if (!memcmp((void *)sess_p->isid, (void *)conn->sess->isid, 6) &&
-                  (!strcmp((void *)sess_p->sess_ops->InitiatorName,
-                           (void *)initiatorname_param->value) &&
+               if (!memcmp(sess_p->isid, conn->sess->isid, 6) &&
+                  (!strcmp(sess_p->sess_ops->InitiatorName,
+                           initiatorname_param->value) &&
                   (sess_p->sess_ops->SessionType == sessiontype))) {
                        atomic_set(&sess_p->session_reinstatement, 1);
                        spin_unlock(&sess_p->conn_lock);
@@ -229,7 +229,7 @@ static int iscsi_login_zero_tsih_s1(
 
        iscsi_login_set_conn_values(sess, conn, pdu->cid);
        sess->init_task_tag     = pdu->itt;
-       memcpy((void *)&sess->isid, (void *)pdu->isid, 6);
+       memcpy(&sess->isid, pdu->isid, 6);
        sess->exp_cmd_sn        = pdu->cmdsn;
        INIT_LIST_HEAD(&sess->sess_conn_list);
        INIT_LIST_HEAD(&sess->sess_ooo_cmdsn_list);
@@ -440,8 +440,7 @@ static int iscsi_login_non_zero_tsih_s2(
                    atomic_read(&sess_p->session_logout) ||
                   (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED))
                        continue;
-               if (!memcmp((const void *)sess_p->isid,
-                    (const void *)pdu->isid, 6) &&
+               if (!memcmp(sess_p->isid, pdu->isid, 6) &&
                     (sess_p->tsih == pdu->tsih)) {
                        iscsit_inc_session_usage_count(sess_p);
                        iscsit_stop_time2retain_timer(sess_p);
@@ -616,8 +615,8 @@ static int iscsi_post_login_handler(
                }
 
                pr_debug("iSCSI Login successful on CID: %hu from %s to"
-                       " %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip,
-                               np->np_port, tpg->tpgt);
+                       " %s:%hu,%hu\n", conn->cid, conn->login_ip,
+                       conn->local_ip, conn->local_port, tpg->tpgt);
 
                list_add_tail(&conn->conn_list, &sess->sess_conn_list);
                atomic_inc(&sess->nconn);
@@ -654,12 +653,13 @@ static int iscsi_post_login_handler(
 
        spin_lock_bh(&se_tpg->session_lock);
        __transport_register_session(&sess->tpg->tpg_se_tpg,
-                       se_sess->se_node_acl, se_sess, (void *)sess);
+                       se_sess->se_node_acl, se_sess, sess);
        pr_debug("Moving to TARG_SESS_STATE_LOGGED_IN.\n");
        sess->session_state = TARG_SESS_STATE_LOGGED_IN;
 
        pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
-               conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt);
+               conn->cid, conn->login_ip, conn->local_ip, conn->local_port,
+               tpg->tpgt);
 
        spin_lock_bh(&sess->conn_lock);
        list_add_tail(&conn->conn_list, &sess->sess_conn_list);
@@ -811,7 +811,7 @@ int iscsi_target_setup_login_socket(
         * Setup the np->np_sockaddr from the passed sockaddr setup
         * in iscsi_target_configfs.c code..
         */
-       memcpy((void *)&np->np_sockaddr, (void *)sockaddr,
+       memcpy(&np->np_sockaddr, sockaddr,
                        sizeof(struct __kernel_sockaddr_storage));
 
        if (sockaddr->ss_family == AF_INET6)
@@ -821,6 +821,7 @@ int iscsi_target_setup_login_socket(
        /*
         * Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY.
         */
+       /* FIXME: Someone please explain why this is endian-safe */
        opt = 1;
        if (np->np_network_transport == ISCSI_TCP) {
                ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
@@ -832,6 +833,7 @@ int iscsi_target_setup_login_socket(
                }
        }
 
+       /* FIXME: Someone please explain why this is endian-safe */
        ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
                        (char *)&opt, sizeof(opt));
        if (ret < 0) {
@@ -840,6 +842,14 @@ int iscsi_target_setup_login_socket(
                goto fail;
        }
 
+       ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
+                       (char *)&opt, sizeof(opt));
+       if (ret < 0) {
+               pr_err("kernel_setsockopt() for IP_FREEBIND"
+                       " failed\n");
+               goto fail;
+       }
+
        ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
        if (ret < 0) {
                pr_err("kernel_bind() failed: %d\n", ret);
@@ -1019,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
                                &sock_in6.sin6_addr.in6_u);
                conn->login_port = ntohs(sock_in6.sin6_port);
+
+               if (conn->sock->ops->getname(conn->sock,
+                               (struct sockaddr *)&sock_in6, &err, 0) < 0) {
+                       pr_err("sock_ops->getname() failed.\n");
+                       iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                                       ISCSI_LOGIN_STATUS_TARGET_ERROR);
+                       goto new_sess_out;
+               }
+               snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
+                               &sock_in6.sin6_addr.in6_u);
+               conn->local_port = ntohs(sock_in6.sin6_port);
+
        } else {
                memset(&sock_in, 0, sizeof(struct sockaddr_in));
 
@@ -1031,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                }
                sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
                conn->login_port = ntohs(sock_in.sin_port);
+
+               if (conn->sock->ops->getname(conn->sock,
+                               (struct sockaddr *)&sock_in, &err, 0) < 0) {
+                       pr_err("sock_ops->getname() failed.\n");
+                       iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                                       ISCSI_LOGIN_STATUS_TARGET_ERROR);
+                       goto new_sess_out;
+               }
+               sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
+               conn->local_port = ntohs(sock_in.sin_port);
        }
 
        conn->network_transport = np->np_network_transport;
@@ -1038,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        pr_debug("Received iSCSI login request from %s on %s Network"
                        " Portal %s:%hu\n", conn->login_ip,
                (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
-                       np->np_ip, np->np_port);
+                       conn->local_ip, conn->local_port);
 
        pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
        conn->conn_state        = TARG_CONN_STATE_IN_LOGIN;
@@ -1206,7 +1238,7 @@ out:
 
 int iscsi_target_login_thread(void *arg)
 {
-       struct iscsi_np *np = (struct iscsi_np *)arg;
+       struct iscsi_np *np = arg;
        int ret;
 
        allow_signal(SIGINT);
index 98936cb7c2947ceb0edbaa41dda91d6641a9b892..e89fa7457254d6f44fde426dceaab84de0a99fa2 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/ctype.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_parameters.h"
@@ -732,7 +732,7 @@ static void iscsi_initiatorname_tolower(
        u32 iqn_size = strlen(param_buf), i;
 
        for (i = 0; i < iqn_size; i++) {
-               c = (char *)&param_buf[i];
+               c = &param_buf[i];
                if (!isupper(*c))
                        continue;
 
index aeafbe0cd7d11b294053f1424e5d91cb3c7336ac..b3c699c4fe8ceb8b9dc2fe35a3eb0e94abfc1126 100644 (file)
@@ -19,7 +19,6 @@
  ******************************************************************************/
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_device.h"
@@ -135,7 +134,7 @@ extern int iscsit_na_nopin_timeout(
                spin_lock_bh(&se_nacl->nacl_sess_lock);
                se_sess = se_nacl->nacl_sess;
                if (se_sess) {
-                       sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+                       sess = se_sess->fabric_sess_ptr;
 
                        spin_lock(&sess->conn_lock);
                        list_for_each_entry(conn, &sess->sess_conn_list,
index f1db83077e0a8418d448a7d9b210cc63014b1d3c..421d6947dc64247c2bc02a1136f8bb2e0489c64a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/export.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
 #include <target/configfs_macros.h>
 
 #include "iscsi_target_core.h"
@@ -746,7 +745,7 @@ static ssize_t iscsi_stat_sess_show_attr_node(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%u\n",
                                sess->sess_ops->SessionType ? 0 : ISCSI_NODE_INDEX);
@@ -770,7 +769,7 @@ static ssize_t iscsi_stat_sess_show_attr_indx(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%u\n",
                                        sess->session_index);
@@ -794,7 +793,7 @@ static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%u\n", sess->cmd_pdus);
        }
@@ -817,7 +816,7 @@ static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%u\n", sess->rsp_pdus);
        }
@@ -840,7 +839,7 @@ static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%llu\n",
                                (unsigned long long)sess->tx_data_octets);
@@ -864,7 +863,7 @@ static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%llu\n",
                                (unsigned long long)sess->rx_data_octets);
@@ -888,7 +887,7 @@ static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%u\n",
                                        sess->conn_digest_errors);
@@ -912,7 +911,7 @@ static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
        spin_lock_bh(&se_nacl->nacl_sess_lock);
        se_sess = se_nacl->nacl_sess;
        if (se_sess) {
-               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+               sess = se_sess->fabric_sess_ptr;
                if (sess)
                        ret = snprintf(page, PAGE_SIZE, "%u\n",
                                        sess->conn_timeout_errors);
index 490207eacde976a179f1197d21f3901afd1c78e0..255ed35da815e3059c1930683255575b51ff58d7 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/unaligned.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_seq_pdu_list.h"
index d4cf2cd25c447f8ac109f7dcdc20fca572d96abc..879d8d0fa3feb38e061c911887e50a91a286c30f 100644 (file)
  ******************************************************************************/
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_tpg.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_erl0.h"
@@ -72,7 +70,7 @@ int iscsit_load_discovery_tpg(void)
 
        ret = core_tpg_register(
                        &lio_target_fabric_configfs->tf_ops,
-                       NULL, &tpg->tpg_se_tpg, (void *)tpg,
+                       NULL, &tpg->tpg_se_tpg, tpg,
                        TRANSPORT_TPG_TYPE_DISCOVERY);
        if (ret < 0) {
                kfree(tpg);
index 02348f727bd4ddaaa4ef4b70e3499fc135001dad..11287e1ece134190b6541bdb2bea45a236e46515 100644 (file)
@@ -22,9 +22,7 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
 #include "iscsi_target_core.h"
@@ -289,7 +287,7 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
        }
 
        se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd,
-                               (void *)cmd->tmr_req, tcm_function,
+                               cmd->tmr_req, tcm_function,
                                GFP_KERNEL);
        if (!se_cmd->se_tmr_req)
                goto out;
@@ -851,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
        case ISCSI_OP_SCSI_TMFUNC:
                transport_generic_free_cmd(&cmd->se_cmd, 1);
                break;
+       case ISCSI_OP_REJECT:
+               /*
+                * Handle special case for REJECT when iscsi_add_reject*() has
+                * overwritten the original iscsi_opcode assignment, and the
+                * associated cmd->se_cmd needs to be released.
+                */
+               if (cmd->se_cmd.se_tfo != NULL) {
+                       transport_generic_free_cmd(&cmd->se_cmd, 1);
+                       break;
+               }
+               /* Fall-through */
        default:
                iscsit_release_cmd(cmd);
                break;
@@ -1066,7 +1075,7 @@ static void iscsit_handle_nopin_response_timeout(unsigned long data)
        if (tiqn) {
                spin_lock_bh(&tiqn->sess_err_stats.lock);
                strcpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
-                               (void *)conn->sess->sess_ops->InitiatorName);
+                               conn->sess->sess_ops->InitiatorName);
                tiqn->sess_err_stats.last_sess_failure_type =
                                ISCSI_SESS_ERR_CXN_TIMEOUT;
                tiqn->sess_err_stats.cxn_timeout_errors++;
index 81d5832fbbd537e7bbffe2c21b1792c1e7a2acde..c47ff7f59e5733226702004617327a28b566f7f1 100644 (file)
 #include <scsi/scsi_cmnd.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_fabric_configfs.h>
-#include <target/target_core_fabric_lib.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_tmr.h>
 
 #include "tcm_loop.h"
 
@@ -421,11 +416,11 @@ static struct scsi_host_template tcm_loop_driver_template = {
        .queuecommand           = tcm_loop_queuecommand,
        .change_queue_depth     = tcm_loop_change_queue_depth,
        .eh_device_reset_handler = tcm_loop_device_reset,
-       .can_queue              = TL_SCSI_CAN_QUEUE,
+       .can_queue              = 1024,
        .this_id                = -1,
-       .sg_tablesize           = TL_SCSI_SG_TABLESIZE,
-       .cmd_per_lun            = TL_SCSI_CMD_PER_LUN,
-       .max_sectors            = TL_SCSI_MAX_SECTORS,
+       .sg_tablesize           = 256,
+       .cmd_per_lun            = 1024,
+       .max_sectors            = 0xFFFF,
        .use_clustering         = DISABLE_CLUSTERING,
        .slave_alloc            = tcm_loop_slave_alloc,
        .slave_configure        = tcm_loop_slave_configure,
@@ -564,8 +559,7 @@ static char *tcm_loop_get_fabric_name(void)
 
 static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
 {
-       struct tcm_loop_tpg *tl_tpg =
-                       (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+       struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
        /*
         * tl_proto_id is set at tcm_loop_configfs.c:tcm_loop_make_scsi_hba()
@@ -592,8 +586,7 @@ static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
 
 static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
 {
-       struct tcm_loop_tpg *tl_tpg =
-               (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+       struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
        /*
         * Return the passed NAA identifier for the SAS Target Port
         */
@@ -602,8 +595,7 @@ static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
 
 static u16 tcm_loop_get_tag(struct se_portal_group *se_tpg)
 {
-       struct tcm_loop_tpg *tl_tpg =
-               (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+       struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
        /*
         * This Tag is used when forming SCSI Name identifier in EVPD=1 0x83
         * to represent the SCSI Target Port.
@@ -623,8 +615,7 @@ static u32 tcm_loop_get_pr_transport_id(
        int *format_code,
        unsigned char *buf)
 {
-       struct tcm_loop_tpg *tl_tpg =
-                       (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+       struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
 
        switch (tl_hba->tl_proto_id) {
@@ -653,8 +644,7 @@ static u32 tcm_loop_get_pr_transport_id_len(
        struct t10_pr_registration *pr_reg,
        int *format_code)
 {
-       struct tcm_loop_tpg *tl_tpg =
-                       (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+       struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
 
        switch (tl_hba->tl_proto_id) {
@@ -687,8 +677,7 @@ static char *tcm_loop_parse_pr_out_transport_id(
        u32 *out_tid_len,
        char **port_nexus_ptr)
 {
-       struct tcm_loop_tpg *tl_tpg =
-                       (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+       struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
 
        switch (tl_hba->tl_proto_id) {
index 6b76c7a22bb062fa692a89e89d903b747e67e157..15a036441471d3aca51624e903ea19f8b7ca8941 100644 (file)
@@ -1,16 +1,7 @@
 #define TCM_LOOP_VERSION               "v2.1-rc1"
 #define TL_WWN_ADDR_LEN                        256
 #define TL_TPGS_PER_HBA                        32
-/*
- * Defaults for struct scsi_host_template tcm_loop_driver_template
- *
- * We use large can_queue and cmd_per_lun here and let TCM enforce
- * the underlying se_device_t->queue_depth.
- */
-#define TL_SCSI_CAN_QUEUE              1024
-#define TL_SCSI_CMD_PER_LUN            1024
-#define TL_SCSI_MAX_SECTORS            1024
-#define TL_SCSI_SG_TABLESIZE           256
+
 /*
  * Used in tcm_loop_driver_probe() for struct Scsi_Host->max_cmd_len
  */
index 1dcbef499d6a09f2add951dee10c955f3541ccb8..01a2691dfb47c4f192f0b123a068339653e575f1 100644 (file)
 #include <scsi/scsi_cmnd.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
-#include "target_core_hba.h"
 #include "target_core_ua.h"
 
 static int core_alua_check_transition(int state, int *primary);
@@ -79,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
        list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
@@ -164,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
        buf[2] = ((rd_len >> 8) & 0xff);
        buf[3] = (rd_len & 0xff);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -195,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
                cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                return -EINVAL;
        }
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        /*
         * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
@@ -352,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
        }
 
 out:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
        return 0;
index 831468b3163d777f3eb5c982fc05819d37dea3e6..f3d71fa88a2825dab89a2847685ddfeb54eb57d2 100644 (file)
 #include <scsi/scsi.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+
+#include "target_core_internal.h"
 #include "target_core_ua.h"
-#include "target_core_cdb.h"
 
 static void
 target_fill_alua_data(struct se_port *port, unsigned char *buf)
@@ -82,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
                buf[0] = 0x3f; /* Not connected */
@@ -93,6 +94,18 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
        }
        buf[2] = dev->transport->get_device_rev(dev);
 
+       /*
+        * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2
+        *
+        * SPC4 says:
+        *   A RESPONSE DATA FORMAT field set to 2h indicates that the
+        *   standard INQUIRY data is in the format defined in this
+        *   standard. Response data format values less than 2h are
+        *   obsolete. Response data format values greater than 2h are
+        *   reserved.
+        */
+       buf[3] = 2;
+
        /*
         * Enable SCCS and TPGS fields for Emulated ALUA
         */
@@ -115,15 +128,13 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
                goto out;
        }
 
-       snprintf((unsigned char *)&buf[8], 8, "LIO-ORG");
-       snprintf((unsigned char *)&buf[16], 16, "%s",
-                &dev->se_sub_dev->t10_wwn.model[0]);
-       snprintf((unsigned char *)&buf[32], 4, "%s",
-                &dev->se_sub_dev->t10_wwn.revision[0]);
+       snprintf(&buf[8], 8, "LIO-ORG");
+       snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
+       snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
        buf[4] = 31; /* Set additional length to 31 */
 
 out:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        return 0;
 }
 
@@ -138,8 +149,7 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
                        SDF_EMULATED_VPD_UNIT_SERIAL) {
                u32 unit_serial_len;
 
-               unit_serial_len =
-                       strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
+               unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
                unit_serial_len++; /* For NULL Terminator */
 
                if (((len + 4) + unit_serial_len) > cmd->data_length) {
@@ -148,8 +158,8 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
                        buf[3] = (len & 0xff);
                        return 0;
                }
-               len += sprintf((unsigned char *)&buf[4], "%s",
-                       &dev->se_sub_dev->t10_wwn.unit_serial[0]);
+               len += sprintf(&buf[4], "%s",
+                       dev->se_sub_dev->t10_wwn.unit_serial);
                len++; /* Extra Byte for NULL Terminator */
                buf[3] = len;
        }
@@ -279,14 +289,13 @@ check_t10_vend_desc:
                        len += (prod_len + unit_serial_len);
                        goto check_port;
                }
-               id_len += sprintf((unsigned char *)&buf[off+12],
-                               "%s:%s", prod,
+               id_len += sprintf(&buf[off+12], "%s:%s", prod,
                                &dev->se_sub_dev->t10_wwn.unit_serial[0]);
        }
        buf[off] = 0x2; /* ASCII */
        buf[off+1] = 0x1; /* T10 Vendor ID */
        buf[off+2] = 0x0;
-       memcpy((unsigned char *)&buf[off+4], "LIO-ORG", 8);
+       memcpy(&buf[off+4], "LIO-ORG", 8);
        /* Extra Byte for NULL Terminator */
        id_len++;
        /* Identifier Length */
@@ -689,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task)
        int p, ret;
 
        if (!(cdb[1] & 0x1)) {
+               if (cdb[2]) {
+                       pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
+                              cdb[2]);
+                       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+                       return -EINVAL;
+               }
+
                ret = target_emulate_inquiry_std(cmd);
                goto out;
        }
@@ -707,7 +723,7 @@ int target_emulate_inquiry(struct se_task *task)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = dev->transport->get_device_type(dev);
 
@@ -720,11 +736,11 @@ int target_emulate_inquiry(struct se_task *task)
        }
 
        pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
-       cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
        ret = -EINVAL;
 
 out_unmap:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 out:
        if (!ret) {
                task->task_scsi_status = GOOD;
@@ -746,7 +762,7 @@ int target_emulate_readcapacity(struct se_task *task)
        else
                blocks = (u32)blocks_long;
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = (blocks >> 24) & 0xff;
        buf[1] = (blocks >> 16) & 0xff;
@@ -762,7 +778,7 @@ int target_emulate_readcapacity(struct se_task *task)
        if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                put_unaligned_be32(0xFFFFFFFF, &buf[0]);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -776,7 +792,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
        unsigned char *buf;
        unsigned long long blocks = dev->transport->get_blocks(dev);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = (blocks >> 56) & 0xff;
        buf[1] = (blocks >> 48) & 0xff;
@@ -797,7 +813,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
        if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                buf[14] = 0x80;
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -1010,9 +1026,9 @@ int target_emulate_modesense(struct se_task *task)
                        offset = cmd->data_length;
        }
 
-       rbuf = transport_kmap_first_data_page(cmd);
+       rbuf = transport_kmap_data_sg(cmd);
        memcpy(rbuf, buf, offset);
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
@@ -1034,7 +1050,7 @@ int target_emulate_request_sense(struct se_task *task)
                return -ENOSYS;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
                /*
@@ -1042,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task)
                 */
                buf[0] = 0x70;
                buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
-               /*
-                * Make sure request data length is enough for additional
-                * sense data.
-                */
-               if (cmd->data_length <= 18) {
+
+               if (cmd->data_length < 18) {
                        buf[7] = 0x00;
                        err = -EINVAL;
                        goto end;
@@ -1063,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task)
                 */
                buf[0] = 0x70;
                buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
-               /*
-                * Make sure request data length is enough for additional
-                * sense data.
-                */
-               if (cmd->data_length <= 18) {
+
+               if (cmd->data_length < 18) {
                        buf[7] = 0x00;
                        err = -EINVAL;
                        goto end;
@@ -1080,7 +1090,7 @@ int target_emulate_request_sense(struct se_task *task)
        }
 
 end:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        task->task_scsi_status = GOOD;
        transport_complete_task(task, 1);
        return 0;
@@ -1114,7 +1124,7 @@ int target_emulate_unmap(struct se_task *task)
        dl = get_unaligned_be16(&cdb[0]);
        bd_dl = get_unaligned_be16(&cdb[2]);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        ptr = &buf[offset];
        pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
@@ -1138,7 +1148,7 @@ int target_emulate_unmap(struct se_task *task)
        }
 
 err:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        if (!ret) {
                task->task_scsi_status = GOOD;
                transport_complete_task(task, 1);
diff --git a/drivers/target/target_core_cdb.h b/drivers/target/target_core_cdb.h
deleted file mode 100644 (file)
index ad6b1e3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef TARGET_CORE_CDB_H
-#define TARGET_CORE_CDB_H
-
-int target_emulate_inquiry(struct se_task *task);
-int target_emulate_readcapacity(struct se_task *task);
-int target_emulate_readcapacity_16(struct se_task *task);
-int target_emulate_modesense(struct se_task *task);
-int target_emulate_request_sense(struct se_task *task);
-int target_emulate_unmap(struct se_task *task);
-int target_emulate_write_same(struct se_task *task);
-int target_emulate_synchronize_cache(struct se_task *task);
-int target_emulate_noop(struct se_task *task);
-
-#endif /* TARGET_CORE_CDB_H */
index 93d4f6a1b7980c597c119ae7f7f0506d57846993..6e043eeb1db9c4449edfb4a4385184de1c0633fa 100644 (file)
 #include <linux/spinlock.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_fabric_configfs.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
-#include "target_core_hba.h"
 #include "target_core_pr.h"
 #include "target_core_rd.h"
-#include "target_core_stat.h"
 
 extern struct t10_alua_lu_gp *default_lu_gp;
 
@@ -1452,7 +1450,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                return -ENOMEM;
 
        orig = opts;
-       while ((ptr = strsep(&opts, ",")) != NULL) {
+       while ((ptr = strsep(&opts, ",\n")) != NULL) {
                if (!*ptr)
                        continue;
 
@@ -1631,7 +1629,7 @@ static struct config_item_type target_core_dev_pr_cit = {
 
 static ssize_t target_core_show_dev_info(void *p, char *page)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
        struct se_hba *hba = se_dev->se_dev_hba;
        struct se_subsystem_api *t = hba->transport;
        int bl = 0;
@@ -1659,7 +1657,7 @@ static ssize_t target_core_store_dev_control(
        const char *page,
        size_t count)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
        struct se_hba *hba = se_dev->se_dev_hba;
        struct se_subsystem_api *t = hba->transport;
 
@@ -1682,7 +1680,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_control = {
 
 static ssize_t target_core_show_dev_alias(void *p, char *page)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
 
        if (!(se_dev->su_dev_flags & SDF_USING_ALIAS))
                return 0;
@@ -1695,7 +1693,7 @@ static ssize_t target_core_store_dev_alias(
        const char *page,
        size_t count)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
        struct se_hba *hba = se_dev->se_dev_hba;
        ssize_t read_bytes;
 
@@ -1706,9 +1704,14 @@ static ssize_t target_core_store_dev_alias(
                return -EINVAL;
        }
 
-       se_dev->su_dev_flags |= SDF_USING_ALIAS;
        read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
                        "%s", page);
+       if (!read_bytes)
+               return -EINVAL;
+       if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
+               se_dev->se_dev_alias[read_bytes - 1] = '\0';
+
+       se_dev->su_dev_flags |= SDF_USING_ALIAS;
 
        pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
                config_item_name(&hba->hba_group.cg_item),
@@ -1728,7 +1731,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_alias = {
 
 static ssize_t target_core_show_dev_udev_path(void *p, char *page)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
 
        if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH))
                return 0;
@@ -1741,7 +1744,7 @@ static ssize_t target_core_store_dev_udev_path(
        const char *page,
        size_t count)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
        struct se_hba *hba = se_dev->se_dev_hba;
        ssize_t read_bytes;
 
@@ -1752,9 +1755,14 @@ static ssize_t target_core_store_dev_udev_path(
                return -EINVAL;
        }
 
-       se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
        read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
                        "%s", page);
+       if (!read_bytes)
+               return -EINVAL;
+       if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
+               se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
+
+       se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
 
        pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
                config_item_name(&hba->hba_group.cg_item),
@@ -1777,7 +1785,7 @@ static ssize_t target_core_store_dev_enable(
        const char *page,
        size_t count)
 {
-       struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *se_dev = p;
        struct se_device *dev;
        struct se_hba *hba = se_dev->se_dev_hba;
        struct se_subsystem_api *t = hba->transport;
@@ -1822,7 +1830,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_enable = {
 static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
 {
        struct se_device *dev;
-       struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *su_dev = p;
        struct config_item *lu_ci;
        struct t10_alua_lu_gp *lu_gp;
        struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -1860,7 +1868,7 @@ static ssize_t target_core_store_alua_lu_gp(
        size_t count)
 {
        struct se_device *dev;
-       struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p;
+       struct se_subsystem_dev *su_dev = p;
        struct se_hba *hba = su_dev->se_dev_hba;
        struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL;
        struct t10_alua_lu_gp_member *lu_gp_mem;
index 9b8639425472d8322aab749c6ae03fb56ea2a377..edbcabbf85f7339d1eddef7d618b26181540cd5a 100644 (file)
 #include <scsi/scsi_device.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
-#include "target_core_hba.h"
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
@@ -322,11 +320,12 @@ int core_free_device_list_for_node(
 void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
 {
        struct se_dev_entry *deve;
+       unsigned long flags;
 
-       spin_lock_irq(&se_nacl->device_list_lock);
+       spin_lock_irqsave(&se_nacl->device_list_lock, flags);
        deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
        deve->deve_cmds--;
-       spin_unlock_irq(&se_nacl->device_list_lock);
+       spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
 }
 
 void core_update_device_list_access(
@@ -658,7 +657,7 @@ int target_report_luns(struct se_task *se_task)
        unsigned char *buf;
        u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
 
-       buf = transport_kmap_first_data_page(se_cmd);
+       buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
 
        /*
         * If no struct se_session pointer is present, this struct se_cmd is
@@ -696,7 +695,7 @@ int target_report_luns(struct se_task *se_task)
         * See SPC3 r07, page 159.
         */
 done:
-       transport_kunmap_first_data_page(se_cmd);
+       transport_kunmap_data_sg(se_cmd);
        lun_count *= 8;
        buf[0] = ((lun_count >> 24) & 0xff);
        buf[1] = ((lun_count >> 16) & 0xff);
@@ -1134,8 +1133,6 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag)
  */
 int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 {
-       u32 orig_queue_depth = dev->queue_depth;
-
        if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
                pr_err("dev[%p]: Unable to change SE Device TCQ while"
                        " dev_export_obj: %d count exists\n", dev,
@@ -1169,11 +1166,6 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
        }
 
        dev->se_sub_dev->se_dev_attrib.queue_depth = dev->queue_depth = queue_depth;
-       if (queue_depth > orig_queue_depth)
-               atomic_add(queue_depth - orig_queue_depth, &dev->depth_left);
-       else if (queue_depth < orig_queue_depth)
-               atomic_sub(orig_queue_depth - queue_depth, &dev->depth_left);
-
        pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n",
                        dev, queue_depth);
        return 0;
@@ -1303,24 +1295,26 @@ struct se_lun *core_dev_add_lun(
 {
        struct se_lun *lun_p;
        u32 lun_access = 0;
+       int rc;
 
        if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
                pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
                        atomic_read(&dev->dev_access_obj.obj_access_count));
-               return NULL;
+               return ERR_PTR(-EACCES);
        }
 
        lun_p = core_tpg_pre_addlun(tpg, lun);
-       if ((IS_ERR(lun_p)) || !lun_p)
-               return NULL;
+       if (IS_ERR(lun_p))
+               return lun_p;
 
        if (dev->dev_flags & DF_READ_ONLY)
                lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
        else
                lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
 
-       if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
-               return NULL;
+       rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
+       if (rc < 0)
+               return ERR_PTR(rc);
 
        pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
                " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -1357,11 +1351,10 @@ int core_dev_del_lun(
        u32 unpacked_lun)
 {
        struct se_lun *lun;
-       int ret = 0;
 
-       lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
-       if (!lun)
-               return ret;
+       lun = core_tpg_pre_dellun(tpg, unpacked_lun);
+       if (IS_ERR(lun))
+               return PTR_ERR(lun);
 
        core_tpg_post_dellun(tpg, lun);
 
index 09b6f8729f918edbcd913770ef73c16485594839..9a2ce11e1a6e4025d7400dd313ccec64028308b3 100644 (file)
 #include <linux/configfs.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_fabric_configfs.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
-#include "target_core_hba.h"
 #include "target_core_pr.h"
-#include "target_core_stat.h"
 
 #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs)             \
 static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
@@ -770,9 +766,9 @@ static int target_fabric_port_link(
 
        lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
                                lun->unpacked_lun);
-       if (IS_ERR(lun_p) || !lun_p) {
+       if (IS_ERR(lun_p)) {
                pr_err("core_dev_add_lun() failed\n");
-               ret = -EINVAL;
+               ret = PTR_ERR(lun_p);
                goto out;
        }
 
index ec4249be617e348aaed580cfa027df1fc5174bbf..283a36e464e65ee5e55e9dded0037262a8203a9a 100644 (file)
 #include <scsi/scsi_cmnd.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_lib.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
-#include "target_core_hba.h"
+#include "target_core_internal.h"
 #include "target_core_pr.h"
 
 /*
@@ -402,7 +399,7 @@ char *iscsi_parse_pr_out_transport_id(
                add_len = ((buf[2] >> 8) & 0xff);
                add_len |= (buf[3] & 0xff);
 
-               tid_len = strlen((char *)&buf[4]);
+               tid_len = strlen(&buf[4]);
                tid_len += 4; /* Add four bytes for iSCSI Transport ID header */
                tid_len += 1; /* Add one byte for NULL terminator */
                padding = ((-tid_len) & 3);
@@ -423,11 +420,11 @@ char *iscsi_parse_pr_out_transport_id(
         * format.
         */
        if (format_code == 0x40) {
-               p = strstr((char *)&buf[4], ",i,0x");
+               p = strstr(&buf[4], ",i,0x");
                if (!p) {
                        pr_err("Unable to locate \",i,0x\" seperator"
                                " for Initiator port identifier: %s\n",
-                               (char *)&buf[4]);
+                               &buf[4]);
                        return NULL;
                }
                *p = '\0'; /* Terminate iSCSI Name */
index b4864fba4ef0d511758916a8debac60ee9f43674..7ed58e2df7914176cb8c9bd8e8bad187b5218131 100644 (file)
@@ -37,8 +37,7 @@
 #include <scsi/scsi_host.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
 
 #include "target_core_file.h"
 
@@ -86,7 +85,7 @@ static void fd_detach_hba(struct se_hba *hba)
 static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name)
 {
        struct fd_dev *fd_dev;
-       struct fd_host *fd_host = (struct fd_host *) hba->hba_ptr;
+       struct fd_host *fd_host = hba->hba_ptr;
 
        fd_dev = kzalloc(sizeof(struct fd_dev), GFP_KERNEL);
        if (!fd_dev) {
@@ -114,8 +113,8 @@ static struct se_device *fd_create_virtdevice(
        struct se_device *dev;
        struct se_dev_limits dev_limits;
        struct queue_limits *limits;
-       struct fd_dev *fd_dev = (struct fd_dev *) p;
-       struct fd_host *fd_host = (struct fd_host *) hba->hba_ptr;
+       struct fd_dev *fd_dev = p;
+       struct fd_host *fd_host = hba->hba_ptr;
        mm_segment_t old_fs;
        struct file *file;
        struct inode *inode = NULL;
@@ -240,7 +239,7 @@ fail:
  */
 static void fd_free_device(void *p)
 {
-       struct fd_dev *fd_dev = (struct fd_dev *) p;
+       struct fd_dev *fd_dev = p;
 
        if (fd_dev->fd_file) {
                filp_close(fd_dev->fd_file, NULL);
@@ -498,7 +497,7 @@ static ssize_t fd_set_configfs_dev_params(
 
        orig = opts;
 
-       while ((ptr = strsep(&opts, ",")) != NULL) {
+       while ((ptr = strsep(&opts, ",\n")) != NULL) {
                if (!*ptr)
                        continue;
 
@@ -559,7 +558,7 @@ out:
 
 static ssize_t fd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev)
 {
-       struct fd_dev *fd_dev = (struct fd_dev *) se_dev->se_dev_su_ptr;
+       struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
 
        if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {
                pr_err("Missing fd_dev_name=\n");
index c68019d6c406292335522d536760fb8bb5904629..3dd1bd4b6f71c712eb10770ebf976a9a7fa67cfc 100644 (file)
 #include <net/tcp.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 
-#include "target_core_hba.h"
+#include "target_core_internal.h"
 
 static LIST_HEAD(subsystem_list);
 static DEFINE_MUTEX(subsystem_mutex);
diff --git a/drivers/target/target_core_hba.h b/drivers/target/target_core_hba.h
deleted file mode 100644 (file)
index bb0fea5..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef TARGET_CORE_HBA_H
-#define TARGET_CORE_HBA_H
-
-extern struct se_hba *core_alloc_hba(const char *, u32, u32);
-extern int core_delete_hba(struct se_hba *);
-
-#endif /* TARGET_CORE_HBA_H */
index 4aa9922044382628fc21e12d8df3ab67840c23ae..8572eae62da7a20399216db03ea04fe9fa1dde3e 100644 (file)
@@ -42,8 +42,7 @@
 #include <scsi/scsi_host.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
 
 #include "target_core_iblock.h"
 
@@ -130,7 +129,7 @@ static struct se_device *iblock_create_virtdevice(
        /*
         * These settings need to be made tunable..
         */
-       ib_dev->ibd_bio_set = bioset_create(32, 64);
+       ib_dev->ibd_bio_set = bioset_create(32, 0);
        if (!ib_dev->ibd_bio_set) {
                pr_err("IBLOCK: Unable to create bioset()\n");
                return ERR_PTR(-ENOMEM);
@@ -182,7 +181,7 @@ static struct se_device *iblock_create_virtdevice(
                 */
                dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
                dev->se_sub_dev->se_dev_attrib.unmap_granularity =
-                               q->limits.discard_granularity;
+                               q->limits.discard_granularity >> 9;
                dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
                                q->limits.discard_alignment;
 
@@ -391,7 +390,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
 
        orig = opts;
 
-       while ((ptr = strsep(&opts, ",")) != NULL) {
+       while ((ptr = strsep(&opts, ",\n")) != NULL) {
                if (!*ptr)
                        continue;
 
@@ -465,7 +464,7 @@ static ssize_t iblock_show_configfs_dev_params(
        if (bd) {
                bl += sprintf(b + bl, "Major: %d Minor: %d  %s\n",
                        MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ?
-                       "" : (bd->bd_holder == (struct iblock_dev *)ibd) ?
+                       "" : (bd->bd_holder == ibd) ?
                        "CLAIMED: IBLOCK" : "CLAIMED: OS");
        } else {
                bl += sprintf(b + bl, "Major: 0 Minor: 0\n");
@@ -489,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
        struct iblock_req *ib_req = IBLOCK_REQ(task);
        struct bio *bio;
 
+       /*
+        * Only allocate as many vector entries as the bio code allows us to,
+        * we'll loop later on until we have handled the whole request.
+        */
+       if (sg_num > BIO_MAX_PAGES)
+               sg_num = BIO_MAX_PAGES;
+
        bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
        if (!bio) {
                pr_err("Unable to allocate memory for bio\n");
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
new file mode 100644 (file)
index 0000000..4500136
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef TARGET_CORE_INTERNAL_H
+#define TARGET_CORE_INTERNAL_H
+
+/* target_core_alua.c */
+extern struct t10_alua_lu_gp *default_lu_gp;
+
+/* target_core_cdb.c */
+int    target_emulate_inquiry(struct se_task *task);
+int    target_emulate_readcapacity(struct se_task *task);
+int    target_emulate_readcapacity_16(struct se_task *task);
+int    target_emulate_modesense(struct se_task *task);
+int    target_emulate_request_sense(struct se_task *task);
+int    target_emulate_unmap(struct se_task *task);
+int    target_emulate_write_same(struct se_task *task);
+int    target_emulate_synchronize_cache(struct se_task *task);
+int    target_emulate_noop(struct se_task *task);
+
+/* target_core_device.c */
+struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
+int    core_free_device_list_for_node(struct se_node_acl *,
+               struct se_portal_group *);
+void   core_dec_lacl_count(struct se_node_acl *, struct se_cmd *);
+void   core_update_device_list_access(u32, u32, struct se_node_acl *);
+int    core_update_device_list_for_node(struct se_lun *, struct se_lun_acl *,
+               u32, u32, struct se_node_acl *, struct se_portal_group *, int);
+void   core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
+int    core_dev_export(struct se_device *, struct se_portal_group *,
+               struct se_lun *);
+void   core_dev_unexport(struct se_device *, struct se_portal_group *,
+               struct se_lun *);
+int    target_report_luns(struct se_task *);
+void   se_release_device_for_hba(struct se_device *);
+void   se_release_vpd_for_dev(struct se_device *);
+int    se_free_virtual_device(struct se_device *, struct se_hba *);
+int    se_dev_check_online(struct se_device *);
+int    se_dev_check_shutdown(struct se_device *);
+void   se_dev_set_default_attribs(struct se_device *, struct se_dev_limits *);
+int    se_dev_set_task_timeout(struct se_device *, u32);
+int    se_dev_set_max_unmap_lba_count(struct se_device *, u32);
+int    se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
+int    se_dev_set_unmap_granularity(struct se_device *, u32);
+int    se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
+int    se_dev_set_emulate_dpo(struct se_device *, int);
+int    se_dev_set_emulate_fua_write(struct se_device *, int);
+int    se_dev_set_emulate_fua_read(struct se_device *, int);
+int    se_dev_set_emulate_write_cache(struct se_device *, int);
+int    se_dev_set_emulate_ua_intlck_ctrl(struct se_device *, int);
+int    se_dev_set_emulate_tas(struct se_device *, int);
+int    se_dev_set_emulate_tpu(struct se_device *, int);
+int    se_dev_set_emulate_tpws(struct se_device *, int);
+int    se_dev_set_enforce_pr_isids(struct se_device *, int);
+int    se_dev_set_is_nonrot(struct se_device *, int);
+int    se_dev_set_emulate_rest_reord(struct se_device *dev, int);
+int    se_dev_set_queue_depth(struct se_device *, u32);
+int    se_dev_set_max_sectors(struct se_device *, u32);
+int    se_dev_set_optimal_sectors(struct se_device *, u32);
+int    se_dev_set_block_size(struct se_device *, u32);
+struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_hba *,
+               struct se_device *, u32);
+int    core_dev_del_lun(struct se_portal_group *, u32);
+struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
+struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
+               u32, char *, int *);
+int    core_dev_add_initiator_node_lun_acl(struct se_portal_group *,
+               struct se_lun_acl *, u32, u32);
+int    core_dev_del_initiator_node_lun_acl(struct se_portal_group *,
+               struct se_lun *, struct se_lun_acl *);
+void   core_dev_free_initiator_node_lun_acl(struct se_portal_group *,
+               struct se_lun_acl *lacl);
+int    core_dev_setup_virtual_lun0(void);
+void   core_dev_release_virtual_lun0(void);
+
+/* target_core_hba.c */
+struct se_hba *core_alloc_hba(const char *, u32, u32);
+int    core_delete_hba(struct se_hba *);
+
+/* target_core_tmr.c */
+int    core_tmr_lun_reset(struct se_device *, struct se_tmr_req *,
+               struct list_head *, struct se_cmd *);
+
+/* target_core_tpg.c */
+extern struct se_device *g_lun0_dev;
+
+struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
+               const char *);
+struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
+               unsigned char *);
+void   core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *);
+void   core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
+struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
+int    core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
+               u32, void *);
+struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
+int    core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
+
+/* target_core_transport.c */
+extern struct kmem_cache *se_tmr_req_cache;
+
+int    init_se_kmem_caches(void);
+void   release_se_kmem_caches(void);
+u32    scsi_get_new_index(scsi_index_t);
+void   transport_subsystem_check_init(void);
+void   transport_cmd_finish_abort(struct se_cmd *, int);
+void   __transport_remove_task_from_execute_queue(struct se_task *,
+               struct se_device *);
+unsigned char *transport_dump_cmd_direction(struct se_cmd *);
+void   transport_dump_dev_state(struct se_device *, char *, int *);
+void   transport_dump_dev_info(struct se_device *, struct se_lun *,
+               unsigned long long, char *, int *);
+void   transport_dump_vpd_proto_id(struct t10_vpd *, unsigned char *, int);
+int    transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int);
+int    transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int);
+int    transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
+bool   target_stop_task(struct se_task *task, unsigned long *flags);
+int    transport_clear_lun_from_sessions(struct se_lun *);
+void   transport_send_task_abort(struct se_cmd *);
+
+/* target_core_stat.c */
+void   target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
+void   target_stat_setup_port_default_groups(struct se_lun *);
+void   target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
+
+#endif /* TARGET_CORE_INTERNAL_H */
index 95dee7074aeb5eb05f630fdded543e948ac206b3..b7c779389eea6820c34c5f9d6a6dafc98638c932 100644 (file)
 #include <asm/unaligned.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
-#include "target_core_hba.h"
+#include "target_core_internal.h"
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
@@ -481,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder(
        case READ_MEDIA_SERIAL_NUMBER:
        case REPORT_LUNS:
        case REQUEST_SENSE:
+       case PERSISTENT_RESERVE_IN:
                ret = 0; /*/ Allowed CDBs */
                break;
        default:
@@ -1537,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(
        tidh_new->dest_local_nexus = 1;
        list_add_tail(&tidh_new->dest_list, &tid_dest_list);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        /*
         * For a PERSISTENT RESERVE OUT specify initiator ports payload,
         * first extract TransportID Parameter Data Length, and make sure
@@ -1788,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(
 
        }
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        /*
         * Go ahead and create a registrations from tid_dest_list for the
@@ -1836,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port(
 
        return 0;
 out:
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        /*
         * For the failure case, release everything from tid_dest_list
         * including *dest_pr_reg and the configfs dependances..
@@ -2984,21 +2982,6 @@ static void core_scsi3_release_preempt_and_abort(
        }
 }
 
-int core_scsi3_check_cdb_abort_and_preempt(
-       struct list_head *preempt_and_abort_list,
-       struct se_cmd *cmd)
-{
-       struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-
-       list_for_each_entry_safe(pr_reg, pr_reg_tmp, preempt_and_abort_list,
-                               pr_reg_abort_list) {
-               if (pr_reg->pr_res_key == cmd->pr_res_key)
-                       return 0;
-       }
-
-       return 1;
-}
-
 static int core_scsi3_pro_preempt(
        struct se_cmd *cmd,
        int type,
@@ -3138,7 +3121,7 @@ static int core_scsi3_pro_preempt(
                        if (!calling_it_nexus)
                                core_scsi3_ua_allocate(pr_reg_nacl,
                                        pr_res_mapped_lun, 0x2A,
-                                       ASCQ_2AH_RESERVATIONS_PREEMPTED);
+                                       ASCQ_2AH_REGISTRATIONS_PREEMPTED);
                }
                spin_unlock(&pr_tmpl->registration_lock);
                /*
@@ -3251,7 +3234,7 @@ static int core_scsi3_pro_preempt(
                 *    additional sense code set to REGISTRATIONS PREEMPTED;
                 */
                core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
-                               ASCQ_2AH_RESERVATIONS_PREEMPTED);
+                               ASCQ_2AH_REGISTRATIONS_PREEMPTED);
        }
        spin_unlock(&pr_tmpl->registration_lock);
        /*
@@ -3428,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move(
         * will be moved to for the TransportID containing SCSI initiator WWN
         * information.
         */
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        rtpi = (buf[18] & 0xff) << 8;
        rtpi |= buf[19] & 0xff;
        tid_len = (buf[20] & 0xff) << 24;
        tid_len |= (buf[21] & 0xff) << 16;
        tid_len |= (buf[22] & 0xff) << 8;
        tid_len |= buf[23] & 0xff;
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        buf = NULL;
 
        if ((tid_len + 24) != cmd->data_length) {
@@ -3487,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move(
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        proto_ident = (buf[24] & 0x0f);
 #if 0
        pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
@@ -3521,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move(
                goto out;
        }
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        buf = NULL;
 
        pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s"
@@ -3786,13 +3769,13 @@ after_iport_check:
                                        " REGISTER_AND_MOVE\n");
        }
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        core_scsi3_put_pr_reg(dest_pr_reg);
        return 0;
 out:
        if (buf)
-               transport_kunmap_first_data_page(cmd);
+               transport_kunmap_data_sg(cmd);
        if (dest_se_deve)
                core_scsi3_lunacl_undepend_item(dest_se_deve);
        if (dest_node_acl)
@@ -3866,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
        scope = (cdb[2] & 0xf0);
        type = (cdb[2] & 0x0f);
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        /*
         * From PERSISTENT_RESERVE_OUT parameter list (payload)
         */
@@ -3884,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
                aptpl = (buf[17] & 0x01);
                unreg = (buf[17] & 0x02);
        }
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
        buf = NULL;
 
        /*
@@ -3984,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
        buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
        buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4018,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
        buf[6] = ((add_len >> 8) & 0xff);
        buf[7] = (add_len & 0xff);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
@@ -4044,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
        buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
        buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
        buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4103,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 
 err:
        spin_unlock(&se_dev->dev_reservation_lock);
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
@@ -4127,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = ((add_len << 8) & 0xff);
        buf[1] = (add_len & 0xff);
@@ -4159,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
        buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
        buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
@@ -4189,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                return -EINVAL;
        }
 
-       buf = transport_kmap_first_data_page(cmd);
+       buf = transport_kmap_data_sg(cmd);
 
        buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
        buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
@@ -4310,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
        buf[6] = ((add_len >> 8) & 0xff);
        buf[7] = (add_len & 0xff);
 
-       transport_kunmap_first_data_page(cmd);
+       transport_kunmap_data_sg(cmd);
 
        return 0;
 }
index b97f6940dd051a9e6c18e1842d0626af3a60ebbc..7a233feb7e992a30502ea4b43368214eb8f269ff 100644 (file)
@@ -60,8 +60,6 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
                                             struct se_node_acl *);
 extern void core_scsi3_free_all_registrations(struct se_device *);
 extern unsigned char *core_scsi3_pr_dump_type(int);
-extern int core_scsi3_check_cdb_abort_and_preempt(struct list_head *,
-                                                 struct se_cmd *);
 
 extern int target_scsi3_emulate_pr_in(struct se_task *task);
 extern int target_scsi3_emulate_pr_out(struct se_task *task);
index 8b15e56b038461169872d964055316c0318e7e31..8d4def30e9e80f788e20c6f120ff107be9d07be0 100644 (file)
@@ -44,8 +44,7 @@
 #include <scsi/scsi_tcq.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
 
 #include "target_core_pscsi.h"
 
@@ -105,7 +104,7 @@ static void pscsi_detach_hba(struct se_hba *hba)
 
 static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag)
 {
-       struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)hba->hba_ptr;
+       struct pscsi_hba_virt *phv = hba->hba_ptr;
        struct Scsi_Host *sh = phv->phv_lld_host;
        /*
         * Release the struct Scsi_Host
@@ -351,7 +350,6 @@ static struct se_device *pscsi_add_device_to_list(
         * scsi_device_put() and the pdv->pdv_sd cleared.
         */
        pdv->pdv_sd = sd;
-
        dev = transport_add_device_to_core_hba(hba, &pscsi_template,
                                se_dev, dev_flags, pdv,
                                &dev_limits, NULL, NULL);
@@ -406,7 +404,7 @@ static struct se_device *pscsi_create_type_disk(
        __releases(sh->host_lock)
 {
        struct se_device *dev;
-       struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
+       struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
        struct Scsi_Host *sh = sd->host;
        struct block_device *bd;
        u32 dev_flags = 0;
@@ -454,7 +452,7 @@ static struct se_device *pscsi_create_type_rom(
        __releases(sh->host_lock)
 {
        struct se_device *dev;
-       struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
+       struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
        struct Scsi_Host *sh = sd->host;
        u32 dev_flags = 0;
 
@@ -489,7 +487,7 @@ static struct se_device *pscsi_create_type_other(
        __releases(sh->host_lock)
 {
        struct se_device *dev;
-       struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
+       struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
        struct Scsi_Host *sh = sd->host;
        u32 dev_flags = 0;
 
@@ -510,10 +508,10 @@ static struct se_device *pscsi_create_virtdevice(
        struct se_subsystem_dev *se_dev,
        void *p)
 {
-       struct pscsi_dev_virt *pdv = (struct pscsi_dev_virt *)p;
+       struct pscsi_dev_virt *pdv = p;
        struct se_device *dev;
        struct scsi_device *sd;
-       struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)hba->hba_ptr;
+       struct pscsi_hba_virt *phv = hba->hba_ptr;
        struct Scsi_Host *sh = phv->phv_lld_host;
        int legacy_mode_enable = 0;
 
@@ -695,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task)
 
                if (task->task_se_cmd->se_deve->lun_flags &
                                TRANSPORT_LUNFLAGS_READ_ONLY) {
-                       unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd);
+                       unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
 
                        if (cdb[0] == MODE_SENSE_10) {
                                if (!(buf[3] & 0x80))
@@ -705,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task)
                                        buf[2] |= 0x80;
                        }
 
-                       transport_kunmap_first_data_page(task->task_se_cmd);
+                       transport_kunmap_data_sg(task->task_se_cmd);
                }
        }
 after_mode_sense:
@@ -818,7 +816,7 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
 
        orig = opts;
 
-       while ((ptr = strsep(&opts, ",")) != NULL) {
+       while ((ptr = strsep(&opts, ",\n")) != NULL) {
                if (!*ptr)
                        continue;
 
@@ -1144,7 +1142,7 @@ static unsigned char *pscsi_get_sense_buffer(struct se_task *task)
 {
        struct pscsi_plugin_task *pt = PSCSI_TASK(task);
 
-       return (unsigned char *)&pt->pscsi_sense[0];
+       return pt->pscsi_sense;
 }
 
 /*     pscsi_get_device_rev():
index 02e51faa2f4ea168f0a6139c8e303fc9fca81c28..8b68f7b82631ea8e0993da09228882820366067b 100644 (file)
@@ -37,9 +37,7 @@
 #include <scsi/scsi_host.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
 
 #include "target_core_rd.h"
 
@@ -474,7 +472,7 @@ static ssize_t rd_set_configfs_dev_params(
 
        orig = opts;
 
-       while ((ptr = strsep(&opts, ",")) != NULL) {
+       while ((ptr = strsep(&opts, ",\n")) != NULL) {
                if (!*ptr)
                        continue;
 
index 874152aed94af013de0bc5762f0959ea25281e05..f8c2d2cc34310041323d2614c3dfb09902a1f1db 100644 (file)
 #include <scsi/scsi_host.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
-#include "target_core_hba.h"
+#include "target_core_internal.h"
 
 #ifndef INITIAL_JIFFIES
 #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
@@ -1755,8 +1755,7 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
        /* scsiAttIntrPortName+scsiAttIntrPortIdentifier */
        memset(buf, 0, 64);
        if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL)
-               tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess,
-                               (unsigned char *)&buf[0], 64);
+               tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess, buf, 64);
 
        ret = snprintf(page, PAGE_SIZE, "%s+i+%s\n", nacl->initiatorname, buf);
        spin_unlock_irq(&nacl->nacl_sess_lock);
diff --git a/drivers/target/target_core_stat.h b/drivers/target/target_core_stat.h
deleted file mode 100644 (file)
index 86c252f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef TARGET_CORE_STAT_H
-#define TARGET_CORE_STAT_H
-
-extern void target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
-extern void target_stat_setup_port_default_groups(struct se_lun *);
-extern void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
-
-#endif   /*** TARGET_CORE_STAT_H ***/
index 684522805a1f370a99a5745c2fa3815a9c722912..dcb0618c9388a9e41341b7abef159d18a2eed259 100644 (file)
 #include <scsi/scsi_cmnd.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
 #include "target_core_pr.h"
 
@@ -101,6 +100,21 @@ static void core_tmr_handle_tas_abort(
        transport_cmd_finish_abort(cmd, 0);
 }
 
+static int target_check_cdb_and_preempt(struct list_head *list,
+               struct se_cmd *cmd)
+{
+       struct t10_pr_registration *reg;
+
+       if (!list)
+               return 0;
+       list_for_each_entry(reg, list, pr_reg_abort_list) {
+               if (reg->pr_res_key == cmd->pr_res_key)
+                       return 0;
+       }
+
+       return 1;
+}
+
 static void core_tmr_drain_tmr_list(
        struct se_device *dev,
        struct se_tmr_req *tmr,
@@ -132,9 +146,7 @@ static void core_tmr_drain_tmr_list(
                 * parameter (eg: for PROUT PREEMPT_AND_ABORT service action
                 * skip non regisration key matching TMRs.
                 */
-               if (preempt_and_abort_list &&
-                   (core_scsi3_check_cdb_abort_and_preempt(
-                                       preempt_and_abort_list, cmd) != 0))
+               if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
                        continue;
 
                spin_lock(&cmd->t_state_lock);
@@ -211,9 +223,7 @@ static void core_tmr_drain_task_list(
                 * For PREEMPT_AND_ABORT usage, only process commands
                 * with a matching reservation key.
                 */
-               if (preempt_and_abort_list &&
-                   (core_scsi3_check_cdb_abort_and_preempt(
-                                       preempt_and_abort_list, cmd) != 0))
+               if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
                        continue;
                /*
                 * Not aborting PROUT PREEMPT_AND_ABORT CDB..
@@ -222,7 +232,7 @@ static void core_tmr_drain_task_list(
                        continue;
 
                list_move_tail(&task->t_state_list, &drain_task_list);
-               atomic_set(&task->task_state_active, 0);
+               task->t_state_active = false;
                /*
                 * Remove from task execute list before processing drain_task_list
                 */
@@ -321,9 +331,7 @@ static void core_tmr_drain_cmd_list(
                 * For PREEMPT_AND_ABORT usage, only process commands
                 * with a matching reservation key.
                 */
-               if (preempt_and_abort_list &&
-                   (core_scsi3_check_cdb_abort_and_preempt(
-                                       preempt_and_abort_list, cmd) != 0))
+               if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
                        continue;
                /*
                 * Not aborting PROUT PREEMPT_AND_ABORT CDB..
index 8ddd133025b932a98a5968bfeb4f30b0d396a3d2..06336ecd872df683e8d2ac08e61d2898d03cfcb9 100644 (file)
 #include <scsi/scsi_cmnd.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 
-#include "target_core_hba.h"
-#include "target_core_stat.h"
+#include "target_core_internal.h"
 
 extern struct se_device *g_lun0_dev;
 
@@ -810,8 +807,7 @@ static void core_tpg_shutdown_lun(
 
 struct se_lun *core_tpg_pre_dellun(
        struct se_portal_group *tpg,
-       u32 unpacked_lun,
-       int *ret)
+       u32 unpacked_lun)
 {
        struct se_lun *lun;
 
index 0257658e2e3ea8a75642ae0dcabc77547ac2379b..58cea07b12fbcaea6ae4f3990ed02cf2deba1995 100644 (file)
 #include <scsi/scsi_tcq.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
-#include "target_core_cdb.h"
-#include "target_core_hba.h"
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
@@ -72,7 +68,7 @@ struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
 
 static int transport_generic_write_pending(struct se_cmd *);
 static int transport_processing_thread(void *param);
-static int __transport_execute_tasks(struct se_device *dev);
+static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *);
 static void transport_complete_task_attr(struct se_cmd *cmd);
 static void transport_handle_queue_full(struct se_cmd *cmd,
                struct se_device *dev);
@@ -212,14 +208,13 @@ u32 scsi_get_new_index(scsi_index_t type)
        return new_index;
 }
 
-void transport_init_queue_obj(struct se_queue_obj *qobj)
+static void transport_init_queue_obj(struct se_queue_obj *qobj)
 {
        atomic_set(&qobj->queue_cnt, 0);
        INIT_LIST_HEAD(&qobj->qobj_list);
        init_waitqueue_head(&qobj->thread_wq);
        spin_lock_init(&qobj->cmd_queue_lock);
 }
-EXPORT_SYMBOL(transport_init_queue_obj);
 
 void transport_subsystem_check_init(void)
 {
@@ -426,18 +421,18 @@ static void transport_all_task_dev_remove_state(struct se_cmd *cmd)
                if (task->task_flags & TF_ACTIVE)
                        continue;
 
-               if (!atomic_read(&task->task_state_active))
-                       continue;
-
                spin_lock_irqsave(&dev->execute_task_lock, flags);
-               list_del(&task->t_state_list);
-               pr_debug("Removed ITT: 0x%08x dev: %p task[%p]\n",
-                       cmd->se_tfo->get_task_tag(cmd), dev, task);
-               spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+               if (task->t_state_active) {
+                       pr_debug("Removed ITT: 0x%08x dev: %p task[%p]\n",
+                               cmd->se_tfo->get_task_tag(cmd), dev, task);
 
-               atomic_set(&task->task_state_active, 0);
-               atomic_dec(&cmd->t_task_cdbs_ex_left);
+                       list_del(&task->t_state_list);
+                       atomic_dec(&cmd->t_task_cdbs_ex_left);
+                       task->t_state_active = false;
+               }
+               spin_unlock_irqrestore(&dev->execute_task_lock, flags);
        }
+
 }
 
 /*     transport_cmd_check_stop():
@@ -696,12 +691,6 @@ void transport_complete_task(struct se_task *task, int success)
        struct se_cmd *cmd = task->task_se_cmd;
        struct se_device *dev = cmd->se_dev;
        unsigned long flags;
-#if 0
-       pr_debug("task: %p CDB: 0x%02x obj_ptr: %p\n", task,
-                       cmd->t_task_cdb[0], dev);
-#endif
-       if (dev)
-               atomic_inc(&dev->depth_left);
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        task->task_flags &= ~TF_ACTIVE;
@@ -714,7 +703,7 @@ void transport_complete_task(struct se_task *task, int success)
        if (dev && dev->transport->transport_complete) {
                if (dev->transport->transport_complete(task) != 0) {
                        cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
-                       task->task_sense = 1;
+                       task->task_flags |= TF_HAS_SENSE;
                        success = 1;
                }
        }
@@ -743,13 +732,7 @@ void transport_complete_task(struct se_task *task, int success)
        }
 
        if (cmd->t_tasks_failed) {
-               if (!task->task_error_status) {
-                       task->task_error_status =
-                               TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-                       cmd->scsi_sense_reason =
-                               TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-               }
-
+               cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                INIT_WORK(&cmd->work, target_complete_failure_work);
        } else {
                atomic_set(&cmd->t_transport_complete, 1);
@@ -824,7 +807,7 @@ static void __transport_add_task_to_execute_queue(
        head_of_queue = transport_add_task_check_sam_attr(task, task_prev, dev);
        atomic_inc(&dev->execute_tasks);
 
-       if (atomic_read(&task->task_state_active))
+       if (task->t_state_active)
                return;
        /*
         * Determine if this task needs to go to HEAD_OF_QUEUE for the
@@ -838,7 +821,7 @@ static void __transport_add_task_to_execute_queue(
        else
                list_add_tail(&task->t_state_list, &dev->state_task_list);
 
-       atomic_set(&task->task_state_active, 1);
+       task->t_state_active = true;
 
        pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
                task->task_se_cmd->se_tfo->get_task_tag(task->task_se_cmd),
@@ -853,29 +836,26 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        list_for_each_entry(task, &cmd->t_task_list, t_list) {
-               if (atomic_read(&task->task_state_active))
-                       continue;
-
                spin_lock(&dev->execute_task_lock);
-               list_add_tail(&task->t_state_list, &dev->state_task_list);
-               atomic_set(&task->task_state_active, 1);
-
-               pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
-                       task->task_se_cmd->se_tfo->get_task_tag(
-                       task->task_se_cmd), task, dev);
-
+               if (!task->t_state_active) {
+                       list_add_tail(&task->t_state_list,
+                                     &dev->state_task_list);
+                       task->t_state_active = true;
+
+                       pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
+                               task->task_se_cmd->se_tfo->get_task_tag(
+                               task->task_se_cmd), task, dev);
+               }
                spin_unlock(&dev->execute_task_lock);
        }
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
-static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
+static void __transport_add_tasks_from_cmd(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_task *task, *task_prev = NULL;
-       unsigned long flags;
 
-       spin_lock_irqsave(&dev->execute_task_lock, flags);
        list_for_each_entry(task, &cmd->t_task_list, t_list) {
                if (!list_empty(&task->t_execute_list))
                        continue;
@@ -886,6 +866,15 @@ static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
                __transport_add_task_to_execute_queue(task, task_prev, dev);
                task_prev = task;
        }
+}
+
+static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
+{
+       unsigned long flags;
+       struct se_device *dev = cmd->se_dev;
+
+       spin_lock_irqsave(&dev->execute_task_lock, flags);
+       __transport_add_tasks_from_cmd(cmd);
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
 
@@ -896,7 +885,7 @@ void __transport_remove_task_from_execute_queue(struct se_task *task,
        atomic_dec(&dev->execute_tasks);
 }
 
-void transport_remove_task_from_execute_queue(
+static void transport_remove_task_from_execute_queue(
        struct se_task *task,
        struct se_device *dev)
 {
@@ -983,9 +972,8 @@ void transport_dump_dev_state(
                break;
        }
 
-       *bl += sprintf(b + *bl, "  Execute/Left/Max Queue Depth: %d/%d/%d",
-               atomic_read(&dev->execute_tasks), atomic_read(&dev->depth_left),
-               dev->queue_depth);
+       *bl += sprintf(b + *bl, "  Execute/Max Queue Depth: %d/%d",
+               atomic_read(&dev->execute_tasks), dev->queue_depth);
        *bl += sprintf(b + *bl, "  SectorSize: %u  MaxSectors: %u\n",
                dev->se_sub_dev->se_dev_attrib.block_size, dev->se_sub_dev->se_dev_attrib.max_sectors);
        *bl += sprintf(b + *bl, "        ");
@@ -1267,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev)
 static void scsi_dump_inquiry(struct se_device *dev)
 {
        struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
+       char buf[17];
        int i, device_type;
        /*
         * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
         */
-       pr_debug("  Vendor: ");
        for (i = 0; i < 8; i++)
                if (wwn->vendor[i] >= 0x20)
-                       pr_debug("%c", wwn->vendor[i]);
+                       buf[i] = wwn->vendor[i];
                else
-                       pr_debug(" ");
+                       buf[i] = ' ';
+       buf[i] = '\0';
+       pr_debug("  Vendor: %s\n", buf);
 
-       pr_debug("  Model: ");
        for (i = 0; i < 16; i++)
                if (wwn->model[i] >= 0x20)
-                       pr_debug("%c", wwn->model[i]);
+                       buf[i] = wwn->model[i];
                else
-                       pr_debug(" ");
+                       buf[i] = ' ';
+       buf[i] = '\0';
+       pr_debug("  Model: %s\n", buf);
 
-       pr_debug("  Revision: ");
        for (i = 0; i < 4; i++)
                if (wwn->revision[i] >= 0x20)
-                       pr_debug("%c", wwn->revision[i]);
+                       buf[i] = wwn->revision[i];
                else
-                       pr_debug(" ");
-
-       pr_debug("\n");
+                       buf[i] = ' ';
+       buf[i] = '\0';
+       pr_debug("  Revision: %s\n", buf);
 
        device_type = dev->transport->get_device_type(dev);
        pr_debug("  Type:   %s ", scsi_device_type(device_type));
@@ -1340,9 +1330,6 @@ struct se_device *transport_add_device_to_core_hba(
        spin_lock_init(&dev->se_port_lock);
        spin_lock_init(&dev->se_tmr_lock);
        spin_lock_init(&dev->qf_cmd_lock);
-
-       dev->queue_depth        = dev_limits->queue_depth;
-       atomic_set(&dev->depth_left, dev->queue_depth);
        atomic_set(&dev->dev_ordered_id, 0);
 
        se_dev_set_default_attribs(dev, dev_limits);
@@ -1654,6 +1641,81 @@ int transport_handle_cdb_direct(
 }
 EXPORT_SYMBOL(transport_handle_cdb_direct);
 
+/**
+ * target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd
+ *
+ * @se_cmd: command descriptor to submit
+ * @se_sess: associated se_sess for endpoint
+ * @cdb: pointer to SCSI CDB
+ * @sense: pointer to SCSI sense buffer
+ * @unpacked_lun: unpacked LUN to reference for struct se_lun
+ * @data_length: fabric expected data transfer length
+ * @task_addr: SAM task attribute
+ * @data_dir: DMA data direction
+ * @flags: flags for command submission from target_sc_flags_tables
+ *
+ * This may only be called from process context, and also currently
+ * assumes internal allocation of fabric payload buffer by target-core.
+ **/
+void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+               unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
+               u32 data_length, int task_attr, int data_dir, int flags)
+{
+       struct se_portal_group *se_tpg;
+       int rc;
+
+       se_tpg = se_sess->se_tpg;
+       BUG_ON(!se_tpg);
+       BUG_ON(se_cmd->se_tfo || se_cmd->se_sess);
+       BUG_ON(in_interrupt());
+       /*
+        * Initialize se_cmd for target operation.  From this point
+        * exceptions are handled by sending exception status via
+        * target_core_fabric_ops->queue_status() callback
+        */
+       transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
+                               data_length, data_dir, task_attr, sense);
+       /*
+        * Obtain struct se_cmd->cmd_kref reference and add new cmd to
+        * se_sess->sess_cmd_list.  A second kref_get here is necessary
+        * for fabrics using TARGET_SCF_ACK_KREF that expect a second
+        * kref_put() to happen during fabric packet acknowledgement.
+        */
+       target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       /*
+        * Signal bidirectional data payloads to target-core
+        */
+       if (flags & TARGET_SCF_BIDI_OP)
+               se_cmd->se_cmd_flags |= SCF_BIDI;
+       /*
+        * Locate se_lun pointer and attach it to struct se_cmd
+        */
+       if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) {
+               transport_send_check_condition_and_sense(se_cmd,
+                               se_cmd->scsi_sense_reason, 0);
+               target_put_sess_cmd(se_sess, se_cmd);
+               return;
+       }
+       /*
+        * Sanitize CDBs via transport_generic_cmd_sequencer() and
+        * allocate the necessary tasks to complete the received CDB+data
+        */
+       rc = transport_generic_allocate_tasks(se_cmd, cdb);
+       if (rc != 0) {
+               transport_generic_request_failure(se_cmd);
+               return;
+       }
+       /*
+        * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
+        * for immediate execution of READs, otherwise wait for
+        * transport_generic_handle_data() to be called for WRITEs
+        * when fabric has filled the incoming buffer.
+        */
+       transport_handle_cdb_direct(se_cmd);
+       return;
+}
+EXPORT_SYMBOL(target_submit_cmd);
+
 /*
  * Used by fabric module frontends defining a TFO->new_cmd_map() caller
  * to  queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to
@@ -1920,18 +1982,6 @@ static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd)
        spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 }
 
-static inline int transport_tcq_window_closed(struct se_device *dev)
-{
-       if (dev->dev_tcq_window_closed++ <
-                       PYX_TRANSPORT_WINDOW_CLOSED_THRESHOLD) {
-               msleep(PYX_TRANSPORT_WINDOW_CLOSED_WAIT_SHORT);
-       } else
-               msleep(PYX_TRANSPORT_WINDOW_CLOSED_WAIT_LONG);
-
-       wake_up_interruptible(&dev->dev_queue_obj.thread_wq);
-       return 0;
-}
-
 /*
  * Called from Fabric Module context from transport_execute_tasks()
  *
@@ -2014,13 +2064,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd)
 static int transport_execute_tasks(struct se_cmd *cmd)
 {
        int add_tasks;
-
-       if (se_dev_check_online(cmd->se_dev) != 0) {
-               cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-               transport_generic_request_failure(cmd);
-               return 0;
-       }
-
+       struct se_device *se_dev = cmd->se_dev;
        /*
         * Call transport_cmd_check_stop() to see if a fabric exception
         * has occurred that prevents execution.
@@ -2034,19 +2078,16 @@ static int transport_execute_tasks(struct se_cmd *cmd)
                if (!add_tasks)
                        goto execute_tasks;
                /*
-                * This calls transport_add_tasks_from_cmd() to handle
-                * HEAD_OF_QUEUE ordering for SAM Task Attribute emulation
-                * (if enabled) in __transport_add_task_to_execute_queue() and
-                * transport_add_task_check_sam_attr().
+                * __transport_execute_tasks() -> __transport_add_tasks_from_cmd()
+                * adds associated se_tasks while holding dev->execute_task_lock
+                * before I/O dispath to avoid a double spinlock access.
                 */
-               transport_add_tasks_from_cmd(cmd);
+               __transport_execute_tasks(se_dev, cmd);
+               return 0;
        }
-       /*
-        * Kick the execution queue for the cmd associated struct se_device
-        * storage object.
-        */
+
 execute_tasks:
-       __transport_execute_tasks(cmd->se_dev);
+       __transport_execute_tasks(se_dev, NULL);
        return 0;
 }
 
@@ -2056,24 +2097,18 @@ execute_tasks:
  *
  * Called from transport_processing_thread()
  */
-static int __transport_execute_tasks(struct se_device *dev)
+static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *new_cmd)
 {
        int error;
        struct se_cmd *cmd = NULL;
        struct se_task *task = NULL;
        unsigned long flags;
 
-       /*
-        * Check if there is enough room in the device and HBA queue to send
-        * struct se_tasks to the selected transport.
-        */
 check_depth:
-       if (!atomic_read(&dev->depth_left))
-               return transport_tcq_window_closed(dev);
-
-       dev->dev_tcq_window_closed = 0;
-
        spin_lock_irq(&dev->execute_task_lock);
+       if (new_cmd != NULL)
+               __transport_add_tasks_from_cmd(new_cmd);
+
        if (list_empty(&dev->execute_task_list)) {
                spin_unlock_irq(&dev->execute_task_lock);
                return 0;
@@ -2083,10 +2118,7 @@ check_depth:
        __transport_remove_task_from_execute_queue(task, dev);
        spin_unlock_irq(&dev->execute_task_lock);
 
-       atomic_dec(&dev->depth_left);
-
        cmd = task->task_se_cmd;
-
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        task->task_flags |= (TF_ACTIVE | TF_SENT);
        atomic_inc(&cmd->t_task_cdbs_sent);
@@ -2107,10 +2139,10 @@ check_depth:
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                atomic_set(&cmd->t_transport_sent, 0);
                transport_stop_tasks_for_cmd(cmd);
-               atomic_inc(&dev->depth_left);
                transport_generic_request_failure(cmd);
        }
 
+       new_cmd = NULL;
        goto check_depth;
 
        return 0;
@@ -2351,7 +2383,7 @@ static int transport_get_sense_data(struct se_cmd *cmd)
 
        list_for_each_entry_safe(task, task_tmp,
                                &cmd->t_task_list, t_list) {
-               if (!task->task_sense)
+               if (!(task->task_flags & TF_HAS_SENSE))
                        continue;
 
                if (!dev->transport->get_sense_buffer) {
@@ -2665,7 +2697,7 @@ static int transport_generic_cmd_sequencer(
                        cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 
                        if (target_check_write_same_discard(&cdb[10], dev) < 0)
-                               goto out_invalid_cdb_field;
+                               goto out_unsupported_cdb;
                        if (!passthrough)
                                cmd->execute_task = target_emulate_write_same;
                        break;
@@ -2948,7 +2980,7 @@ static int transport_generic_cmd_sequencer(
                cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 
                if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_invalid_cdb_field;
+                       goto out_unsupported_cdb;
                if (!passthrough)
                        cmd->execute_task = target_emulate_write_same;
                break;
@@ -2971,7 +3003,7 @@ static int transport_generic_cmd_sequencer(
                 * of byte 1 bit 3 UNMAP instead of original reserved field
                 */
                if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_invalid_cdb_field;
+                       goto out_unsupported_cdb;
                if (!passthrough)
                        cmd->execute_task = target_emulate_write_same;
                break;
@@ -3053,11 +3085,6 @@ static int transport_generic_cmd_sequencer(
             (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
                goto out_unsupported_cdb;
 
-       /* Let's limit control cdbs to a page, for simplicity's sake. */
-       if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
-           size > PAGE_SIZE)
-               goto out_invalid_cdb_field;
-
        transport_set_supported_SAM_opcode(cmd);
        return ret;
 
@@ -3345,6 +3372,32 @@ static inline void transport_free_pages(struct se_cmd *cmd)
        cmd->t_bidi_data_nents = 0;
 }
 
+/**
+ * transport_release_cmd - free a command
+ * @cmd:       command to free
+ *
+ * This routine unconditionally frees a command, and reference counting
+ * or list removal must be done in the caller.
+ */
+static void transport_release_cmd(struct se_cmd *cmd)
+{
+       BUG_ON(!cmd->se_tfo);
+
+       if (cmd->se_tmr_req)
+               core_tmr_release_req(cmd->se_tmr_req);
+       if (cmd->t_task_cdb != cmd->__t_task_cdb)
+               kfree(cmd->t_task_cdb);
+       /*
+        * If this cmd has been setup with target_get_sess_cmd(), drop
+        * the kref and call ->release_cmd() in kref callback.
+        */
+        if (cmd->check_release != 0) {
+               target_put_sess_cmd(cmd->se_sess, cmd);
+               return;
+       }
+       cmd->se_tfo->release_cmd(cmd);
+}
+
 /**
  * transport_put_cmd - release a reference to a command
  * @cmd:       command to release
@@ -3435,9 +3488,11 @@ int transport_generic_map_mem_to_cmd(
 }
 EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
 
-void *transport_kmap_first_data_page(struct se_cmd *cmd)
+void *transport_kmap_data_sg(struct se_cmd *cmd)
 {
        struct scatterlist *sg = cmd->t_data_sg;
+       struct page **pages;
+       int i;
 
        BUG_ON(!sg);
        /*
@@ -3445,15 +3500,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd)
         * tcm_loop who may be using a contig buffer from the SCSI midlayer for
         * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()
         */
-       return kmap(sg_page(sg)) + sg->offset;
+       if (!cmd->t_data_nents)
+               return NULL;
+       else if (cmd->t_data_nents == 1)
+               return kmap(sg_page(sg)) + sg->offset;
+
+       /* >1 page. use vmap */
+       pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
+       if (!pages)
+               return NULL;
+
+       /* convert sg[] to pages[] */
+       for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
+               pages[i] = sg_page(sg);
+       }
+
+       cmd->t_data_vmap = vmap(pages, cmd->t_data_nents,  VM_MAP, PAGE_KERNEL);
+       kfree(pages);
+       if (!cmd->t_data_vmap)
+               return NULL;
+
+       return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
 }
-EXPORT_SYMBOL(transport_kmap_first_data_page);
+EXPORT_SYMBOL(transport_kmap_data_sg);
 
-void transport_kunmap_first_data_page(struct se_cmd *cmd)
+void transport_kunmap_data_sg(struct se_cmd *cmd)
 {
-       kunmap(sg_page(cmd->t_data_sg));
+       if (!cmd->t_data_nents)
+               return;
+       else if (cmd->t_data_nents == 1)
+               kunmap(sg_page(cmd->t_data_sg));
+
+       vunmap(cmd->t_data_vmap);
+       cmd->t_data_vmap = NULL;
 }
-EXPORT_SYMBOL(transport_kunmap_first_data_page);
+EXPORT_SYMBOL(transport_kunmap_data_sg);
 
 static int
 transport_generic_get_mem(struct se_cmd *cmd)
@@ -3461,6 +3542,7 @@ transport_generic_get_mem(struct se_cmd *cmd)
        u32 length = cmd->data_length;
        unsigned int nents;
        struct page *page;
+       gfp_t zero_flag;
        int i = 0;
 
        nents = DIV_ROUND_UP(length, PAGE_SIZE);
@@ -3471,9 +3553,11 @@ transport_generic_get_mem(struct se_cmd *cmd)
        cmd->t_data_nents = nents;
        sg_init_table(cmd->t_data_sg, nents);
 
+       zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO;
+
        while (length) {
                u32 page_len = min_t(u32, length, PAGE_SIZE);
-               page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               page = alloc_page(GFP_KERNEL | zero_flag);
                if (!page)
                        goto out;
 
@@ -3701,6 +3785,11 @@ transport_allocate_control_task(struct se_cmd *cmd)
        struct se_task *task;
        unsigned long flags;
 
+       /* Workaround for handling zero-length control CDBs */
+       if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
+           !cmd->data_length)
+               return 0;
+
        task = transport_generic_get_task(cmd, cmd->data_direction);
        if (!task)
                return -ENOMEM;
@@ -3772,6 +3861,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
        else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
                cmd->t_state = TRANSPORT_COMPLETE;
                atomic_set(&cmd->t_transport_active, 1);
+
+               if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
+                       u8 ua_asc = 0, ua_ascq = 0;
+
+                       core_scsi3_ua_clear_for_request_sense(cmd,
+                                       &ua_asc, &ua_ascq);
+               }
+
                INIT_WORK(&cmd->work, target_complete_ok_work);
                queue_work(target_completion_wq, &cmd->work);
                return 0;
@@ -3870,33 +3967,6 @@ queue_full:
        return 0;
 }
 
-/**
- * transport_release_cmd - free a command
- * @cmd:       command to free
- *
- * This routine unconditionally frees a command, and reference counting
- * or list removal must be done in the caller.
- */
-void transport_release_cmd(struct se_cmd *cmd)
-{
-       BUG_ON(!cmd->se_tfo);
-
-       if (cmd->se_tmr_req)
-               core_tmr_release_req(cmd->se_tmr_req);
-       if (cmd->t_task_cdb != cmd->__t_task_cdb)
-               kfree(cmd->t_task_cdb);
-       /*
-        * Check if target_wait_for_sess_cmds() is expecting to
-        * release se_cmd directly here..
-        */
-       if (cmd->check_release != 0 && cmd->se_tfo->check_release_cmd)
-               if (cmd->se_tfo->check_release_cmd(cmd) != 0)
-                       return;
-
-       cmd->se_tfo->release_cmd(cmd);
-}
-EXPORT_SYMBOL(transport_release_cmd);
-
 void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
 {
        if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
@@ -3923,11 +3993,22 @@ EXPORT_SYMBOL(transport_generic_free_cmd);
 /* target_get_sess_cmd - Add command to active ->sess_cmd_list
  * @se_sess:   session to reference
  * @se_cmd:    command descriptor to add
+ * @ack_kref:  Signal that fabric will perform an ack target_put_sess_cmd()
  */
-void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
+void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
+                       bool ack_kref)
 {
        unsigned long flags;
 
+       kref_init(&se_cmd->cmd_kref);
+       /*
+        * Add a second kref if the fabric caller is expecting to handle
+        * fabric acknowledgement that requires two target_put_sess_cmd()
+        * invocations before se_cmd descriptor release.
+        */
+       if (ack_kref == true)
+               kref_get(&se_cmd->cmd_kref);
+
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
        se_cmd->check_release = 1;
@@ -3935,30 +4016,36 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
 }
 EXPORT_SYMBOL(target_get_sess_cmd);
 
-/* target_put_sess_cmd - Check for active I/O shutdown or list delete
- * @se_sess:   session to reference
- * @se_cmd:    command descriptor to drop
- */
-int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
+static void target_release_cmd_kref(struct kref *kref)
 {
+       struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
+       struct se_session *se_sess = se_cmd->se_sess;
        unsigned long flags;
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        if (list_empty(&se_cmd->se_cmd_list)) {
                spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
                WARN_ON(1);
-               return 0;
+               return;
        }
-
        if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
                spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
                complete(&se_cmd->cmd_wait_comp);
-               return 1;
+               return;
        }
        list_del(&se_cmd->se_cmd_list);
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 
-       return 0;
+       se_cmd->se_tfo->release_cmd(se_cmd);
+}
+
+/* target_put_sess_cmd - Check for active I/O shutdown via kref_put
+ * @se_sess:   session to reference
+ * @se_cmd:    command descriptor to drop
+ */
+int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
+{
+       return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
 }
 EXPORT_SYMBOL(target_put_sess_cmd);
 
@@ -4174,7 +4261,7 @@ check_cond:
 
 static int transport_clear_lun_thread(void *p)
 {
-       struct se_lun *lun = (struct se_lun *)p;
+       struct se_lun *lun = p;
 
        __transport_clear_lun_from_sessions(lun);
        complete(&lun->lun_shutdown_comp);
@@ -4353,6 +4440,7 @@ int transport_send_check_condition_and_sense(
        case TCM_NON_EXISTENT_LUN:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT NOT SUPPORTED */
@@ -4362,6 +4450,7 @@ int transport_send_check_condition_and_sense(
        case TCM_SECTOR_COUNT_TOO_MANY:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID COMMAND OPERATION CODE */
@@ -4370,6 +4459,7 @@ int transport_send_check_condition_and_sense(
        case TCM_UNKNOWN_MODE_PAGE:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
@@ -4378,6 +4468,7 @@ int transport_send_check_condition_and_sense(
        case TCM_CHECK_CONDITION_ABORT_CMD:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* BUS DEVICE RESET FUNCTION OCCURRED */
@@ -4387,6 +4478,7 @@ int transport_send_check_condition_and_sense(
        case TCM_INCORRECT_AMOUNT_OF_DATA:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* WRITE ERROR */
@@ -4397,22 +4489,25 @@ int transport_send_check_condition_and_sense(
        case TCM_INVALID_CDB_FIELD:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
-               /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
                break;
        case TCM_INVALID_PARAMETER_LIST:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
-               /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN PARAMETER LIST */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
                break;
        case TCM_UNEXPECTED_UNSOLICITED_DATA:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* WRITE ERROR */
@@ -4423,6 +4518,7 @@ int transport_send_check_condition_and_sense(
        case TCM_SERVICE_CRC_ERROR:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* PROTOCOL SERVICE CRC ERROR */
@@ -4433,6 +4529,7 @@ int transport_send_check_condition_and_sense(
        case TCM_SNACK_REJECTED:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* READ ERROR */
@@ -4443,6 +4540,7 @@ int transport_send_check_condition_and_sense(
        case TCM_WRITE_PROTECTED:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* DATA PROTECT */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
                /* WRITE PROTECTED */
@@ -4451,6 +4549,7 @@ int transport_send_check_condition_and_sense(
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* UNIT ATTENTION */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
                core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
@@ -4460,6 +4559,7 @@ int transport_send_check_condition_and_sense(
        case TCM_CHECK_CONDITION_NOT_READY:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* Not Ready */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = NOT_READY;
                transport_get_sense_codes(cmd, &asc, &ascq);
@@ -4470,6 +4570,7 @@ int transport_send_check_condition_and_sense(
        default:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
                buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT COMMUNICATION FAILURE */
@@ -4545,11 +4646,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
        cmd->se_tfo->queue_status(cmd);
 }
 
-/*     transport_generic_do_tmr():
- *
- *
- */
-int transport_generic_do_tmr(struct se_cmd *cmd)
+static int transport_generic_do_tmr(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_tmr_req *tmr = cmd->se_tmr_req;
@@ -4597,7 +4694,7 @@ static int transport_processing_thread(void *param)
 {
        int ret;
        struct se_cmd *cmd;
-       struct se_device *dev = (struct se_device *) param;
+       struct se_device *dev = param;
 
        while (!kthread_should_stop()) {
                ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq,
@@ -4607,8 +4704,6 @@ static int transport_processing_thread(void *param)
                        goto out;
 
 get_cmd:
-               __transport_execute_tasks(dev);
-
                cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj);
                if (!cmd)
                        continue;
index 50a480db7a66df3d619e103060ca6c1be301f9b4..3e12f6bcfa10ba6d502aab352a6ea474839a1dd0 100644 (file)
 #include <scsi/scsi_cmnd.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
+#include "target_core_internal.h"
 #include "target_core_alua.h"
-#include "target_core_hba.h"
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
index 71fc9cea5dc9ba120b725a4e0f6bf94c879d1340..9e7e26c74c7944e4b20d93eaaf20f7490068df57 100644 (file)
 #include <scsi/fc_encode.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_tmr.h>
 #include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
@@ -367,6 +363,11 @@ static void ft_send_tm(struct ft_cmd *cmd)
        struct ft_sess *sess;
        u8 tm_func;
 
+       transport_init_se_cmd(&cmd->se_cmd, &ft_configfs->tf_ops,
+                       cmd->sess->se_sess, 0, DMA_NONE, 0,
+                       &cmd->ft_sense_buffer[0]);
+       target_get_sess_cmd(cmd->sess->se_sess, &cmd->se_cmd, false);
+
        fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
 
        switch (fcp->fc_tm_flags) {
@@ -420,7 +421,6 @@ static void ft_send_tm(struct ft_cmd *cmd)
                        sess = cmd->sess;
                        transport_send_check_condition_and_sense(&cmd->se_cmd,
                                cmd->se_cmd.scsi_sense_reason, 0);
-                       transport_generic_free_cmd(&cmd->se_cmd, 0);
                        ft_sess_put(sess);
                        return;
                }
@@ -536,12 +536,10 @@ static void ft_send_work(struct work_struct *work)
 {
        struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
        struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
-       struct se_cmd *se_cmd;
        struct fcp_cmnd *fcp;
        int data_dir = 0;
        u32 data_len;
        int task_attr;
-       int ret;
 
        fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
        if (!fcp)
@@ -591,15 +589,6 @@ static void ft_send_work(struct work_struct *work)
                data_len = ntohl(fcp->fc_dl);
                cmd->cdb = fcp->fc_cdb;
        }
-
-       se_cmd = &cmd->se_cmd;
-       /*
-        * Initialize struct se_cmd descriptor from target_core_mod
-        * infrastructure
-        */
-       transport_init_se_cmd(se_cmd, &ft_configfs->tf_ops, cmd->sess->se_sess,
-                             data_len, data_dir, task_attr,
-                             &cmd->ft_sense_buffer[0]);
        /*
         * Check for FCP task management flags
         */
@@ -607,39 +596,16 @@ static void ft_send_work(struct work_struct *work)
                ft_send_tm(cmd);
                return;
        }
-
        fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
-
        cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
-       ret = transport_lookup_cmd_lun(&cmd->se_cmd, cmd->lun);
-       if (ret < 0) {
-               ft_dump_cmd(cmd, __func__);
-               transport_send_check_condition_and_sense(&cmd->se_cmd,
-                       cmd->se_cmd.scsi_sense_reason, 0);
-               return;
-       }
-
-       ret = transport_generic_allocate_tasks(se_cmd, cmd->cdb);
-
-       pr_debug("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
-       ft_dump_cmd(cmd, __func__);
-
-       if (ret == -ENOMEM) {
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       }
-       if (ret == -EINVAL) {
-               if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
-                       ft_queue_status(se_cmd);
-               else
-                       transport_send_check_condition_and_sense(se_cmd,
-                                       se_cmd->scsi_sense_reason, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       }
-       transport_handle_cdb_direct(se_cmd);
+       /*
+        * Use a single se_cmd->cmd_kref as we expect to release se_cmd
+        * directly from ft_check_stop_free callback in response path.
+        */
+       target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
+                               &cmd->ft_sense_buffer[0], cmd->lun, data_len,
+                               task_attr, data_dir, 0);
+       pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
        return;
 
 err:
index 9402b7387cac570d91ff6001a885daed3bbd8b6d..73852fbc857b4b5aee0622ee7b55fb5c0880291b 100644 (file)
 #include <scsi/libfc.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_fabric_configfs.h>
-#include <target/target_core_fabric_lib.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
index 1369b1cb103d7d1e0ad4053322e599713445e9b7..d8cabc21036d3ec1040168b9940ab013c55b4a0b 100644 (file)
 #include <scsi/fc_encode.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
index 326921385aff973c17ce4f8598ba791c0fa94fc2..4c0507cf808c08662609765b41488a35c461add7 100644 (file)
 #include <scsi/libfc.h>
 
 #include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
 
index dd9a5743fa991f3fb789d2e17d12563deaead0cd..220ce7e31cf50faa89fd35a46946111b523da0d5 100644 (file)
@@ -1304,7 +1304,7 @@ static struct genl_multicast_group thermal_event_mcgrp = {
        .name = THERMAL_GENL_MCAST_GROUP_NAME,
 };
 
-int generate_netlink_event(u32 orig, enum events event)
+int thermal_generate_netlink_event(u32 orig, enum events event)
 {
        struct sk_buff *skb;
        struct nlattr *attr;
@@ -1363,7 +1363,7 @@ int generate_netlink_event(u32 orig, enum events event)
 
        return result;
 }
-EXPORT_SYMBOL(generate_netlink_event);
+EXPORT_SYMBOL(thermal_generate_netlink_event);
 
 static int genetlink_init(void)
 {
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
deleted file mode 100644 (file)
index 9f50c4e..0000000
+++ /dev/null
@@ -1,3357 +0,0 @@
-/*
- *  Driver for 8250/16550-type serial ports
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2001 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * A note about mapbase / membase
- *
- *  mapbase is the physical address of the IO port.
- *  membase is an 'ioremapped' cookie.
- */
-
-#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/ratelimit.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/nmi.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "8250.h"
-
-#ifdef CONFIG_SPARC
-#include "suncore.h"
-#endif
-
-/*
- * Configuration:
- *   share_irqs - whether we pass IRQF_SHARED to request_irq().  This option
- *                is unsafe when used on edge-triggered interrupts.
- */
-static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
-
-static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
-
-static struct uart_driver serial8250_reg;
-
-static int serial_index(struct uart_port *port)
-{
-       return (serial8250_reg.minor - 64) + port->line;
-}
-
-static unsigned int skip_txen_test; /* force skip of txen test at init time */
-
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...)     printk(fmt)
-#else
-#define DEBUG_INTR(fmt...)     do { } while (0)
-#endif
-
-#define PASS_LIMIT     512
-
-#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)
-
-
-/*
- * We default to IRQ0 for the "no irq" hack.   Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define CONFIG_SERIAL_DETECT_IRQ 1
-#endif
-#ifdef CONFIG_SERIAL_8250_MANY_PORTS
-#define CONFIG_SERIAL_MANY_PORTS 1
-#endif
-
-/*
- * HUB6 is always on.  This will be removed once the header
- * files have been cleaned.
- */
-#define CONFIG_HUB6 1
-
-#include <asm/serial.h>
-/*
- * SERIAL_PORT_DFNS tells us about built-in ports that have no
- * standard enumeration mechanism.   Platforms that can find all
- * serial ports via mechanisms like ACPI or PCI need not supply it.
- */
-#ifndef SERIAL_PORT_DFNS
-#define SERIAL_PORT_DFNS
-#endif
-
-static const struct old_serial_port old_serial_port[] = {
-       SERIAL_PORT_DFNS /* defined in asm/serial.h */
-};
-
-#define UART_NR        CONFIG_SERIAL_8250_NR_UARTS
-
-#ifdef CONFIG_SERIAL_8250_RSA
-
-#define PORT_RSA_MAX 4
-static unsigned long probe_rsa[PORT_RSA_MAX];
-static unsigned int probe_rsa_count;
-#endif /* CONFIG_SERIAL_8250_RSA  */
-
-struct irq_info {
-       struct                  hlist_node node;
-       int                     irq;
-       spinlock_t              lock;   /* Protects list not the hash */
-       struct list_head        *head;
-};
-
-#define NR_IRQ_HASH            32      /* Can be adjusted later */
-static struct hlist_head irq_lists[NR_IRQ_HASH];
-static DEFINE_MUTEX(hash_mutex);       /* Used to walk the hash */
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial8250_config uart_config[] = {
-       [PORT_UNKNOWN] = {
-               .name           = "unknown",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_8250] = {
-               .name           = "8250",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16450] = {
-               .name           = "16450",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16550] = {
-               .name           = "16550",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16550A] = {
-               .name           = "16550A",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_CIRRUS] = {
-               .name           = "Cirrus",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16650] = {
-               .name           = "ST16650",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_16650V2] = {
-               .name           = "ST16650V2",
-               .fifo_size      = 32,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
-                                 UART_FCR_T_TRIG_00,
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_16750] = {
-               .name           = "TI16750",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
-                                 UART_FCR7_64BYTE,
-               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
-       },
-       [PORT_STARTECH] = {
-               .name           = "Startech",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16C950] = {
-               .name           = "16C950/954",
-               .fifo_size      = 128,
-               .tx_loadsz      = 128,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               /* UART_CAP_EFR breaks billionon CF bluetooth card. */
-               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP,
-       },
-       [PORT_16654] = {
-               .name           = "ST16654",
-               .fifo_size      = 64,
-               .tx_loadsz      = 32,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
-                                 UART_FCR_T_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_16850] = {
-               .name           = "XR16850",
-               .fifo_size      = 128,
-               .tx_loadsz      = 128,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_RSA] = {
-               .name           = "RSA",
-               .fifo_size      = 2048,
-               .tx_loadsz      = 2048,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_NS16550A] = {
-               .name           = "NS16550A",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_NATSEMI,
-       },
-       [PORT_XSCALE] = {
-               .name           = "XScale",
-               .fifo_size      = 32,
-               .tx_loadsz      = 32,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
-       },
-       [PORT_RM9000] = {
-               .name           = "RM9000",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_OCTEON] = {
-               .name           = "OCTEON",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_AR7] = {
-               .name           = "AR7",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-       [PORT_U6_16550A] = {
-               .name           = "U6_16550A",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-       [PORT_TEGRA] = {
-               .name           = "Tegra",
-               .fifo_size      = 32,
-               .tx_loadsz      = 8,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
-                                 UART_FCR_T_TRIG_01,
-               .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
-       },
-       [PORT_XR17D15X] = {
-               .name           = "XR17D15X",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
-       },
-};
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-
-/* Au1x00 UART hardware has a weird register layout */
-static const u8 au_io_in_map[] = {
-       [UART_RX]  = 0,
-       [UART_IER] = 2,
-       [UART_IIR] = 3,
-       [UART_LCR] = 5,
-       [UART_MCR] = 6,
-       [UART_LSR] = 7,
-       [UART_MSR] = 8,
-};
-
-static const u8 au_io_out_map[] = {
-       [UART_TX]  = 1,
-       [UART_IER] = 2,
-       [UART_FCR] = 4,
-       [UART_LCR] = 5,
-       [UART_MCR] = 6,
-};
-
-/* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
-{
-       if (p->iotype != UPIO_AU)
-               return offset;
-       return au_io_in_map[offset];
-}
-
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
-{
-       if (p->iotype != UPIO_AU)
-               return offset;
-       return au_io_out_map[offset];
-}
-
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-
-static const u8
-       regmap_in[8] = {
-               [UART_RX]       = 0x00,
-               [UART_IER]      = 0x0c,
-               [UART_IIR]      = 0x14,
-               [UART_LCR]      = 0x1c,
-               [UART_MCR]      = 0x20,
-               [UART_LSR]      = 0x24,
-               [UART_MSR]      = 0x28,
-               [UART_SCR]      = 0x2c
-       },
-       regmap_out[8] = {
-               [UART_TX]       = 0x04,
-               [UART_IER]      = 0x0c,
-               [UART_FCR]      = 0x18,
-               [UART_LCR]      = 0x1c,
-               [UART_MCR]      = 0x20,
-               [UART_LSR]      = 0x24,
-               [UART_MSR]      = 0x28,
-               [UART_SCR]      = 0x2c
-       };
-
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
-{
-       if (p->iotype != UPIO_RM9000)
-               return offset;
-       return regmap_in[offset];
-}
-
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
-{
-       if (p->iotype != UPIO_RM9000)
-               return offset;
-       return regmap_out[offset];
-}
-
-#else
-
-/* sane hardware needs no mapping */
-#define map_8250_in_reg(up, offset) (offset)
-#define map_8250_out_reg(up, offset) (offset)
-
-#endif
-
-static unsigned int hub6_serial_in(struct uart_port *p, int offset)
-{
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       outb(p->hub6 - 1 + offset, p->iobase);
-       return inb(p->iobase + 1);
-}
-
-static void hub6_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       outb(p->hub6 - 1 + offset, p->iobase);
-       outb(value, p->iobase + 1);
-}
-
-static unsigned int mem_serial_in(struct uart_port *p, int offset)
-{
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       return readb(p->membase + offset);
-}
-
-static void mem_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       writeb(value, p->membase + offset);
-}
-
-static void mem32_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       writel(value, p->membase + offset);
-}
-
-static unsigned int mem32_serial_in(struct uart_port *p, int offset)
-{
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       return readl(p->membase + offset);
-}
-
-static unsigned int au_serial_in(struct uart_port *p, int offset)
-{
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       return __raw_readl(p->membase + offset);
-}
-
-static void au_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       __raw_writel(value, p->membase + offset);
-}
-
-static unsigned int io_serial_in(struct uart_port *p, int offset)
-{
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       return inb(p->iobase + offset);
-}
-
-static void io_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       outb(value, p->iobase + offset);
-}
-
-static int serial8250_default_handle_irq(struct uart_port *port);
-
-static void set_io_from_upio(struct uart_port *p)
-{
-       struct uart_8250_port *up =
-               container_of(p, struct uart_8250_port, port);
-       switch (p->iotype) {
-       case UPIO_HUB6:
-               p->serial_in = hub6_serial_in;
-               p->serial_out = hub6_serial_out;
-               break;
-
-       case UPIO_MEM:
-               p->serial_in = mem_serial_in;
-               p->serial_out = mem_serial_out;
-               break;
-
-       case UPIO_RM9000:
-       case UPIO_MEM32:
-               p->serial_in = mem32_serial_in;
-               p->serial_out = mem32_serial_out;
-               break;
-
-       case UPIO_AU:
-               p->serial_in = au_serial_in;
-               p->serial_out = au_serial_out;
-               break;
-
-       default:
-               p->serial_in = io_serial_in;
-               p->serial_out = io_serial_out;
-               break;
-       }
-       /* Remember loaded iotype */
-       up->cur_iotype = p->iotype;
-       p->handle_irq = serial8250_default_handle_irq;
-}
-
-static void
-serial_out_sync(struct uart_8250_port *up, int offset, int value)
-{
-       struct uart_port *p = &up->port;
-       switch (p->iotype) {
-       case UPIO_MEM:
-       case UPIO_MEM32:
-       case UPIO_AU:
-               p->serial_out(p, offset, value);
-               p->serial_in(p, UART_LCR);      /* safe, no side-effects */
-               break;
-       default:
-               p->serial_out(p, offset, value);
-       }
-}
-
-#define serial_in(up, offset)          \
-       (up->port.serial_in(&(up)->port, (offset)))
-#define serial_out(up, offset, value)  \
-       (up->port.serial_out(&(up)->port, (offset), (value)))
-/*
- * We used to support using pause I/O for certain machines.  We
- * haven't supported this for a while, but just in case it's badly
- * needed for certain old 386 machines, I've left these #define's
- * in....
- */
-#define serial_inp(up, offset)         serial_in(up, offset)
-#define serial_outp(up, offset, value) serial_out(up, offset, value)
-
-/* Uart divisor latch read */
-static inline int _serial_dl_read(struct uart_8250_port *up)
-{
-       return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
-}
-
-/* Uart divisor latch write */
-static inline void _serial_dl_write(struct uart_8250_port *up, int value)
-{
-       serial_outp(up, UART_DLL, value & 0xff);
-       serial_outp(up, UART_DLM, value >> 8 & 0xff);
-}
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-/* Au1x00 haven't got a standard divisor latch */
-static int serial_dl_read(struct uart_8250_port *up)
-{
-       if (up->port.iotype == UPIO_AU)
-               return __raw_readl(up->port.membase + 0x28);
-       else
-               return _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
-       if (up->port.iotype == UPIO_AU)
-               __raw_writel(value, up->port.membase + 0x28);
-       else
-               _serial_dl_write(up, value);
-}
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-static int serial_dl_read(struct uart_8250_port *up)
-{
-       return  (up->port.iotype == UPIO_RM9000) ?
-               (((__raw_readl(up->port.membase + 0x10) << 8) |
-               (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
-               _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
-       if (up->port.iotype == UPIO_RM9000) {
-               __raw_writel(value, up->port.membase + 0x08);
-               __raw_writel(value >> 8, up->port.membase + 0x10);
-       } else {
-               _serial_dl_write(up, value);
-       }
-}
-#else
-#define serial_dl_read(up) _serial_dl_read(up)
-#define serial_dl_write(up, value) _serial_dl_write(up, value)
-#endif
-
-/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-{
-       serial_out(up, UART_SCR, offset);
-       serial_out(up, UART_ICR, value);
-}
-
-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-{
-       unsigned int value;
-
-       serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
-       serial_out(up, UART_SCR, offset);
-       value = serial_in(up, UART_ICR);
-       serial_icr_write(up, UART_ACR, up->acr);
-
-       return value;
-}
-
-/*
- * FIFO support.
- */
-static void serial8250_clear_fifos(struct uart_8250_port *p)
-{
-       if (p->capabilities & UART_CAP_FIFO) {
-               serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
-               serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
-                              UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-               serial_outp(p, UART_FCR, 0);
-       }
-}
-
-/*
- * IER sleep support.  UARTs which have EFRs need the "extended
- * capability" bit enabled.  Note that on XR16C850s, we need to
- * reset LCR to write to IER.
- */
-static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
-{
-       if (p->capabilities & UART_CAP_SLEEP) {
-               if (p->capabilities & UART_CAP_EFR) {
-                       serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
-                       serial_outp(p, UART_EFR, UART_EFR_ECB);
-                       serial_outp(p, UART_LCR, 0);
-               }
-               serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
-               if (p->capabilities & UART_CAP_EFR) {
-                       serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
-                       serial_outp(p, UART_EFR, 0);
-                       serial_outp(p, UART_LCR, 0);
-               }
-       }
-}
-
-#ifdef CONFIG_SERIAL_8250_RSA
-/*
- * Attempts to turn on the RSA FIFO.  Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __enable_rsa(struct uart_8250_port *up)
-{
-       unsigned char mode;
-       int result;
-
-       mode = serial_inp(up, UART_RSA_MSR);
-       result = mode & UART_RSA_MSR_FIFO;
-
-       if (!result) {
-               serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
-               mode = serial_inp(up, UART_RSA_MSR);
-               result = mode & UART_RSA_MSR_FIFO;
-       }
-
-       if (result)
-               up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
-       return result;
-}
-
-static void enable_rsa(struct uart_8250_port *up)
-{
-       if (up->port.type == PORT_RSA) {
-               if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
-                       spin_lock_irq(&up->port.lock);
-                       __enable_rsa(up);
-                       spin_unlock_irq(&up->port.lock);
-               }
-               if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
-                       serial_outp(up, UART_RSA_FRR, 0);
-       }
-}
-
-/*
- * Attempts to turn off the RSA FIFO.  Returns zero on failure.
- * It is unknown why interrupts were disabled in here.  However,
- * the caller is expected to preserve this behaviour by grabbing
- * the spinlock before calling this function.
- */
-static void disable_rsa(struct uart_8250_port *up)
-{
-       unsigned char mode;
-       int result;
-
-       if (up->port.type == PORT_RSA &&
-           up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
-               spin_lock_irq(&up->port.lock);
-
-               mode = serial_inp(up, UART_RSA_MSR);
-               result = !(mode & UART_RSA_MSR_FIFO);
-
-               if (!result) {
-                       serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
-                       mode = serial_inp(up, UART_RSA_MSR);
-                       result = !(mode & UART_RSA_MSR_FIFO);
-               }
-
-               if (result)
-                       up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
-               spin_unlock_irq(&up->port.lock);
-       }
-}
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-/*
- * This is a quickie test to see how big the FIFO is.
- * It doesn't work at all the time, more's the pity.
- */
-static int size_fifo(struct uart_8250_port *up)
-{
-       unsigned char old_fcr, old_mcr, old_lcr;
-       unsigned short old_dl;
-       int count;
-
-       old_lcr = serial_inp(up, UART_LCR);
-       serial_outp(up, UART_LCR, 0);
-       old_fcr = serial_inp(up, UART_FCR);
-       old_mcr = serial_inp(up, UART_MCR);
-       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                   UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-       serial_outp(up, UART_MCR, UART_MCR_LOOP);
-       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       old_dl = serial_dl_read(up);
-       serial_dl_write(up, 0x0001);
-       serial_outp(up, UART_LCR, 0x03);
-       for (count = 0; count < 256; count++)
-               serial_outp(up, UART_TX, count);
-       mdelay(20);/* FIXME - schedule_timeout */
-       for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
-            (count < 256); count++)
-               serial_inp(up, UART_RX);
-       serial_outp(up, UART_FCR, old_fcr);
-       serial_outp(up, UART_MCR, old_mcr);
-       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       serial_dl_write(up, old_dl);
-       serial_outp(up, UART_LCR, old_lcr);
-
-       return count;
-}
-
-/*
- * Read UART ID using the divisor method - set DLL and DLM to zero
- * and the revision will be in DLL and device type in DLM.  We
- * preserve the device state across this.
- */
-static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
-{
-       unsigned char old_dll, old_dlm, old_lcr;
-       unsigned int id;
-
-       old_lcr = serial_inp(p, UART_LCR);
-       serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
-
-       old_dll = serial_inp(p, UART_DLL);
-       old_dlm = serial_inp(p, UART_DLM);
-
-       serial_outp(p, UART_DLL, 0);
-       serial_outp(p, UART_DLM, 0);
-
-       id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
-
-       serial_outp(p, UART_DLL, old_dll);
-       serial_outp(p, UART_DLM, old_dlm);
-       serial_outp(p, UART_LCR, old_lcr);
-
-       return id;
-}
-
-/*
- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
- * When this function is called we know it is at least a StarTech
- * 16650 V2, but it might be one of several StarTech UARTs, or one of
- * its clones.  (We treat the broken original StarTech 16650 V1 as a
- * 16550, and why not?  Startech doesn't seem to even acknowledge its
- * existence.)
- *
- * What evil have men's minds wrought...
- */
-static void autoconfig_has_efr(struct uart_8250_port *up)
-{
-       unsigned int id1, id2, id3, rev;
-
-       /*
-        * Everything with an EFR has SLEEP
-        */
-       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-
-       /*
-        * First we check to see if it's an Oxford Semiconductor UART.
-        *
-        * If we have to do this here because some non-National
-        * Semiconductor clone chips lock up if you try writing to the
-        * LSR register (which serial_icr_read does)
-        */
-
-       /*
-        * Check for Oxford Semiconductor 16C950.
-        *
-        * EFR [4] must be set else this test fails.
-        *
-        * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
-        * claims that it's needed for 952 dual UART's (which are not
-        * recommended for new designs).
-        */
-       up->acr = 0;
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-       serial_out(up, UART_EFR, UART_EFR_ECB);
-       serial_out(up, UART_LCR, 0x00);
-       id1 = serial_icr_read(up, UART_ID1);
-       id2 = serial_icr_read(up, UART_ID2);
-       id3 = serial_icr_read(up, UART_ID3);
-       rev = serial_icr_read(up, UART_REV);
-
-       DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-
-       if (id1 == 0x16 && id2 == 0xC9 &&
-           (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
-               up->port.type = PORT_16C950;
-
-               /*
-                * Enable work around for the Oxford Semiconductor 952 rev B
-                * chip which causes it to seriously miscalculate baud rates
-                * when DLL is 0.
-                */
-               if (id3 == 0x52 && rev == 0x01)
-                       up->bugs |= UART_BUG_QUOT;
-               return;
-       }
-
-       /*
-        * We check for a XR16C850 by setting DLL and DLM to 0, and then
-        * reading back DLL and DLM.  The chip type depends on the DLM
-        * value read back:
-        *  0x10 - XR16C850 and the DLL contains the chip revision.
-        *  0x12 - XR16C2850.
-        *  0x14 - XR16C854.
-        */
-       id1 = autoconfig_read_divisor_id(up);
-       DEBUG_AUTOCONF("850id=%04x ", id1);
-
-       id2 = id1 >> 8;
-       if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
-               up->port.type = PORT_16850;
-               return;
-       }
-
-       /*
-        * It wasn't an XR16C850.
-        *
-        * We distinguish between the '654 and the '650 by counting
-        * how many bytes are in the FIFO.  I'm using this for now,
-        * since that's the technique that was sent to me in the
-        * serial driver update, but I'm not convinced this works.
-        * I've had problems doing this in the past.  -TYT
-        */
-       if (size_fifo(up) == 64)
-               up->port.type = PORT_16654;
-       else
-               up->port.type = PORT_16650V2;
-}
-
-/*
- * We detected a chip without a FIFO.  Only two fall into
- * this category - the original 8250 and the 16450.  The
- * 16450 has a scratch register (accessible with LCR=0)
- */
-static void autoconfig_8250(struct uart_8250_port *up)
-{
-       unsigned char scratch, status1, status2;
-
-       up->port.type = PORT_8250;
-
-       scratch = serial_in(up, UART_SCR);
-       serial_outp(up, UART_SCR, 0xa5);
-       status1 = serial_in(up, UART_SCR);
-       serial_outp(up, UART_SCR, 0x5a);
-       status2 = serial_in(up, UART_SCR);
-       serial_outp(up, UART_SCR, scratch);
-
-       if (status1 == 0xa5 && status2 == 0x5a)
-               up->port.type = PORT_16450;
-}
-
-static int broken_efr(struct uart_8250_port *up)
-{
-       /*
-        * Exar ST16C2550 "A2" devices incorrectly detect as
-        * having an EFR, and report an ID of 0x0201.  See
-        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html 
-        */
-       if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
-               return 1;
-
-       return 0;
-}
-
-static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
-{
-       unsigned char status;
-
-       status = serial_in(up, 0x04); /* EXCR2 */
-#define PRESL(x) ((x) & 0x30)
-       if (PRESL(status) == 0x10) {
-               /* already in high speed mode */
-               return 0;
-       } else {
-               status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-               status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
-               serial_outp(up, 0x04, status);
-       }
-       return 1;
-}
-
-/*
- * We know that the chip has FIFOs.  Does it have an EFR?  The
- * EFR is located in the same register position as the IIR and
- * we know the top two bits of the IIR are currently set.  The
- * EFR should contain zero.  Try to read the EFR.
- */
-static void autoconfig_16550a(struct uart_8250_port *up)
-{
-       unsigned char status1, status2;
-       unsigned int iersave;
-
-       up->port.type = PORT_16550A;
-       up->capabilities |= UART_CAP_FIFO;
-
-       /*
-        * Check for presence of the EFR when DLAB is set.
-        * Only ST16C650V1 UARTs pass this test.
-        */
-       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       if (serial_in(up, UART_EFR) == 0) {
-               serial_outp(up, UART_EFR, 0xA8);
-               if (serial_in(up, UART_EFR) != 0) {
-                       DEBUG_AUTOCONF("EFRv1 ");
-                       up->port.type = PORT_16650;
-                       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-               } else {
-                       DEBUG_AUTOCONF("Motorola 8xxx DUART ");
-               }
-               serial_outp(up, UART_EFR, 0);
-               return;
-       }
-
-       /*
-        * Maybe it requires 0xbf to be written to the LCR.
-        * (other ST16C650V2 UARTs, TI16C752A, etc)
-        */
-       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-       if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
-               DEBUG_AUTOCONF("EFRv2 ");
-               autoconfig_has_efr(up);
-               return;
-       }
-
-       /*
-        * Check for a National Semiconductor SuperIO chip.
-        * Attempt to switch to bank 2, read the value of the LOOP bit
-        * from EXCR1. Switch back to bank 0, change it in MCR. Then
-        * switch back to bank 2, read it from EXCR1 again and check
-        * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
-        */
-       serial_outp(up, UART_LCR, 0);
-       status1 = serial_in(up, UART_MCR);
-       serial_outp(up, UART_LCR, 0xE0);
-       status2 = serial_in(up, 0x02); /* EXCR1 */
-
-       if (!((status2 ^ status1) & UART_MCR_LOOP)) {
-               serial_outp(up, UART_LCR, 0);
-               serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
-               serial_outp(up, UART_LCR, 0xE0);
-               status2 = serial_in(up, 0x02); /* EXCR1 */
-               serial_outp(up, UART_LCR, 0);
-               serial_outp(up, UART_MCR, status1);
-
-               if ((status2 ^ status1) & UART_MCR_LOOP) {
-                       unsigned short quot;
-
-                       serial_outp(up, UART_LCR, 0xE0);
-
-                       quot = serial_dl_read(up);
-                       quot <<= 3;
-
-                       if (ns16550a_goto_highspeed(up))
-                               serial_dl_write(up, quot);
-
-                       serial_outp(up, UART_LCR, 0);
-
-                       up->port.uartclk = 921600*16;
-                       up->port.type = PORT_NS16550A;
-                       up->capabilities |= UART_NATSEMI;
-                       return;
-               }
-       }
-
-       /*
-        * No EFR.  Try to detect a TI16750, which only sets bit 5 of
-        * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
-        * Try setting it with and without DLAB set.  Cheap clones
-        * set bit 5 without DLAB set.
-        */
-       serial_outp(up, UART_LCR, 0);
-       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-       status1 = serial_in(up, UART_IIR) >> 5;
-       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-       status2 = serial_in(up, UART_IIR) >> 5;
-       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       serial_outp(up, UART_LCR, 0);
-
-       DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-
-       if (status1 == 6 && status2 == 7) {
-               up->port.type = PORT_16750;
-               up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
-               return;
-       }
-
-       /*
-        * Try writing and reading the UART_IER_UUE bit (b6).
-        * If it works, this is probably one of the Xscale platform's
-        * internal UARTs.
-        * We're going to explicitly set the UUE bit to 0 before
-        * trying to write and read a 1 just to make sure it's not
-        * already a 1 and maybe locked there before we even start start.
-        */
-       iersave = serial_in(up, UART_IER);
-       serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
-       if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
-               /*
-                * OK it's in a known zero state, try writing and reading
-                * without disturbing the current state of the other bits.
-                */
-               serial_outp(up, UART_IER, iersave | UART_IER_UUE);
-               if (serial_in(up, UART_IER) & UART_IER_UUE) {
-                       /*
-                        * It's an Xscale.
-                        * We'll leave the UART_IER_UUE bit set to 1 (enabled).
-                        */
-                       DEBUG_AUTOCONF("Xscale ");
-                       up->port.type = PORT_XSCALE;
-                       up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
-                       return;
-               }
-       } else {
-               /*
-                * If we got here we couldn't force the IER_UUE bit to 0.
-                * Log it and continue.
-                */
-               DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
-       }
-       serial_outp(up, UART_IER, iersave);
-
-       /*
-        * Exar uarts have EFR in a weird location
-        */
-       if (up->port.flags & UPF_EXAR_EFR) {
-               up->port.type = PORT_XR17D15X;
-               up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
-       }
-
-       /*
-        * We distinguish between 16550A and U6 16550A by counting
-        * how many bytes are in the FIFO.
-        */
-       if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
-               up->port.type = PORT_U6_16550A;
-               up->capabilities |= UART_CAP_AFE;
-       }
-}
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port.  It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A.  The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-{
-       unsigned char status1, scratch, scratch2, scratch3;
-       unsigned char save_lcr, save_mcr;
-       unsigned long flags;
-
-       if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
-               return;
-
-       DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
-                      serial_index(&up->port), up->port.iobase, up->port.membase);
-
-       /*
-        * We really do need global IRQs disabled here - we're going to
-        * be frobbing the chips IRQ enable register to see if it exists.
-        */
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       up->capabilities = 0;
-       up->bugs = 0;
-
-       if (!(up->port.flags & UPF_BUGGY_UART)) {
-               /*
-                * Do a simple existence test first; if we fail this,
-                * there's no point trying anything else.
-                *
-                * 0x80 is used as a nonsense port to prevent against
-                * false positives due to ISA bus float.  The
-                * assumption is that 0x80 is a non-existent port;
-                * which should be safe since include/asm/io.h also
-                * makes this assumption.
-                *
-                * Note: this is safe as long as MCR bit 4 is clear
-                * and the device is in "PC" mode.
-                */
-               scratch = serial_inp(up, UART_IER);
-               serial_outp(up, UART_IER, 0);
-#ifdef __i386__
-               outb(0xff, 0x080);
-#endif
-               /*
-                * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
-                * 16C754B) allow only to modify them if an EFR bit is set.
-                */
-               scratch2 = serial_inp(up, UART_IER) & 0x0f;
-               serial_outp(up, UART_IER, 0x0F);
-#ifdef __i386__
-               outb(0, 0x080);
-#endif
-               scratch3 = serial_inp(up, UART_IER) & 0x0f;
-               serial_outp(up, UART_IER, scratch);
-               if (scratch2 != 0 || scratch3 != 0x0F) {
-                       /*
-                        * We failed; there's nothing here
-                        */
-                       DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-                                      scratch2, scratch3);
-                       goto out;
-               }
-       }
-
-       save_mcr = serial_in(up, UART_MCR);
-       save_lcr = serial_in(up, UART_LCR);
-
-       /*
-        * Check to see if a UART is really there.  Certain broken
-        * internal modems based on the Rockwell chipset fail this
-        * test, because they apparently don't implement the loopback
-        * test mode.  So this test is skipped on the COM 1 through
-        * COM 4 ports.  This *should* be safe, since no board
-        * manufacturer would be stupid enough to design a board
-        * that conflicts with COM 1-4 --- we hope!
-        */
-       if (!(up->port.flags & UPF_SKIP_TEST)) {
-               serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
-               status1 = serial_inp(up, UART_MSR) & 0xF0;
-               serial_outp(up, UART_MCR, save_mcr);
-               if (status1 != 0x90) {
-                       DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-                                      status1);
-                       goto out;
-               }
-       }
-
-       /*
-        * We're pretty sure there's a port here.  Lets find out what
-        * type of port it is.  The IIR top two bits allows us to find
-        * out if it's 8250 or 16450, 16550, 16550A or later.  This
-        * determines what we test for next.
-        *
-        * We also initialise the EFR (if any) to zero for later.  The
-        * EFR occupies the same register location as the FCR and IIR.
-        */
-       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-       serial_outp(up, UART_EFR, 0);
-       serial_outp(up, UART_LCR, 0);
-
-       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       scratch = serial_in(up, UART_IIR) >> 6;
-
-       DEBUG_AUTOCONF("iir=%d ", scratch);
-
-       switch (scratch) {
-       case 0:
-               autoconfig_8250(up);
-               break;
-       case 1:
-               up->port.type = PORT_UNKNOWN;
-               break;
-       case 2:
-               up->port.type = PORT_16550;
-               break;
-       case 3:
-               autoconfig_16550a(up);
-               break;
-       }
-
-#ifdef CONFIG_SERIAL_8250_RSA
-       /*
-        * Only probe for RSA ports if we got the region.
-        */
-       if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
-               int i;
-
-               for (i = 0 ; i < probe_rsa_count; ++i) {
-                       if (probe_rsa[i] == up->port.iobase &&
-                           __enable_rsa(up)) {
-                               up->port.type = PORT_RSA;
-                               break;
-                       }
-               }
-       }
-#endif
-
-       serial_outp(up, UART_LCR, save_lcr);
-
-       if (up->capabilities != uart_config[up->port.type].flags) {
-               printk(KERN_WARNING
-                      "ttyS%d: detected caps %08x should be %08x\n",
-                      serial_index(&up->port), up->capabilities,
-                      uart_config[up->port.type].flags);
-       }
-
-       up->port.fifosize = uart_config[up->port.type].fifo_size;
-       up->capabilities = uart_config[up->port.type].flags;
-       up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
-
-       if (up->port.type == PORT_UNKNOWN)
-               goto out;
-
-       /*
-        * Reset the UART.
-        */
-#ifdef CONFIG_SERIAL_8250_RSA
-       if (up->port.type == PORT_RSA)
-               serial_outp(up, UART_RSA_FRR, 0);
-#endif
-       serial_outp(up, UART_MCR, save_mcr);
-       serial8250_clear_fifos(up);
-       serial_in(up, UART_RX);
-       if (up->capabilities & UART_CAP_UUE)
-               serial_outp(up, UART_IER, UART_IER_UUE);
-       else
-               serial_outp(up, UART_IER, 0);
-
- out:
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-}
-
-static void autoconfig_irq(struct uart_8250_port *up)
-{
-       unsigned char save_mcr, save_ier;
-       unsigned char save_ICP = 0;
-       unsigned int ICP = 0;
-       unsigned long irqs;
-       int irq;
-
-       if (up->port.flags & UPF_FOURPORT) {
-               ICP = (up->port.iobase & 0xfe0) | 0x1f;
-               save_ICP = inb_p(ICP);
-               outb_p(0x80, ICP);
-               (void) inb_p(ICP);
-       }
-
-       /* forget possible initially masked and pending IRQ */
-       probe_irq_off(probe_irq_on());
-       save_mcr = serial_inp(up, UART_MCR);
-       save_ier = serial_inp(up, UART_IER);
-       serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
-       irqs = probe_irq_on();
-       serial_outp(up, UART_MCR, 0);
-       udelay(10);
-       if (up->port.flags & UPF_FOURPORT) {
-               serial_outp(up, UART_MCR,
-                           UART_MCR_DTR | UART_MCR_RTS);
-       } else {
-               serial_outp(up, UART_MCR,
-                           UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-       }
-       serial_outp(up, UART_IER, 0x0f);        /* enable all intrs */
-       (void)serial_inp(up, UART_LSR);
-       (void)serial_inp(up, UART_RX);
-       (void)serial_inp(up, UART_IIR);
-       (void)serial_inp(up, UART_MSR);
-       serial_outp(up, UART_TX, 0xFF);
-       udelay(20);
-       irq = probe_irq_off(irqs);
-
-       serial_outp(up, UART_MCR, save_mcr);
-       serial_outp(up, UART_IER, save_ier);
-
-       if (up->port.flags & UPF_FOURPORT)
-               outb_p(save_ICP, ICP);
-
-       up->port.irq = (irq > 0) ? irq : 0;
-}
-
-static inline void __stop_tx(struct uart_8250_port *p)
-{
-       if (p->ier & UART_IER_THRI) {
-               p->ier &= ~UART_IER_THRI;
-               serial_out(p, UART_IER, p->ier);
-       }
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       __stop_tx(up);
-
-       /*
-        * We really want to stop the transmitter from sending.
-        */
-       if (up->port.type == PORT_16C950) {
-               up->acr |= UART_ACR_TXDIS;
-               serial_icr_write(up, UART_ACR, up->acr);
-       }
-}
-
-static void serial8250_start_tx(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       if (!(up->ier & UART_IER_THRI)) {
-               up->ier |= UART_IER_THRI;
-               serial_out(up, UART_IER, up->ier);
-
-               if (up->bugs & UART_BUG_TXEN) {
-                       unsigned char lsr;
-                       lsr = serial_in(up, UART_LSR);
-                       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-                       if ((up->port.type == PORT_RM9000) ?
-                               (lsr & UART_LSR_THRE) :
-                               (lsr & UART_LSR_TEMT))
-                               serial8250_tx_chars(up);
-               }
-       }
-
-       /*
-        * Re-enable the transmitter if we disabled it.
-        */
-       if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
-               up->acr &= ~UART_ACR_TXDIS;
-               serial_icr_write(up, UART_ACR, up->acr);
-       }
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       up->ier &= ~UART_IER_RLSI;
-       up->port.read_status_mask &= ~UART_LSR_DR;
-       serial_out(up, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       /* no MSR capabilities */
-       if (up->bugs & UART_BUG_NOMSR)
-               return;
-
-       up->ier |= UART_IER_MSI;
-       serial_out(up, UART_IER, up->ier);
-}
-
-/*
- * Clear the Tegra rx fifo after a break
- *
- * FIXME: This needs to become a port specific callback once we have a
- * framework for this
- */
-static void clear_rx_fifo(struct uart_8250_port *up)
-{
-       unsigned int status, tmout = 10000;
-       do {
-               status = serial_in(up, UART_LSR);
-               if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
-                       status = serial_in(up, UART_RX);
-               else
-                       break;
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       } while (1);
-}
-
-/*
- * serial8250_rx_chars: processes according to the passed in LSR
- * value, and returns the remaining LSR bits not handled
- * by this Rx routine.
- */
-unsigned char
-serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
-{
-       struct tty_struct *tty = up->port.state->port.tty;
-       unsigned char ch;
-       int max_count = 256;
-       char flag;
-
-       do {
-               if (likely(lsr & UART_LSR_DR))
-                       ch = serial_inp(up, UART_RX);
-               else
-                       /*
-                        * Intel 82571 has a Serial Over Lan device that will
-                        * set UART_LSR_BI without setting UART_LSR_DR when
-                        * it receives a break. To avoid reading from the
-                        * receive buffer without UART_LSR_DR bit set, we
-                        * just force the read character to be 0
-                        */
-                       ch = 0;
-
-               flag = TTY_NORMAL;
-               up->port.icount.rx++;
-
-               lsr |= up->lsr_saved_flags;
-               up->lsr_saved_flags = 0;
-
-               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
-                       /*
-                        * For statistics only
-                        */
-                       if (lsr & UART_LSR_BI) {
-                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);
-                               up->port.icount.brk++;
-                               /*
-                                * If tegra port then clear the rx fifo to
-                                * accept another break/character.
-                                */
-                               if (up->port.type == PORT_TEGRA)
-                                       clear_rx_fifo(up);
-
-                               /*
-                                * We do the SysRQ and SAK checking
-                                * here because otherwise the break
-                                * may get masked by ignore_status_mask
-                                * or read_status_mask.
-                                */
-                               if (uart_handle_break(&up->port))
-                                       goto ignore_char;
-                       } else if (lsr & UART_LSR_PE)
-                               up->port.icount.parity++;
-                       else if (lsr & UART_LSR_FE)
-                               up->port.icount.frame++;
-                       if (lsr & UART_LSR_OE)
-                               up->port.icount.overrun++;
-
-                       /*
-                        * Mask off conditions which should be ignored.
-                        */
-                       lsr &= up->port.read_status_mask;
-
-                       if (lsr & UART_LSR_BI) {
-                               DEBUG_INTR("handling break....");
-                               flag = TTY_BREAK;
-                       } else if (lsr & UART_LSR_PE)
-                               flag = TTY_PARITY;
-                       else if (lsr & UART_LSR_FE)
-                               flag = TTY_FRAME;
-               }
-               if (uart_handle_sysrq_char(&up->port, ch))
-                       goto ignore_char;
-
-               uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
-
-ignore_char:
-               lsr = serial_inp(up, UART_LSR);
-       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
-       spin_unlock(&up->port.lock);
-       tty_flip_buffer_push(tty);
-       spin_lock(&up->port.lock);
-       return lsr;
-}
-EXPORT_SYMBOL_GPL(serial8250_rx_chars);
-
-void serial8250_tx_chars(struct uart_8250_port *up)
-{
-       struct circ_buf *xmit = &up->port.state->xmit;
-       int count;
-
-       if (up->port.x_char) {
-               serial_outp(up, UART_TX, up->port.x_char);
-               up->port.icount.tx++;
-               up->port.x_char = 0;
-               return;
-       }
-       if (uart_tx_stopped(&up->port)) {
-               serial8250_stop_tx(&up->port);
-               return;
-       }
-       if (uart_circ_empty(xmit)) {
-               __stop_tx(up);
-               return;
-       }
-
-       count = up->tx_loadsz;
-       do {
-               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               up->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-
-       DEBUG_INTR("THRE...");
-
-       if (uart_circ_empty(xmit))
-               __stop_tx(up);
-}
-EXPORT_SYMBOL_GPL(serial8250_tx_chars);
-
-unsigned int serial8250_modem_status(struct uart_8250_port *up)
-{
-       unsigned int status = serial_in(up, UART_MSR);
-
-       status |= up->msr_saved_flags;
-       up->msr_saved_flags = 0;
-       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
-           up->port.state != NULL) {
-               if (status & UART_MSR_TERI)
-                       up->port.icount.rng++;
-               if (status & UART_MSR_DDSR)
-                       up->port.icount.dsr++;
-               if (status & UART_MSR_DDCD)
-                       uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-               if (status & UART_MSR_DCTS)
-                       uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-               wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-       }
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(serial8250_modem_status);
-
-/*
- * This handles the interrupt from one port.
- */
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
-{
-       unsigned char status;
-       unsigned long flags;
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       if (iir & UART_IIR_NO_INT)
-               return 0;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       status = serial_inp(up, UART_LSR);
-
-       DEBUG_INTR("status = %x...", status);
-
-       if (status & (UART_LSR_DR | UART_LSR_BI))
-               status = serial8250_rx_chars(up, status);
-       serial8250_modem_status(up);
-       if (status & UART_LSR_THRE)
-               serial8250_tx_chars(up);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       return 1;
-}
-EXPORT_SYMBOL_GPL(serial8250_handle_irq);
-
-static int serial8250_default_handle_irq(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned int iir = serial_in(up, UART_IIR);
-
-       return serial8250_handle_irq(port, iir);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts.  (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
-{
-       struct irq_info *i = dev_id;
-       struct list_head *l, *end = NULL;
-       int pass_counter = 0, handled = 0;
-
-       DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-
-       spin_lock(&i->lock);
-
-       l = i->head;
-       do {
-               struct uart_8250_port *up;
-               struct uart_port *port;
-               bool skip;
-
-               up = list_entry(l, struct uart_8250_port, list);
-               port = &up->port;
-               skip = pass_counter && up->port.flags & UPF_IIR_ONCE;
-
-               if (!skip && port->handle_irq(port)) {
-                       handled = 1;
-                       end = NULL;
-               } else if (end == NULL)
-                       end = l;
-
-               l = l->next;
-
-               if (l == i->head && pass_counter++ > PASS_LIMIT) {
-                       /* If we hit this, we're dead. */
-                       printk_ratelimited(KERN_ERR
-                               "serial8250: too much work for irq%d\n", irq);
-                       break;
-               }
-       } while (l != end);
-
-       spin_unlock(&i->lock);
-
-       DEBUG_INTR("end.\n");
-
-       return IRQ_RETVAL(handled);
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning.  Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-{
-       spin_lock_irq(&i->lock);
-
-       if (!list_empty(i->head)) {
-               if (i->head == &up->list)
-                       i->head = i->head->next;
-               list_del(&up->list);
-       } else {
-               BUG_ON(i->head != &up->list);
-               i->head = NULL;
-       }
-       spin_unlock_irq(&i->lock);
-       /* List empty so throw away the hash node */
-       if (i->head == NULL) {
-               hlist_del(&i->node);
-               kfree(i);
-       }
-}
-
-static int serial_link_irq_chain(struct uart_8250_port *up)
-{
-       struct hlist_head *h;
-       struct hlist_node *n;
-       struct irq_info *i;
-       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-
-       mutex_lock(&hash_mutex);
-
-       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
-       hlist_for_each(n, h) {
-               i = hlist_entry(n, struct irq_info, node);
-               if (i->irq == up->port.irq)
-                       break;
-       }
-
-       if (n == NULL) {
-               i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
-               if (i == NULL) {
-                       mutex_unlock(&hash_mutex);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&i->lock);
-               i->irq = up->port.irq;
-               hlist_add_head(&i->node, h);
-       }
-       mutex_unlock(&hash_mutex);
-
-       spin_lock_irq(&i->lock);
-
-       if (i->head) {
-               list_add(&up->list, i->head);
-               spin_unlock_irq(&i->lock);
-
-               ret = 0;
-       } else {
-               INIT_LIST_HEAD(&up->list);
-               i->head = &up->list;
-               spin_unlock_irq(&i->lock);
-               irq_flags |= up->port.irqflags;
-               ret = request_irq(up->port.irq, serial8250_interrupt,
-                                 irq_flags, "serial", i);
-               if (ret < 0)
-                       serial_do_unlink(i, up);
-       }
-
-       return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_8250_port *up)
-{
-       struct irq_info *i;
-       struct hlist_node *n;
-       struct hlist_head *h;
-
-       mutex_lock(&hash_mutex);
-
-       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
-       hlist_for_each(n, h) {
-               i = hlist_entry(n, struct irq_info, node);
-               if (i->irq == up->port.irq)
-                       break;
-       }
-
-       BUG_ON(n == NULL);
-       BUG_ON(i->head == NULL);
-
-       if (list_empty(i->head))
-               free_irq(up->port.irq, i);
-
-       serial_do_unlink(i, up);
-       mutex_unlock(&hash_mutex);
-}
-
-/*
- * This function is used to handle ports that do not have an
- * interrupt.  This doesn't work very well for 16450's, but gives
- * barely passable results for a 16550A.  (Although at the expense
- * of much CPU overhead).
- */
-static void serial8250_timeout(unsigned long data)
-{
-       struct uart_8250_port *up = (struct uart_8250_port *)data;
-
-       up->port.handle_irq(&up->port);
-       mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
-}
-
-static void serial8250_backup_timeout(unsigned long data)
-{
-       struct uart_8250_port *up = (struct uart_8250_port *)data;
-       unsigned int iir, ier = 0, lsr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       /*
-        * Must disable interrupts or else we risk racing with the interrupt
-        * based handler.
-        */
-       if (is_real_interrupt(up->port.irq)) {
-               ier = serial_in(up, UART_IER);
-               serial_out(up, UART_IER, 0);
-       }
-
-       iir = serial_in(up, UART_IIR);
-
-       /*
-        * This should be a safe test for anyone who doesn't trust the
-        * IIR bits on their UART, but it's specifically designed for
-        * the "Diva" UART used on the management processor on many HP
-        * ia64 and parisc boxes.
-        */
-       lsr = serial_in(up, UART_LSR);
-       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-       if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
-           (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
-           (lsr & UART_LSR_THRE)) {
-               iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
-               iir |= UART_IIR_THRI;
-       }
-
-       if (!(iir & UART_IIR_NO_INT))
-               serial8250_tx_chars(up);
-
-       if (is_real_interrupt(up->port.irq))
-               serial_out(up, UART_IER, ier);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /* Standard timer interval plus 0.2s to keep the port running */
-       mod_timer(&up->timer,
-               jiffies + uart_poll_timeout(&up->port) + HZ / 5);
-}
-
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned long flags;
-       unsigned int lsr;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       lsr = serial_in(up, UART_LSR);
-       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned int status;
-       unsigned int ret;
-
-       status = serial8250_modem_status(up);
-
-       ret = 0;
-       if (status & UART_MSR_DCD)
-               ret |= TIOCM_CAR;
-       if (status & UART_MSR_RI)
-               ret |= TIOCM_RNG;
-       if (status & UART_MSR_DSR)
-               ret |= TIOCM_DSR;
-       if (status & UART_MSR_CTS)
-               ret |= TIOCM_CTS;
-       return ret;
-}
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned char mcr = 0;
-
-       if (mctrl & TIOCM_RTS)
-               mcr |= UART_MCR_RTS;
-       if (mctrl & TIOCM_DTR)
-               mcr |= UART_MCR_DTR;
-       if (mctrl & TIOCM_OUT1)
-               mcr |= UART_MCR_OUT1;
-       if (mctrl & TIOCM_OUT2)
-               mcr |= UART_MCR_OUT2;
-       if (mctrl & TIOCM_LOOP)
-               mcr |= UART_MCR_LOOP;
-
-       mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-
-       serial_out(up, UART_MCR, mcr);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned long flags;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (break_state == -1)
-               up->lcr |= UART_LCR_SBC;
-       else
-               up->lcr &= ~UART_LCR_SBC;
-       serial_out(up, UART_LCR, up->lcr);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- *     Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
-       unsigned int status, tmout = 10000;
-
-       /* Wait up to 10ms for the character(s) to be sent. */
-       for (;;) {
-               status = serial_in(up, UART_LSR);
-
-               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
-
-               if ((status & bits) == bits)
-                       break;
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       }
-
-       /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & UPF_CONS_FLOW) {
-               unsigned int tmout;
-               for (tmout = 1000000; tmout; tmout--) {
-                       unsigned int msr = serial_in(up, UART_MSR);
-                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
-                       if (msr & UART_MSR_CTS)
-                               break;
-                       udelay(1);
-                       touch_nmi_watchdog();
-               }
-       }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial8250_get_poll_char(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned char lsr = serial_inp(up, UART_LSR);
-
-       if (!(lsr & UART_LSR_DR))
-               return NO_POLL_CHAR;
-
-       return serial_inp(up, UART_RX);
-}
-
-
-static void serial8250_put_poll_char(struct uart_port *port,
-                        unsigned char c)
-{
-       unsigned int ier;
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       /*
-        *      First save the IER then disable the interrupts
-        */
-       ier = serial_in(up, UART_IER);
-       if (up->capabilities & UART_CAP_UUE)
-               serial_out(up, UART_IER, UART_IER_UUE);
-       else
-               serial_out(up, UART_IER, 0);
-
-       wait_for_xmitr(up, BOTH_EMPTY);
-       /*
-        *      Send the character out.
-        *      If a LF, also do CR...
-        */
-       serial_out(up, UART_TX, c);
-       if (c == 10) {
-               wait_for_xmitr(up, BOTH_EMPTY);
-               serial_out(up, UART_TX, 13);
-       }
-
-       /*
-        *      Finally, wait for transmitter to become empty
-        *      and restore the IER
-        */
-       wait_for_xmitr(up, BOTH_EMPTY);
-       serial_out(up, UART_IER, ier);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-static int serial8250_startup(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned long flags;
-       unsigned char lsr, iir;
-       int retval;
-
-       up->port.fifosize = uart_config[up->port.type].fifo_size;
-       up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
-       up->capabilities = uart_config[up->port.type].flags;
-       up->mcr = 0;
-
-       if (up->port.iotype != up->cur_iotype)
-               set_io_from_upio(port);
-
-       if (up->port.type == PORT_16C950) {
-               /* Wake up and initialize UART */
-               up->acr = 0;
-               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-               serial_outp(up, UART_EFR, UART_EFR_ECB);
-               serial_outp(up, UART_IER, 0);
-               serial_outp(up, UART_LCR, 0);
-               serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
-               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-               serial_outp(up, UART_EFR, UART_EFR_ECB);
-               serial_outp(up, UART_LCR, 0);
-       }
-
-#ifdef CONFIG_SERIAL_8250_RSA
-       /*
-        * If this is an RSA port, see if we can kick it up to the
-        * higher speed clock.
-        */
-       enable_rsa(up);
-#endif
-
-       /*
-        * Clear the FIFO buffers and disable them.
-        * (they will be reenabled in set_termios())
-        */
-       serial8250_clear_fifos(up);
-
-       /*
-        * Clear the interrupt registers.
-        */
-       (void) serial_inp(up, UART_LSR);
-       (void) serial_inp(up, UART_RX);
-       (void) serial_inp(up, UART_IIR);
-       (void) serial_inp(up, UART_MSR);
-
-       /*
-        * At this point, there's no way the LSR could still be 0xff;
-        * if it is, then bail out, because there's likely no UART
-        * here.
-        */
-       if (!(up->port.flags & UPF_BUGGY_UART) &&
-           (serial_inp(up, UART_LSR) == 0xff)) {
-               printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
-                                  serial_index(&up->port));
-               return -ENODEV;
-       }
-
-       /*
-        * For a XR16C850, we need to set the trigger levels
-        */
-       if (up->port.type == PORT_16850) {
-               unsigned char fctr;
-
-               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
-               fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
-               serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
-               serial_outp(up, UART_TRG, UART_TRG_96);
-               serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
-               serial_outp(up, UART_TRG, UART_TRG_96);
-
-               serial_outp(up, UART_LCR, 0);
-       }
-
-       if (is_real_interrupt(up->port.irq)) {
-               unsigned char iir1;
-               /*
-                * Test for UARTs that do not reassert THRE when the
-                * transmitter is idle and the interrupt has already
-                * been cleared.  Real 16550s should always reassert
-                * this interrupt whenever the transmitter is idle and
-                * the interrupt is enabled.  Delays are necessary to
-                * allow register changes to become visible.
-                */
-               spin_lock_irqsave(&up->port.lock, flags);
-               if (up->port.irqflags & IRQF_SHARED)
-                       disable_irq_nosync(up->port.irq);
-
-               wait_for_xmitr(up, UART_LSR_THRE);
-               serial_out_sync(up, UART_IER, UART_IER_THRI);
-               udelay(1); /* allow THRE to set */
-               iir1 = serial_in(up, UART_IIR);
-               serial_out(up, UART_IER, 0);
-               serial_out_sync(up, UART_IER, UART_IER_THRI);
-               udelay(1); /* allow a working UART time to re-assert THRE */
-               iir = serial_in(up, UART_IIR);
-               serial_out(up, UART_IER, 0);
-
-               if (up->port.irqflags & IRQF_SHARED)
-                       enable_irq(up->port.irq);
-               spin_unlock_irqrestore(&up->port.lock, flags);
-
-               /*
-                * If the interrupt is not reasserted, setup a timer to
-                * kick the UART on a regular basis.
-                */
-               if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
-                       up->bugs |= UART_BUG_THRE;
-                       pr_debug("ttyS%d - using backup timer\n",
-                                serial_index(port));
-               }
-       }
-
-       /*
-        * The above check will only give an accurate result the first time
-        * the port is opened so this value needs to be preserved.
-        */
-       if (up->bugs & UART_BUG_THRE) {
-               up->timer.function = serial8250_backup_timeout;
-               up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies +
-                       uart_poll_timeout(port) + HZ / 5);
-       }
-
-       /*
-        * If the "interrupt" for this port doesn't correspond with any
-        * hardware interrupt, we use a timer-based system.  The original
-        * driver used to do this with IRQ0.
-        */
-       if (!is_real_interrupt(up->port.irq)) {
-               up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
-       } else {
-               retval = serial_link_irq_chain(up);
-               if (retval)
-                       return retval;
-       }
-
-       /*
-        * Now, initialize the UART
-        */
-       serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (up->port.flags & UPF_FOURPORT) {
-               if (!is_real_interrupt(up->port.irq))
-                       up->port.mctrl |= TIOCM_OUT1;
-       } else
-               /*
-                * Most PC uarts need OUT2 raised to enable interrupts.
-                */
-               if (is_real_interrupt(up->port.irq))
-                       up->port.mctrl |= TIOCM_OUT2;
-
-       serial8250_set_mctrl(&up->port, up->port.mctrl);
-
-       /* Serial over Lan (SoL) hack:
-          Intel 8257x Gigabit ethernet chips have a
-          16550 emulation, to be used for Serial Over Lan.
-          Those chips take a longer time than a normal
-          serial device to signalize that a transmission
-          data was queued. Due to that, the above test generally
-          fails. One solution would be to delay the reading of
-          iir. However, this is not reliable, since the timeout
-          is variable. So, let's just don't test if we receive
-          TX irq. This way, we'll never enable UART_BUG_TXEN.
-        */
-       if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
-               goto dont_test_tx_en;
-
-       /*
-        * Do a quick test to see if we receive an
-        * interrupt when we enable the TX irq.
-        */
-       serial_outp(up, UART_IER, UART_IER_THRI);
-       lsr = serial_in(up, UART_LSR);
-       iir = serial_in(up, UART_IIR);
-       serial_outp(up, UART_IER, 0);
-
-       if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
-               if (!(up->bugs & UART_BUG_TXEN)) {
-                       up->bugs |= UART_BUG_TXEN;
-                       pr_debug("ttyS%d - enabling bad tx status workarounds\n",
-                                serial_index(port));
-               }
-       } else {
-               up->bugs &= ~UART_BUG_TXEN;
-       }
-
-dont_test_tx_en:
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /*
-        * Clear the interrupt registers again for luck, and clear the
-        * saved flags to avoid getting false values from polling
-        * routines or the previous session.
-        */
-       serial_inp(up, UART_LSR);
-       serial_inp(up, UART_RX);
-       serial_inp(up, UART_IIR);
-       serial_inp(up, UART_MSR);
-       up->lsr_saved_flags = 0;
-       up->msr_saved_flags = 0;
-
-       /*
-        * Finally, enable interrupts.  Note: Modem status interrupts
-        * are set via set_termios(), which will be occurring imminently
-        * anyway, so we don't enable them here.
-        */
-       up->ier = UART_IER_RLSI | UART_IER_RDI;
-       serial_outp(up, UART_IER, up->ier);
-
-       if (up->port.flags & UPF_FOURPORT) {
-               unsigned int icp;
-               /*
-                * Enable interrupts on the AST Fourport board
-                */
-               icp = (up->port.iobase & 0xfe0) | 0x01f;
-               outb_p(0x80, icp);
-               (void) inb_p(icp);
-       }
-
-       return 0;
-}
-
-static void serial8250_shutdown(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned long flags;
-
-       /*
-        * Disable interrupts from this port
-        */
-       up->ier = 0;
-       serial_outp(up, UART_IER, 0);
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (up->port.flags & UPF_FOURPORT) {
-               /* reset interrupts on the AST Fourport board */
-               inb((up->port.iobase & 0xfe0) | 0x1f);
-               up->port.mctrl |= TIOCM_OUT1;
-       } else
-               up->port.mctrl &= ~TIOCM_OUT2;
-
-       serial8250_set_mctrl(&up->port, up->port.mctrl);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /*
-        * Disable break condition and FIFOs
-        */
-       serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
-       serial8250_clear_fifos(up);
-
-#ifdef CONFIG_SERIAL_8250_RSA
-       /*
-        * Reset the RSA board back to 115kbps compat mode.
-        */
-       disable_rsa(up);
-#endif
-
-       /*
-        * Read data port to reset things, and then unlink from
-        * the IRQ chain.
-        */
-       (void) serial_in(up, UART_RX);
-
-       del_timer_sync(&up->timer);
-       up->timer.function = serial8250_timeout;
-       if (is_real_interrupt(up->port.irq))
-               serial_unlink_irq_chain(up);
-}
-
-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
-{
-       unsigned int quot;
-
-       /*
-        * Handle magic divisors for baud rates above baud_base on
-        * SMSC SuperIO chips.
-        */
-       if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-           baud == (port->uartclk/4))
-               quot = 0x8001;
-       else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-                baud == (port->uartclk/8))
-               quot = 0x8002;
-       else
-               quot = uart_get_divisor(port, baud);
-
-       return quot;
-}
-
-void
-serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
-                         struct ktermios *old)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       unsigned char cval, fcr = 0;
-       unsigned long flags;
-       unsigned int baud, quot;
-
-       switch (termios->c_cflag & CSIZE) {
-       case CS5:
-               cval = UART_LCR_WLEN5;
-               break;
-       case CS6:
-               cval = UART_LCR_WLEN6;
-               break;
-       case CS7:
-               cval = UART_LCR_WLEN7;
-               break;
-       default:
-       case CS8:
-               cval = UART_LCR_WLEN8;
-               break;
-       }
-
-       if (termios->c_cflag & CSTOPB)
-               cval |= UART_LCR_STOP;
-       if (termios->c_cflag & PARENB)
-               cval |= UART_LCR_PARITY;
-       if (!(termios->c_cflag & PARODD))
-               cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
-       if (termios->c_cflag & CMSPAR)
-               cval |= UART_LCR_SPAR;
-#endif
-
-       /*
-        * Ask the core to calculate the divisor for us.
-        */
-       baud = uart_get_baud_rate(port, termios, old,
-                                 port->uartclk / 16 / 0xffff,
-                                 port->uartclk / 16);
-       quot = serial8250_get_divisor(port, baud);
-
-       /*
-        * Oxford Semi 952 rev B workaround
-        */
-       if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
-               quot++;
-
-       if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
-               if (baud < 2400)
-                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-               else
-                       fcr = uart_config[up->port.type].fcr;
-       }
-
-       /*
-        * MCR-based auto flow control.  When AFE is enabled, RTS will be
-        * deasserted when the receive FIFO contains more characters than
-        * the trigger, or the MCR RTS bit is cleared.  In the case where
-        * the remote UART is not using CTS auto flow control, we must
-        * have sufficient FIFO entries for the latency of the remote
-        * UART to respond.  IOW, at least 32 bytes of FIFO.
-        */
-       if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
-               up->mcr &= ~UART_MCR_AFE;
-               if (termios->c_cflag & CRTSCTS)
-                       up->mcr |= UART_MCR_AFE;
-       }
-
-       /*
-        * Ok, we're now changing the port state.  Do it with
-        * interrupts disabled.
-        */
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       /*
-        * Update the per-port timeout.
-        */
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-       if (termios->c_iflag & INPCK)
-               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-       if (termios->c_iflag & (BRKINT | PARMRK))
-               up->port.read_status_mask |= UART_LSR_BI;
-
-       /*
-        * Characteres to ignore
-        */
-       up->port.ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-       if (termios->c_iflag & IGNBRK) {
-               up->port.ignore_status_mask |= UART_LSR_BI;
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns too (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       up->port.ignore_status_mask |= UART_LSR_OE;
-       }
-
-       /*
-        * ignore all characters if CREAD is not set
-        */
-       if ((termios->c_cflag & CREAD) == 0)
-               up->port.ignore_status_mask |= UART_LSR_DR;
-
-       /*
-        * CTS flow control flag and modem status interrupts
-        */
-       up->ier &= ~UART_IER_MSI;
-       if (!(up->bugs & UART_BUG_NOMSR) &&
-                       UART_ENABLE_MS(&up->port, termios->c_cflag))
-               up->ier |= UART_IER_MSI;
-       if (up->capabilities & UART_CAP_UUE)
-               up->ier |= UART_IER_UUE;
-       if (up->capabilities & UART_CAP_RTOIE)
-               up->ier |= UART_IER_RTOIE;
-
-       serial_out(up, UART_IER, up->ier);
-
-       if (up->capabilities & UART_CAP_EFR) {
-               unsigned char efr = 0;
-               /*
-                * TI16C752/Startech hardware flow control.  FIXME:
-                * - TI16C752 requires control thresholds to be set.
-                * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
-                */
-               if (termios->c_cflag & CRTSCTS)
-                       efr |= UART_EFR_CTS;
-
-               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-               if (up->port.flags & UPF_EXAR_EFR)
-                       serial_outp(up, UART_XR_EFR, efr);
-               else
-                       serial_outp(up, UART_EFR, efr);
-       }
-
-#ifdef CONFIG_ARCH_OMAP
-       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
-       if (cpu_is_omap1510() && is_omap_port(up)) {
-               if (baud == 115200) {
-                       quot = 1;
-                       serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
-               } else
-                       serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
-       }
-#endif
-
-       if (up->capabilities & UART_NATSEMI) {
-               /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
-               serial_outp(up, UART_LCR, 0xe0);
-       } else {
-               serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
-       }
-
-       serial_dl_write(up, quot);
-
-       /*
-        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
-        * is written without DLAB set, this mode will be disabled.
-        */
-       if (up->port.type == PORT_16750)
-               serial_outp(up, UART_FCR, fcr);
-
-       serial_outp(up, UART_LCR, cval);                /* reset DLAB */
-       up->lcr = cval;                                 /* Save LCR */
-       if (up->port.type != PORT_16750) {
-               if (fcr & UART_FCR_ENABLE_FIFO) {
-                       /* emulated UARTs (Lucent Venus 167x) need two steps */
-                       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-               }
-               serial_outp(up, UART_FCR, fcr);         /* set fcr */
-       }
-       serial8250_set_mctrl(&up->port, up->port.mctrl);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       /* Don't rewrite B0 */
-       if (tty_termios_baud_rate(termios))
-               tty_termios_encode_baud_rate(termios, baud, baud);
-}
-EXPORT_SYMBOL(serial8250_do_set_termios);
-
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
-                      struct ktermios *old)
-{
-       if (port->set_termios)
-               port->set_termios(port, termios, old);
-       else
-               serial8250_do_set_termios(port, termios, old);
-}
-
-static void
-serial8250_set_ldisc(struct uart_port *port, int new)
-{
-       if (new == N_PPS) {
-               port->flags |= UPF_HARDPPS_CD;
-               serial8250_enable_ms(port);
-       } else
-               port->flags &= ~UPF_HARDPPS_CD;
-}
-
-
-void serial8250_do_pm(struct uart_port *port, unsigned int state,
-                     unsigned int oldstate)
-{
-       struct uart_8250_port *p =
-               container_of(port, struct uart_8250_port, port);
-
-       serial8250_set_sleep(p, state != 0);
-}
-EXPORT_SYMBOL(serial8250_do_pm);
-
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
-             unsigned int oldstate)
-{
-       if (port->pm)
-               port->pm(port, state, oldstate);
-       else
-               serial8250_do_pm(port, state, oldstate);
-}
-
-static unsigned int serial8250_port_size(struct uart_8250_port *pt)
-{
-       if (pt->port.iotype == UPIO_AU)
-               return 0x1000;
-#ifdef CONFIG_ARCH_OMAP
-       if (is_omap_port(pt))
-               return 0x16 << pt->port.regshift;
-#endif
-       return 8 << pt->port.regshift;
-}
-
-/*
- * Resource handling.
- */
-static int serial8250_request_std_resource(struct uart_8250_port *up)
-{
-       unsigned int size = serial8250_port_size(up);
-       int ret = 0;
-
-       switch (up->port.iotype) {
-       case UPIO_AU:
-       case UPIO_TSI:
-       case UPIO_MEM32:
-       case UPIO_MEM:
-               if (!up->port.mapbase)
-                       break;
-
-               if (!request_mem_region(up->port.mapbase, size, "serial")) {
-                       ret = -EBUSY;
-                       break;
-               }
-
-               if (up->port.flags & UPF_IOREMAP) {
-                       up->port.membase = ioremap_nocache(up->port.mapbase,
-                                                                       size);
-                       if (!up->port.membase) {
-                               release_mem_region(up->port.mapbase, size);
-                               ret = -ENOMEM;
-                       }
-               }
-               break;
-
-       case UPIO_HUB6:
-       case UPIO_PORT:
-               if (!request_region(up->port.iobase, size, "serial"))
-                       ret = -EBUSY;
-               break;
-       }
-       return ret;
-}
-
-static void serial8250_release_std_resource(struct uart_8250_port *up)
-{
-       unsigned int size = serial8250_port_size(up);
-
-       switch (up->port.iotype) {
-       case UPIO_AU:
-       case UPIO_TSI:
-       case UPIO_MEM32:
-       case UPIO_MEM:
-               if (!up->port.mapbase)
-                       break;
-
-               if (up->port.flags & UPF_IOREMAP) {
-                       iounmap(up->port.membase);
-                       up->port.membase = NULL;
-               }
-
-               release_mem_region(up->port.mapbase, size);
-               break;
-
-       case UPIO_HUB6:
-       case UPIO_PORT:
-               release_region(up->port.iobase, size);
-               break;
-       }
-}
-
-static int serial8250_request_rsa_resource(struct uart_8250_port *up)
-{
-       unsigned long start = UART_RSA_BASE << up->port.regshift;
-       unsigned int size = 8 << up->port.regshift;
-       int ret = -EINVAL;
-
-       switch (up->port.iotype) {
-       case UPIO_HUB6:
-       case UPIO_PORT:
-               start += up->port.iobase;
-               if (request_region(start, size, "serial-rsa"))
-                       ret = 0;
-               else
-                       ret = -EBUSY;
-               break;
-       }
-
-       return ret;
-}
-
-static void serial8250_release_rsa_resource(struct uart_8250_port *up)
-{
-       unsigned long offset = UART_RSA_BASE << up->port.regshift;
-       unsigned int size = 8 << up->port.regshift;
-
-       switch (up->port.iotype) {
-       case UPIO_HUB6:
-       case UPIO_PORT:
-               release_region(up->port.iobase + offset, size);
-               break;
-       }
-}
-
-static void serial8250_release_port(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       serial8250_release_std_resource(up);
-       if (up->port.type == PORT_RSA)
-               serial8250_release_rsa_resource(up);
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       int ret = 0;
-
-       ret = serial8250_request_std_resource(up);
-       if (ret == 0 && up->port.type == PORT_RSA) {
-               ret = serial8250_request_rsa_resource(up);
-               if (ret < 0)
-                       serial8250_release_std_resource(up);
-       }
-
-       return ret;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       int probeflags = PROBE_ANY;
-       int ret;
-
-       /*
-        * Find the region that we can probe for.  This in turn
-        * tells us whether we can probe for the type of port.
-        */
-       ret = serial8250_request_std_resource(up);
-       if (ret < 0)
-               return;
-
-       ret = serial8250_request_rsa_resource(up);
-       if (ret < 0)
-               probeflags &= ~PROBE_RSA;
-
-       if (up->port.iotype != up->cur_iotype)
-               set_io_from_upio(port);
-
-       if (flags & UART_CONFIG_TYPE)
-               autoconfig(up, probeflags);
-
-       /* if access method is AU, it is a 16550 with a quirk */
-       if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
-               up->bugs |= UART_BUG_NOMSR;
-
-       if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-               autoconfig_irq(up);
-
-       if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
-               serial8250_release_rsa_resource(up);
-       if (up->port.type == PORT_UNKNOWN)
-               serial8250_release_std_resource(up);
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       if (ser->irq >= nr_irqs || ser->irq < 0 ||
-           ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-           ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
-           ser->type == PORT_STARTECH)
-               return -EINVAL;
-       return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
-       int type = port->type;
-
-       if (type >= ARRAY_SIZE(uart_config))
-               type = 0;
-       return uart_config[type].name;
-}
-
-static struct uart_ops serial8250_pops = {
-       .tx_empty       = serial8250_tx_empty,
-       .set_mctrl      = serial8250_set_mctrl,
-       .get_mctrl      = serial8250_get_mctrl,
-       .stop_tx        = serial8250_stop_tx,
-       .start_tx       = serial8250_start_tx,
-       .stop_rx        = serial8250_stop_rx,
-       .enable_ms      = serial8250_enable_ms,
-       .break_ctl      = serial8250_break_ctl,
-       .startup        = serial8250_startup,
-       .shutdown       = serial8250_shutdown,
-       .set_termios    = serial8250_set_termios,
-       .set_ldisc      = serial8250_set_ldisc,
-       .pm             = serial8250_pm,
-       .type           = serial8250_type,
-       .release_port   = serial8250_release_port,
-       .request_port   = serial8250_request_port,
-       .config_port    = serial8250_config_port,
-       .verify_port    = serial8250_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-       .poll_get_char = serial8250_get_poll_char,
-       .poll_put_char = serial8250_put_poll_char,
-#endif
-};
-
-static struct uart_8250_port serial8250_ports[UART_NR];
-
-static void (*serial8250_isa_config)(int port, struct uart_port *up,
-       unsigned short *capabilities);
-
-void serial8250_set_isa_configurator(
-       void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
-{
-       serial8250_isa_config = v;
-}
-EXPORT_SYMBOL(serial8250_set_isa_configurator);
-
-static void __init serial8250_isa_init_ports(void)
-{
-       struct uart_8250_port *up;
-       static int first = 1;
-       int i, irqflag = 0;
-
-       if (!first)
-               return;
-       first = 0;
-
-       for (i = 0; i < nr_uarts; i++) {
-               struct uart_8250_port *up = &serial8250_ports[i];
-
-               up->port.line = i;
-               spin_lock_init(&up->port.lock);
-
-               init_timer(&up->timer);
-               up->timer.function = serial8250_timeout;
-
-               /*
-                * ALPHA_KLUDGE_MCR needs to be killed.
-                */
-               up->mcr_mask = ~ALPHA_KLUDGE_MCR;
-               up->mcr_force = ALPHA_KLUDGE_MCR;
-
-               up->port.ops = &serial8250_pops;
-       }
-
-       if (share_irqs)
-               irqflag = IRQF_SHARED;
-
-       for (i = 0, up = serial8250_ports;
-            i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
-            i++, up++) {
-               up->port.iobase   = old_serial_port[i].port;
-               up->port.irq      = irq_canonicalize(old_serial_port[i].irq);
-               up->port.irqflags = old_serial_port[i].irqflags;
-               up->port.uartclk  = old_serial_port[i].baud_base * 16;
-               up->port.flags    = old_serial_port[i].flags;
-               up->port.hub6     = old_serial_port[i].hub6;
-               up->port.membase  = old_serial_port[i].iomem_base;
-               up->port.iotype   = old_serial_port[i].io_type;
-               up->port.regshift = old_serial_port[i].iomem_reg_shift;
-               set_io_from_upio(&up->port);
-               up->port.irqflags |= irqflag;
-               if (serial8250_isa_config != NULL)
-                       serial8250_isa_config(i, &up->port, &up->capabilities);
-
-       }
-}
-
-static void
-serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
-{
-       up->port.type = type;
-       up->port.fifosize = uart_config[type].fifo_size;
-       up->capabilities = uart_config[type].flags;
-       up->tx_loadsz = uart_config[type].tx_loadsz;
-}
-
-static void __init
-serial8250_register_ports(struct uart_driver *drv, struct device *dev)
-{
-       int i;
-
-       for (i = 0; i < nr_uarts; i++) {
-               struct uart_8250_port *up = &serial8250_ports[i];
-               up->cur_iotype = 0xFF;
-       }
-
-       serial8250_isa_init_ports();
-
-       for (i = 0; i < nr_uarts; i++) {
-               struct uart_8250_port *up = &serial8250_ports[i];
-
-               up->port.dev = dev;
-
-               if (up->port.flags & UPF_FIXED_TYPE)
-                       serial8250_init_fixed_type_port(up, up->port.type);
-
-               uart_add_one_port(drv, &up->port);
-       }
-}
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-
-static void serial8250_console_putchar(struct uart_port *port, int ch)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       wait_for_xmitr(up, UART_LSR_THRE);
-       serial_out(up, UART_TX, ch);
-}
-
-/*
- *     Print a string to the serial port trying not to disturb
- *     any possible real use of the port...
- *
- *     The console_lock must be held when we get here.
- */
-static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
-{
-       struct uart_8250_port *up = &serial8250_ports[co->index];
-       unsigned long flags;
-       unsigned int ier;
-       int locked = 1;
-
-       touch_nmi_watchdog();
-
-       local_irq_save(flags);
-       if (up->port.sysrq) {
-               /* serial8250_handle_irq() already took the lock */
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = spin_trylock(&up->port.lock);
-       } else
-               spin_lock(&up->port.lock);
-
-       /*
-        *      First save the IER then disable the interrupts
-        */
-       ier = serial_in(up, UART_IER);
-
-       if (up->capabilities & UART_CAP_UUE)
-               serial_out(up, UART_IER, UART_IER_UUE);
-       else
-               serial_out(up, UART_IER, 0);
-
-       uart_console_write(&up->port, s, count, serial8250_console_putchar);
-
-       /*
-        *      Finally, wait for transmitter to become empty
-        *      and restore the IER
-        */
-       wait_for_xmitr(up, BOTH_EMPTY);
-       serial_out(up, UART_IER, ier);
-
-       /*
-        *      The receive handling will happen properly because the
-        *      receive ready bit will still be set; it is not cleared
-        *      on read.  However, modem control will not, we must
-        *      call it if we have saved something in the saved flags
-        *      while processing with interrupts off.
-        */
-       if (up->msr_saved_flags)
-               serial8250_modem_status(up);
-
-       if (locked)
-               spin_unlock(&up->port.lock);
-       local_irq_restore(flags);
-}
-
-static int __init serial8250_console_setup(struct console *co, char *options)
-{
-       struct uart_port *port;
-       int baud = 9600;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       /*
-        * Check whether an invalid uart number has been specified, and
-        * if so, search for the first available port that does have
-        * console support.
-        */
-       if (co->index >= nr_uarts)
-               co->index = 0;
-       port = &serial8250_ports[co->index].port;
-       if (!port->iobase && !port->membase)
-               return -ENODEV;
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-       return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static int serial8250_console_early_setup(void)
-{
-       return serial8250_find_port_for_earlycon();
-}
-
-static struct console serial8250_console = {
-       .name           = "ttyS",
-       .write          = serial8250_console_write,
-       .device         = uart_console_device,
-       .setup          = serial8250_console_setup,
-       .early_setup    = serial8250_console_early_setup,
-       .flags          = CON_PRINTBUFFER | CON_ANYTIME,
-       .index          = -1,
-       .data           = &serial8250_reg,
-};
-
-static int __init serial8250_console_init(void)
-{
-       if (nr_uarts > UART_NR)
-               nr_uarts = UART_NR;
-
-       serial8250_isa_init_ports();
-       register_console(&serial8250_console);
-       return 0;
-}
-console_initcall(serial8250_console_init);
-
-int serial8250_find_port(struct uart_port *p)
-{
-       int line;
-       struct uart_port *port;
-
-       for (line = 0; line < nr_uarts; line++) {
-               port = &serial8250_ports[line].port;
-               if (uart_match_port(p, port))
-                       return line;
-       }
-       return -ENODEV;
-}
-
-#define SERIAL8250_CONSOLE     &serial8250_console
-#else
-#define SERIAL8250_CONSOLE     NULL
-#endif
-
-static struct uart_driver serial8250_reg = {
-       .owner                  = THIS_MODULE,
-       .driver_name            = "serial",
-       .dev_name               = "ttyS",
-       .major                  = TTY_MAJOR,
-       .minor                  = 64,
-       .cons                   = SERIAL8250_CONSOLE,
-};
-
-/*
- * early_serial_setup - early registration for 8250 ports
- *
- * Setup an 8250 port structure prior to console initialisation.  Use
- * after console initialisation will cause undefined behaviour.
- */
-int __init early_serial_setup(struct uart_port *port)
-{
-       struct uart_port *p;
-
-       if (port->line >= ARRAY_SIZE(serial8250_ports))
-               return -ENODEV;
-
-       serial8250_isa_init_ports();
-       p = &serial8250_ports[port->line].port;
-       p->iobase       = port->iobase;
-       p->membase      = port->membase;
-       p->irq          = port->irq;
-       p->irqflags     = port->irqflags;
-       p->uartclk      = port->uartclk;
-       p->fifosize     = port->fifosize;
-       p->regshift     = port->regshift;
-       p->iotype       = port->iotype;
-       p->flags        = port->flags;
-       p->mapbase      = port->mapbase;
-       p->private_data = port->private_data;
-       p->type         = port->type;
-       p->line         = port->line;
-
-       set_io_from_upio(p);
-       if (port->serial_in)
-               p->serial_in = port->serial_in;
-       if (port->serial_out)
-               p->serial_out = port->serial_out;
-       if (port->handle_irq)
-               p->handle_irq = port->handle_irq;
-       else
-               p->handle_irq = serial8250_default_handle_irq;
-
-       return 0;
-}
-
-/**
- *     serial8250_suspend_port - suspend one serial port
- *     @line:  serial line number
- *
- *     Suspend one serial port.
- */
-void serial8250_suspend_port(int line)
-{
-       uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-/**
- *     serial8250_resume_port - resume one serial port
- *     @line:  serial line number
- *
- *     Resume one serial port.
- */
-void serial8250_resume_port(int line)
-{
-       struct uart_8250_port *up = &serial8250_ports[line];
-
-       if (up->capabilities & UART_NATSEMI) {
-               /* Ensure it's still in high speed mode */
-               serial_outp(up, UART_LCR, 0xE0);
-
-               ns16550a_goto_highspeed(up);
-
-               serial_outp(up, UART_LCR, 0);
-               up->port.uartclk = 921600*16;
-       }
-       uart_resume_port(&serial8250_reg, &up->port);
-}
-
-/*
- * Register a set of serial devices attached to a platform device.  The
- * list is terminated with a zero flags entry, which means we expect
- * all entries to have at least UPF_BOOT_AUTOCONF set.
- */
-static int __devinit serial8250_probe(struct platform_device *dev)
-{
-       struct plat_serial8250_port *p = dev->dev.platform_data;
-       struct uart_port port;
-       int ret, i, irqflag = 0;
-
-       memset(&port, 0, sizeof(struct uart_port));
-
-       if (share_irqs)
-               irqflag = IRQF_SHARED;
-
-       for (i = 0; p && p->flags != 0; p++, i++) {
-               port.iobase             = p->iobase;
-               port.membase            = p->membase;
-               port.irq                = p->irq;
-               port.irqflags           = p->irqflags;
-               port.uartclk            = p->uartclk;
-               port.regshift           = p->regshift;
-               port.iotype             = p->iotype;
-               port.flags              = p->flags;
-               port.mapbase            = p->mapbase;
-               port.hub6               = p->hub6;
-               port.private_data       = p->private_data;
-               port.type               = p->type;
-               port.serial_in          = p->serial_in;
-               port.serial_out         = p->serial_out;
-               port.handle_irq         = p->handle_irq;
-               port.set_termios        = p->set_termios;
-               port.pm                 = p->pm;
-               port.dev                = &dev->dev;
-               port.irqflags           |= irqflag;
-               ret = serial8250_register_port(&port);
-               if (ret < 0) {
-                       dev_err(&dev->dev, "unable to register port at index %d "
-                               "(IO%lx MEM%llx IRQ%d): %d\n", i,
-                               p->iobase, (unsigned long long)p->mapbase,
-                               p->irq, ret);
-               }
-       }
-       return 0;
-}
-
-/*
- * Remove serial ports registered against a platform device.
- */
-static int __devexit serial8250_remove(struct platform_device *dev)
-{
-       int i;
-
-       for (i = 0; i < nr_uarts; i++) {
-               struct uart_8250_port *up = &serial8250_ports[i];
-
-               if (up->port.dev == &dev->dev)
-                       serial8250_unregister_port(i);
-       }
-       return 0;
-}
-
-static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
-{
-       int i;
-
-       for (i = 0; i < UART_NR; i++) {
-               struct uart_8250_port *up = &serial8250_ports[i];
-
-               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
-                       uart_suspend_port(&serial8250_reg, &up->port);
-       }
-
-       return 0;
-}
-
-static int serial8250_resume(struct platform_device *dev)
-{
-       int i;
-
-       for (i = 0; i < UART_NR; i++) {
-               struct uart_8250_port *up = &serial8250_ports[i];
-
-               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
-                       serial8250_resume_port(i);
-       }
-
-       return 0;
-}
-
-static struct platform_driver serial8250_isa_driver = {
-       .probe          = serial8250_probe,
-       .remove         = __devexit_p(serial8250_remove),
-       .suspend        = serial8250_suspend,
-       .resume         = serial8250_resume,
-       .driver         = {
-               .name   = "serial8250",
-               .owner  = THIS_MODULE,
-       },
-};
-
-/*
- * This "device" covers _all_ ISA 8250-compatible serial devices listed
- * in the table in include/asm/serial.h
- */
-static struct platform_device *serial8250_isa_devs;
-
-/*
- * serial8250_register_port and serial8250_unregister_port allows for
- * 16x50 serial ports to be configured at run-time, to support PCMCIA
- * modems and PCI multiport cards.
- */
-static DEFINE_MUTEX(serial_mutex);
-
-static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
-{
-       int i;
-
-       /*
-        * First, find a port entry which matches.
-        */
-       for (i = 0; i < nr_uarts; i++)
-               if (uart_match_port(&serial8250_ports[i].port, port))
-                       return &serial8250_ports[i];
-
-       /*
-        * We didn't find a matching entry, so look for the first
-        * free entry.  We look for one which hasn't been previously
-        * used (indicated by zero iobase).
-        */
-       for (i = 0; i < nr_uarts; i++)
-               if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
-                   serial8250_ports[i].port.iobase == 0)
-                       return &serial8250_ports[i];
-
-       /*
-        * That also failed.  Last resort is to find any entry which
-        * doesn't have a real port associated with it.
-        */
-       for (i = 0; i < nr_uarts; i++)
-               if (serial8250_ports[i].port.type == PORT_UNKNOWN)
-                       return &serial8250_ports[i];
-
-       return NULL;
-}
-
-/**
- *     serial8250_register_port - register a serial port
- *     @port: serial port template
- *
- *     Configure the serial port specified by the request. If the
- *     port exists and is in use, it is hung up and unregistered
- *     first.
- *
- *     The port is then probed and if necessary the IRQ is autodetected
- *     If this fails an error is returned.
- *
- *     On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
-       struct uart_8250_port *uart;
-       int ret = -ENOSPC;
-
-       if (port->uartclk == 0)
-               return -EINVAL;
-
-       mutex_lock(&serial_mutex);
-
-       uart = serial8250_find_match_or_unused(port);
-       if (uart) {
-               uart_remove_one_port(&serial8250_reg, &uart->port);
-
-               uart->port.iobase       = port->iobase;
-               uart->port.membase      = port->membase;
-               uart->port.irq          = port->irq;
-               uart->port.irqflags     = port->irqflags;
-               uart->port.uartclk      = port->uartclk;
-               uart->port.fifosize     = port->fifosize;
-               uart->port.regshift     = port->regshift;
-               uart->port.iotype       = port->iotype;
-               uart->port.flags        = port->flags | UPF_BOOT_AUTOCONF;
-               uart->port.mapbase      = port->mapbase;
-               uart->port.private_data = port->private_data;
-               if (port->dev)
-                       uart->port.dev = port->dev;
-
-               if (port->flags & UPF_FIXED_TYPE)
-                       serial8250_init_fixed_type_port(uart, port->type);
-
-               set_io_from_upio(&uart->port);
-               /* Possibly override default I/O functions.  */
-               if (port->serial_in)
-                       uart->port.serial_in = port->serial_in;
-               if (port->serial_out)
-                       uart->port.serial_out = port->serial_out;
-               if (port->handle_irq)
-                       uart->port.handle_irq = port->handle_irq;
-               /*  Possibly override set_termios call */
-               if (port->set_termios)
-                       uart->port.set_termios = port->set_termios;
-               if (port->pm)
-                       uart->port.pm = port->pm;
-
-               if (serial8250_isa_config != NULL)
-                       serial8250_isa_config(0, &uart->port,
-                                       &uart->capabilities);
-
-               ret = uart_add_one_port(&serial8250_reg, &uart->port);
-               if (ret == 0)
-                       ret = uart->port.line;
-       }
-       mutex_unlock(&serial_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
-/**
- *     serial8250_unregister_port - remove a 16x50 serial port at runtime
- *     @line: serial line number
- *
- *     Remove one serial port.  This may not be called from interrupt
- *     context.  We hand the port back to the our control.
- */
-void serial8250_unregister_port(int line)
-{
-       struct uart_8250_port *uart = &serial8250_ports[line];
-
-       mutex_lock(&serial_mutex);
-       uart_remove_one_port(&serial8250_reg, &uart->port);
-       if (serial8250_isa_devs) {
-               uart->port.flags &= ~UPF_BOOT_AUTOCONF;
-               uart->port.type = PORT_UNKNOWN;
-               uart->port.dev = &serial8250_isa_devs->dev;
-               uart->capabilities = uart_config[uart->port.type].flags;
-               uart_add_one_port(&serial8250_reg, &uart->port);
-       } else {
-               uart->port.dev = NULL;
-       }
-       mutex_unlock(&serial_mutex);
-}
-EXPORT_SYMBOL(serial8250_unregister_port);
-
-static int __init serial8250_init(void)
-{
-       int ret;
-
-       if (nr_uarts > UART_NR)
-               nr_uarts = UART_NR;
-
-       printk(KERN_INFO "Serial: 8250/16550 driver, "
-               "%d ports, IRQ sharing %sabled\n", nr_uarts,
-               share_irqs ? "en" : "dis");
-
-#ifdef CONFIG_SPARC
-       ret = sunserial_register_minors(&serial8250_reg, UART_NR);
-#else
-       serial8250_reg.nr = UART_NR;
-       ret = uart_register_driver(&serial8250_reg);
-#endif
-       if (ret)
-               goto out;
-
-       serial8250_isa_devs = platform_device_alloc("serial8250",
-                                                   PLAT8250_DEV_LEGACY);
-       if (!serial8250_isa_devs) {
-               ret = -ENOMEM;
-               goto unreg_uart_drv;
-       }
-
-       ret = platform_device_add(serial8250_isa_devs);
-       if (ret)
-               goto put_dev;
-
-       serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
-
-       ret = platform_driver_register(&serial8250_isa_driver);
-       if (ret == 0)
-               goto out;
-
-       platform_device_del(serial8250_isa_devs);
-put_dev:
-       platform_device_put(serial8250_isa_devs);
-unreg_uart_drv:
-#ifdef CONFIG_SPARC
-       sunserial_unregister_minors(&serial8250_reg, UART_NR);
-#else
-       uart_unregister_driver(&serial8250_reg);
-#endif
-out:
-       return ret;
-}
-
-static void __exit serial8250_exit(void)
-{
-       struct platform_device *isa_dev = serial8250_isa_devs;
-
-       /*
-        * This tells serial8250_unregister_port() not to re-register
-        * the ports (thereby making serial8250_isa_driver permanently
-        * in use.)
-        */
-       serial8250_isa_devs = NULL;
-
-       platform_driver_unregister(&serial8250_isa_driver);
-       platform_device_unregister(isa_dev);
-
-#ifdef CONFIG_SPARC
-       sunserial_unregister_minors(&serial8250_reg, UART_NR);
-#else
-       uart_unregister_driver(&serial8250_reg);
-#endif
-}
-
-module_init(serial8250_init);
-module_exit(serial8250_exit);
-
-EXPORT_SYMBOL(serial8250_suspend_port);
-EXPORT_SYMBOL(serial8250_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
-
-module_param(share_irqs, uint, 0644);
-MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
-       " (unsafe)");
-
-module_param(nr_uarts, uint, 0644);
-MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
-
-module_param(skip_txen_test, uint, 0644);
-MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
-
-#ifdef CONFIG_SERIAL_8250_RSA
-module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
-MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
-#endif
-MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h
deleted file mode 100644 (file)
index ae027be..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  Driver for 8250/16550-type serial ports
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2001 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/serial_8250.h>
-
-struct uart_8250_port {
-       struct uart_port        port;
-       struct timer_list       timer;          /* "no irq" timer */
-       struct list_head        list;           /* ports on this IRQ */
-       unsigned short          capabilities;   /* port capabilities */
-       unsigned short          bugs;           /* port bugs */
-       unsigned int            tx_loadsz;      /* transmit fifo load size */
-       unsigned char           acr;
-       unsigned char           ier;
-       unsigned char           lcr;
-       unsigned char           mcr;
-       unsigned char           mcr_mask;       /* mask of user bits */
-       unsigned char           mcr_force;      /* mask of forced bits */
-       unsigned char           cur_iotype;     /* Running I/O type */
-
-       /*
-        * Some bits in registers are cleared on a read, so they must
-        * be saved whenever the register is read but the bits will not
-        * be immediately processed.
-        */
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
-       unsigned char           lsr_saved_flags;
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
-       unsigned char           msr_saved_flags;
-};
-
-struct old_serial_port {
-       unsigned int uart;
-       unsigned int baud_base;
-       unsigned int port;
-       unsigned int irq;
-       unsigned int flags;
-       unsigned char hub6;
-       unsigned char io_type;
-       unsigned char *iomem_base;
-       unsigned short iomem_reg_shift;
-       unsigned long irqflags;
-};
-
-/*
- * This replaces serial_uart_config in include/linux/serial.h
- */
-struct serial8250_config {
-       const char      *name;
-       unsigned short  fifo_size;
-       unsigned short  tx_loadsz;
-       unsigned char   fcr;
-       unsigned int    flags;
-};
-
-#define UART_CAP_FIFO  (1 << 8)        /* UART has FIFO */
-#define UART_CAP_EFR   (1 << 9)        /* UART has EFR */
-#define UART_CAP_SLEEP (1 << 10)       /* UART has IER sleep */
-#define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
-#define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
-#define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, Tegra) */
-
-#define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
-#define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
-#define UART_BUG_NOMSR (1 << 2)        /* UART has buggy MSR status bits (Au1x00) */
-#define UART_BUG_THRE  (1 << 3)        /* UART has buggy THRE reassertion */
-
-#define PROBE_RSA      (1 << 0)
-#define PROBE_ANY      (~0)
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
-#define SERIAL8250_SHARE_IRQS 1
-#else
-#define SERIAL8250_SHARE_IRQS 0
-#endif
-
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-/*
- * Digital did something really horribly wrong with the OUT1 and OUT2
- * lines on at least some ALPHA's.  The failure mode is that if either
- * is cleared, the machine locks up with endless interrupts.
- */
-#define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
-#elif defined(CONFIG_SBC8560)
-/*
- * WindRiver did something similarly broken on their SBC8560 board. The
- * UART tristates its IRQ output while OUT2 is clear, but they pulled
- * the interrupt line _up_ instead of down, so if we register the IRQ
- * while the UART is in that state, we die in an IRQ storm. */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
-#else
-#define ALPHA_KLUDGE_MCR 0
-#endif
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
new file mode 100644 (file)
index 0000000..9b7336f
--- /dev/null
@@ -0,0 +1,3357 @@
+/*
+ *  Driver for 8250/16550-type serial ports
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2001 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A note about mapbase / membase
+ *
+ *  mapbase is the physical address of the IO port.
+ *  membase is an 'ioremapped' cookie.
+ */
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/ratelimit.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/nmi.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "8250.h"
+
+#ifdef CONFIG_SPARC
+#include "../suncore.h"
+#endif
+
+/*
+ * Configuration:
+ *   share_irqs - whether we pass IRQF_SHARED to request_irq().  This option
+ *                is unsafe when used on edge-triggered interrupts.
+ */
+static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
+
+static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
+
+static struct uart_driver serial8250_reg;
+
+static int serial_index(struct uart_port *port)
+{
+       return (serial8250_reg.minor - 64) + port->line;
+}
+
+static unsigned int skip_txen_test; /* force skip of txen test at init time */
+
+/*
+ * Debugging.
+ */
+#if 0
+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
+#endif
+
+#if 0
+#define DEBUG_INTR(fmt...)     printk(fmt)
+#else
+#define DEBUG_INTR(fmt...)     do { } while (0)
+#endif
+
+#define PASS_LIMIT     512
+
+#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)
+
+
+/*
+ * We default to IRQ0 for the "no irq" hack.   Some
+ * machine types want others as well - they're free
+ * to redefine this in their header file.
+ */
+#define is_real_interrupt(irq) ((irq) != 0)
+
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
+#define CONFIG_SERIAL_DETECT_IRQ 1
+#endif
+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
+#define CONFIG_SERIAL_MANY_PORTS 1
+#endif
+
+/*
+ * HUB6 is always on.  This will be removed once the header
+ * files have been cleaned.
+ */
+#define CONFIG_HUB6 1
+
+#include <asm/serial.h>
+/*
+ * SERIAL_PORT_DFNS tells us about built-in ports that have no
+ * standard enumeration mechanism.   Platforms that can find all
+ * serial ports via mechanisms like ACPI or PCI need not supply it.
+ */
+#ifndef SERIAL_PORT_DFNS
+#define SERIAL_PORT_DFNS
+#endif
+
+static const struct old_serial_port old_serial_port[] = {
+       SERIAL_PORT_DFNS /* defined in asm/serial.h */
+};
+
+#define UART_NR        CONFIG_SERIAL_8250_NR_UARTS
+
+#ifdef CONFIG_SERIAL_8250_RSA
+
+#define PORT_RSA_MAX 4
+static unsigned long probe_rsa[PORT_RSA_MAX];
+static unsigned int probe_rsa_count;
+#endif /* CONFIG_SERIAL_8250_RSA  */
+
+struct irq_info {
+       struct                  hlist_node node;
+       int                     irq;
+       spinlock_t              lock;   /* Protects list not the hash */
+       struct list_head        *head;
+};
+
+#define NR_IRQ_HASH            32      /* Can be adjusted later */
+static struct hlist_head irq_lists[NR_IRQ_HASH];
+static DEFINE_MUTEX(hash_mutex);       /* Used to walk the hash */
+
+/*
+ * Here we define the default xmit fifo size used for each type of UART.
+ */
+static const struct serial8250_config uart_config[] = {
+       [PORT_UNKNOWN] = {
+               .name           = "unknown",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_8250] = {
+               .name           = "8250",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16450] = {
+               .name           = "16450",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16550] = {
+               .name           = "16550",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16550A] = {
+               .name           = "16550A",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_CIRRUS] = {
+               .name           = "Cirrus",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16650] = {
+               .name           = "ST16650",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_16650V2] = {
+               .name           = "ST16650V2",
+               .fifo_size      = 32,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_00,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_16750] = {
+               .name           = "TI16750",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+                                 UART_FCR7_64BYTE,
+               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
+       },
+       [PORT_STARTECH] = {
+               .name           = "Startech",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16C950] = {
+               .name           = "16C950/954",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               /* UART_CAP_EFR breaks billionon CF bluetooth card. */
+               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP,
+       },
+       [PORT_16654] = {
+               .name           = "ST16654",
+               .fifo_size      = 64,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_16850] = {
+               .name           = "XR16850",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_RSA] = {
+               .name           = "RSA",
+               .fifo_size      = 2048,
+               .tx_loadsz      = 2048,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_NS16550A] = {
+               .name           = "NS16550A",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_NATSEMI,
+       },
+       [PORT_XSCALE] = {
+               .name           = "XScale",
+               .fifo_size      = 32,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
+       },
+       [PORT_RM9000] = {
+               .name           = "RM9000",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_OCTEON] = {
+               .name           = "OCTEON",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_AR7] = {
+               .name           = "AR7",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_U6_16550A] = {
+               .name           = "U6_16550A",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_TEGRA] = {
+               .name           = "Tegra",
+               .fifo_size      = 32,
+               .tx_loadsz      = 8,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_01,
+               .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
+       },
+       [PORT_XR17D15X] = {
+               .name           = "XR17D15X",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
+       },
+};
+
+#if defined(CONFIG_MIPS_ALCHEMY)
+
+/* Au1x00 UART hardware has a weird register layout */
+static const u8 au_io_in_map[] = {
+       [UART_RX]  = 0,
+       [UART_IER] = 2,
+       [UART_IIR] = 3,
+       [UART_LCR] = 5,
+       [UART_MCR] = 6,
+       [UART_LSR] = 7,
+       [UART_MSR] = 8,
+};
+
+static const u8 au_io_out_map[] = {
+       [UART_TX]  = 1,
+       [UART_IER] = 2,
+       [UART_FCR] = 4,
+       [UART_LCR] = 5,
+       [UART_MCR] = 6,
+};
+
+/* sane hardware needs no mapping */
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
+{
+       if (p->iotype != UPIO_AU)
+               return offset;
+       return au_io_in_map[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
+{
+       if (p->iotype != UPIO_AU)
+               return offset;
+       return au_io_out_map[offset];
+}
+
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+
+static const u8
+       regmap_in[8] = {
+               [UART_RX]       = 0x00,
+               [UART_IER]      = 0x0c,
+               [UART_IIR]      = 0x14,
+               [UART_LCR]      = 0x1c,
+               [UART_MCR]      = 0x20,
+               [UART_LSR]      = 0x24,
+               [UART_MSR]      = 0x28,
+               [UART_SCR]      = 0x2c
+       },
+       regmap_out[8] = {
+               [UART_TX]       = 0x04,
+               [UART_IER]      = 0x0c,
+               [UART_FCR]      = 0x18,
+               [UART_LCR]      = 0x1c,
+               [UART_MCR]      = 0x20,
+               [UART_LSR]      = 0x24,
+               [UART_MSR]      = 0x28,
+               [UART_SCR]      = 0x2c
+       };
+
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
+{
+       if (p->iotype != UPIO_RM9000)
+               return offset;
+       return regmap_in[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
+{
+       if (p->iotype != UPIO_RM9000)
+               return offset;
+       return regmap_out[offset];
+}
+
+#else
+
+/* sane hardware needs no mapping */
+#define map_8250_in_reg(up, offset) (offset)
+#define map_8250_out_reg(up, offset) (offset)
+
+#endif
+
+static unsigned int hub6_serial_in(struct uart_port *p, int offset)
+{
+       offset = map_8250_in_reg(p, offset) << p->regshift;
+       outb(p->hub6 - 1 + offset, p->iobase);
+       return inb(p->iobase + 1);
+}
+
+static void hub6_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = map_8250_out_reg(p, offset) << p->regshift;
+       outb(p->hub6 - 1 + offset, p->iobase);
+       outb(value, p->iobase + 1);
+}
+
+static unsigned int mem_serial_in(struct uart_port *p, int offset)
+{
+       offset = map_8250_in_reg(p, offset) << p->regshift;
+       return readb(p->membase + offset);
+}
+
+static void mem_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = map_8250_out_reg(p, offset) << p->regshift;
+       writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = map_8250_out_reg(p, offset) << p->regshift;
+       writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+{
+       offset = map_8250_in_reg(p, offset) << p->regshift;
+       return readl(p->membase + offset);
+}
+
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+       offset = map_8250_in_reg(p, offset) << p->regshift;
+       return __raw_readl(p->membase + offset);
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = map_8250_out_reg(p, offset) << p->regshift;
+       __raw_writel(value, p->membase + offset);
+}
+
+static unsigned int io_serial_in(struct uart_port *p, int offset)
+{
+       offset = map_8250_in_reg(p, offset) << p->regshift;
+       return inb(p->iobase + offset);
+}
+
+static void io_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = map_8250_out_reg(p, offset) << p->regshift;
+       outb(value, p->iobase + offset);
+}
+
+static int serial8250_default_handle_irq(struct uart_port *port);
+
+static void set_io_from_upio(struct uart_port *p)
+{
+       struct uart_8250_port *up =
+               container_of(p, struct uart_8250_port, port);
+       switch (p->iotype) {
+       case UPIO_HUB6:
+               p->serial_in = hub6_serial_in;
+               p->serial_out = hub6_serial_out;
+               break;
+
+       case UPIO_MEM:
+               p->serial_in = mem_serial_in;
+               p->serial_out = mem_serial_out;
+               break;
+
+       case UPIO_RM9000:
+       case UPIO_MEM32:
+               p->serial_in = mem32_serial_in;
+               p->serial_out = mem32_serial_out;
+               break;
+
+       case UPIO_AU:
+               p->serial_in = au_serial_in;
+               p->serial_out = au_serial_out;
+               break;
+
+       default:
+               p->serial_in = io_serial_in;
+               p->serial_out = io_serial_out;
+               break;
+       }
+       /* Remember loaded iotype */
+       up->cur_iotype = p->iotype;
+       p->handle_irq = serial8250_default_handle_irq;
+}
+
+static void
+serial_out_sync(struct uart_8250_port *up, int offset, int value)
+{
+       struct uart_port *p = &up->port;
+       switch (p->iotype) {
+       case UPIO_MEM:
+       case UPIO_MEM32:
+       case UPIO_AU:
+               p->serial_out(p, offset, value);
+               p->serial_in(p, UART_LCR);      /* safe, no side-effects */
+               break;
+       default:
+               p->serial_out(p, offset, value);
+       }
+}
+
+#define serial_in(up, offset)          \
+       (up->port.serial_in(&(up)->port, (offset)))
+#define serial_out(up, offset, value)  \
+       (up->port.serial_out(&(up)->port, (offset), (value)))
+/*
+ * We used to support using pause I/O for certain machines.  We
+ * haven't supported this for a while, but just in case it's badly
+ * needed for certain old 386 machines, I've left these #define's
+ * in....
+ */
+#define serial_inp(up, offset)         serial_in(up, offset)
+#define serial_outp(up, offset, value) serial_out(up, offset, value)
+
+/* Uart divisor latch read */
+static inline int _serial_dl_read(struct uart_8250_port *up)
+{
+       return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+{
+       serial_outp(up, UART_DLL, value & 0xff);
+       serial_outp(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#if defined(CONFIG_MIPS_ALCHEMY)
+/* Au1x00 haven't got a standard divisor latch */
+static int serial_dl_read(struct uart_8250_port *up)
+{
+       if (up->port.iotype == UPIO_AU)
+               return __raw_readl(up->port.membase + 0x28);
+       else
+               return _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+       if (up->port.iotype == UPIO_AU)
+               __raw_writel(value, up->port.membase + 0x28);
+       else
+               _serial_dl_write(up, value);
+}
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+static int serial_dl_read(struct uart_8250_port *up)
+{
+       return  (up->port.iotype == UPIO_RM9000) ?
+               (((__raw_readl(up->port.membase + 0x10) << 8) |
+               (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+               _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+       if (up->port.iotype == UPIO_RM9000) {
+               __raw_writel(value, up->port.membase + 0x08);
+               __raw_writel(value >> 8, up->port.membase + 0x10);
+       } else {
+               _serial_dl_write(up, value);
+       }
+}
+#else
+#define serial_dl_read(up) _serial_dl_read(up)
+#define serial_dl_write(up, value) _serial_dl_write(up, value)
+#endif
+
+/*
+ * For the 16C950
+ */
+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
+{
+       serial_out(up, UART_SCR, offset);
+       serial_out(up, UART_ICR, value);
+}
+
+static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+{
+       unsigned int value;
+
+       serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
+       serial_out(up, UART_SCR, offset);
+       value = serial_in(up, UART_ICR);
+       serial_icr_write(up, UART_ACR, up->acr);
+
+       return value;
+}
+
+/*
+ * FIFO support.
+ */
+static void serial8250_clear_fifos(struct uart_8250_port *p)
+{
+       if (p->capabilities & UART_CAP_FIFO) {
+               serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+               serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+                              UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+               serial_outp(p, UART_FCR, 0);
+       }
+}
+
+/*
+ * IER sleep support.  UARTs which have EFRs need the "extended
+ * capability" bit enabled.  Note that on XR16C850s, we need to
+ * reset LCR to write to IER.
+ */
+static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+{
+       if (p->capabilities & UART_CAP_SLEEP) {
+               if (p->capabilities & UART_CAP_EFR) {
+                       serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
+                       serial_outp(p, UART_EFR, UART_EFR_ECB);
+                       serial_outp(p, UART_LCR, 0);
+               }
+               serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+               if (p->capabilities & UART_CAP_EFR) {
+                       serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
+                       serial_outp(p, UART_EFR, 0);
+                       serial_outp(p, UART_LCR, 0);
+               }
+       }
+}
+
+#ifdef CONFIG_SERIAL_8250_RSA
+/*
+ * Attempts to turn on the RSA FIFO.  Returns zero on failure.
+ * We set the port uart clock rate if we succeed.
+ */
+static int __enable_rsa(struct uart_8250_port *up)
+{
+       unsigned char mode;
+       int result;
+
+       mode = serial_inp(up, UART_RSA_MSR);
+       result = mode & UART_RSA_MSR_FIFO;
+
+       if (!result) {
+               serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
+               mode = serial_inp(up, UART_RSA_MSR);
+               result = mode & UART_RSA_MSR_FIFO;
+       }
+
+       if (result)
+               up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
+
+       return result;
+}
+
+static void enable_rsa(struct uart_8250_port *up)
+{
+       if (up->port.type == PORT_RSA) {
+               if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
+                       spin_lock_irq(&up->port.lock);
+                       __enable_rsa(up);
+                       spin_unlock_irq(&up->port.lock);
+               }
+               if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+                       serial_outp(up, UART_RSA_FRR, 0);
+       }
+}
+
+/*
+ * Attempts to turn off the RSA FIFO.  Returns zero on failure.
+ * It is unknown why interrupts were disabled in here.  However,
+ * the caller is expected to preserve this behaviour by grabbing
+ * the spinlock before calling this function.
+ */
+static void disable_rsa(struct uart_8250_port *up)
+{
+       unsigned char mode;
+       int result;
+
+       if (up->port.type == PORT_RSA &&
+           up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+               spin_lock_irq(&up->port.lock);
+
+               mode = serial_inp(up, UART_RSA_MSR);
+               result = !(mode & UART_RSA_MSR_FIFO);
+
+               if (!result) {
+                       serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
+                       mode = serial_inp(up, UART_RSA_MSR);
+                       result = !(mode & UART_RSA_MSR_FIFO);
+               }
+
+               if (result)
+                       up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
+               spin_unlock_irq(&up->port.lock);
+       }
+}
+#endif /* CONFIG_SERIAL_8250_RSA */
+
+/*
+ * This is a quickie test to see how big the FIFO is.
+ * It doesn't work at all the time, more's the pity.
+ */
+static int size_fifo(struct uart_8250_port *up)
+{
+       unsigned char old_fcr, old_mcr, old_lcr;
+       unsigned short old_dl;
+       int count;
+
+       old_lcr = serial_inp(up, UART_LCR);
+       serial_outp(up, UART_LCR, 0);
+       old_fcr = serial_inp(up, UART_FCR);
+       old_mcr = serial_inp(up, UART_MCR);
+       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+                   UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+       serial_outp(up, UART_MCR, UART_MCR_LOOP);
+       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       old_dl = serial_dl_read(up);
+       serial_dl_write(up, 0x0001);
+       serial_outp(up, UART_LCR, 0x03);
+       for (count = 0; count < 256; count++)
+               serial_outp(up, UART_TX, count);
+       mdelay(20);/* FIXME - schedule_timeout */
+       for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
+            (count < 256); count++)
+               serial_inp(up, UART_RX);
+       serial_outp(up, UART_FCR, old_fcr);
+       serial_outp(up, UART_MCR, old_mcr);
+       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       serial_dl_write(up, old_dl);
+       serial_outp(up, UART_LCR, old_lcr);
+
+       return count;
+}
+
+/*
+ * Read UART ID using the divisor method - set DLL and DLM to zero
+ * and the revision will be in DLL and device type in DLM.  We
+ * preserve the device state across this.
+ */
+static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+{
+       unsigned char old_dll, old_dlm, old_lcr;
+       unsigned int id;
+
+       old_lcr = serial_inp(p, UART_LCR);
+       serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
+
+       old_dll = serial_inp(p, UART_DLL);
+       old_dlm = serial_inp(p, UART_DLM);
+
+       serial_outp(p, UART_DLL, 0);
+       serial_outp(p, UART_DLM, 0);
+
+       id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
+
+       serial_outp(p, UART_DLL, old_dll);
+       serial_outp(p, UART_DLM, old_dlm);
+       serial_outp(p, UART_LCR, old_lcr);
+
+       return id;
+}
+
+/*
+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+ * When this function is called we know it is at least a StarTech
+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
+ * its clones.  (We treat the broken original StarTech 16650 V1 as a
+ * 16550, and why not?  Startech doesn't seem to even acknowledge its
+ * existence.)
+ *
+ * What evil have men's minds wrought...
+ */
+static void autoconfig_has_efr(struct uart_8250_port *up)
+{
+       unsigned int id1, id2, id3, rev;
+
+       /*
+        * Everything with an EFR has SLEEP
+        */
+       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+
+       /*
+        * First we check to see if it's an Oxford Semiconductor UART.
+        *
+        * If we have to do this here because some non-National
+        * Semiconductor clone chips lock up if you try writing to the
+        * LSR register (which serial_icr_read does)
+        */
+
+       /*
+        * Check for Oxford Semiconductor 16C950.
+        *
+        * EFR [4] must be set else this test fails.
+        *
+        * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
+        * claims that it's needed for 952 dual UART's (which are not
+        * recommended for new designs).
+        */
+       up->acr = 0;
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       serial_out(up, UART_EFR, UART_EFR_ECB);
+       serial_out(up, UART_LCR, 0x00);
+       id1 = serial_icr_read(up, UART_ID1);
+       id2 = serial_icr_read(up, UART_ID2);
+       id3 = serial_icr_read(up, UART_ID3);
+       rev = serial_icr_read(up, UART_REV);
+
+       DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
+
+       if (id1 == 0x16 && id2 == 0xC9 &&
+           (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
+               up->port.type = PORT_16C950;
+
+               /*
+                * Enable work around for the Oxford Semiconductor 952 rev B
+                * chip which causes it to seriously miscalculate baud rates
+                * when DLL is 0.
+                */
+               if (id3 == 0x52 && rev == 0x01)
+                       up->bugs |= UART_BUG_QUOT;
+               return;
+       }
+
+       /*
+        * We check for a XR16C850 by setting DLL and DLM to 0, and then
+        * reading back DLL and DLM.  The chip type depends on the DLM
+        * value read back:
+        *  0x10 - XR16C850 and the DLL contains the chip revision.
+        *  0x12 - XR16C2850.
+        *  0x14 - XR16C854.
+        */
+       id1 = autoconfig_read_divisor_id(up);
+       DEBUG_AUTOCONF("850id=%04x ", id1);
+
+       id2 = id1 >> 8;
+       if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
+               up->port.type = PORT_16850;
+               return;
+       }
+
+       /*
+        * It wasn't an XR16C850.
+        *
+        * We distinguish between the '654 and the '650 by counting
+        * how many bytes are in the FIFO.  I'm using this for now,
+        * since that's the technique that was sent to me in the
+        * serial driver update, but I'm not convinced this works.
+        * I've had problems doing this in the past.  -TYT
+        */
+       if (size_fifo(up) == 64)
+               up->port.type = PORT_16654;
+       else
+               up->port.type = PORT_16650V2;
+}
+
+/*
+ * We detected a chip without a FIFO.  Only two fall into
+ * this category - the original 8250 and the 16450.  The
+ * 16450 has a scratch register (accessible with LCR=0)
+ */
+static void autoconfig_8250(struct uart_8250_port *up)
+{
+       unsigned char scratch, status1, status2;
+
+       up->port.type = PORT_8250;
+
+       scratch = serial_in(up, UART_SCR);
+       serial_outp(up, UART_SCR, 0xa5);
+       status1 = serial_in(up, UART_SCR);
+       serial_outp(up, UART_SCR, 0x5a);
+       status2 = serial_in(up, UART_SCR);
+       serial_outp(up, UART_SCR, scratch);
+
+       if (status1 == 0xa5 && status2 == 0x5a)
+               up->port.type = PORT_16450;
+}
+
+static int broken_efr(struct uart_8250_port *up)
+{
+       /*
+        * Exar ST16C2550 "A2" devices incorrectly detect as
+        * having an EFR, and report an ID of 0x0201.  See
+        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html 
+        */
+       if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
+               return 1;
+
+       return 0;
+}
+
+static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+{
+       unsigned char status;
+
+       status = serial_in(up, 0x04); /* EXCR2 */
+#define PRESL(x) ((x) & 0x30)
+       if (PRESL(status) == 0x10) {
+               /* already in high speed mode */
+               return 0;
+       } else {
+               status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+               status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
+               serial_outp(up, 0x04, status);
+       }
+       return 1;
+}
+
+/*
+ * We know that the chip has FIFOs.  Does it have an EFR?  The
+ * EFR is located in the same register position as the IIR and
+ * we know the top two bits of the IIR are currently set.  The
+ * EFR should contain zero.  Try to read the EFR.
+ */
+static void autoconfig_16550a(struct uart_8250_port *up)
+{
+       unsigned char status1, status2;
+       unsigned int iersave;
+
+       up->port.type = PORT_16550A;
+       up->capabilities |= UART_CAP_FIFO;
+
+       /*
+        * Check for presence of the EFR when DLAB is set.
+        * Only ST16C650V1 UARTs pass this test.
+        */
+       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       if (serial_in(up, UART_EFR) == 0) {
+               serial_outp(up, UART_EFR, 0xA8);
+               if (serial_in(up, UART_EFR) != 0) {
+                       DEBUG_AUTOCONF("EFRv1 ");
+                       up->port.type = PORT_16650;
+                       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+               } else {
+                       DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+               }
+               serial_outp(up, UART_EFR, 0);
+               return;
+       }
+
+       /*
+        * Maybe it requires 0xbf to be written to the LCR.
+        * (other ST16C650V2 UARTs, TI16C752A, etc)
+        */
+       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
+               DEBUG_AUTOCONF("EFRv2 ");
+               autoconfig_has_efr(up);
+               return;
+       }
+
+       /*
+        * Check for a National Semiconductor SuperIO chip.
+        * Attempt to switch to bank 2, read the value of the LOOP bit
+        * from EXCR1. Switch back to bank 0, change it in MCR. Then
+        * switch back to bank 2, read it from EXCR1 again and check
+        * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
+        */
+       serial_outp(up, UART_LCR, 0);
+       status1 = serial_in(up, UART_MCR);
+       serial_outp(up, UART_LCR, 0xE0);
+       status2 = serial_in(up, 0x02); /* EXCR1 */
+
+       if (!((status2 ^ status1) & UART_MCR_LOOP)) {
+               serial_outp(up, UART_LCR, 0);
+               serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
+               serial_outp(up, UART_LCR, 0xE0);
+               status2 = serial_in(up, 0x02); /* EXCR1 */
+               serial_outp(up, UART_LCR, 0);
+               serial_outp(up, UART_MCR, status1);
+
+               if ((status2 ^ status1) & UART_MCR_LOOP) {
+                       unsigned short quot;
+
+                       serial_outp(up, UART_LCR, 0xE0);
+
+                       quot = serial_dl_read(up);
+                       quot <<= 3;
+
+                       if (ns16550a_goto_highspeed(up))
+                               serial_dl_write(up, quot);
+
+                       serial_outp(up, UART_LCR, 0);
+
+                       up->port.uartclk = 921600*16;
+                       up->port.type = PORT_NS16550A;
+                       up->capabilities |= UART_NATSEMI;
+                       return;
+               }
+       }
+
+       /*
+        * No EFR.  Try to detect a TI16750, which only sets bit 5 of
+        * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
+        * Try setting it with and without DLAB set.  Cheap clones
+        * set bit 5 without DLAB set.
+        */
+       serial_outp(up, UART_LCR, 0);
+       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+       status1 = serial_in(up, UART_IIR) >> 5;
+       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+       status2 = serial_in(up, UART_IIR) >> 5;
+       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       serial_outp(up, UART_LCR, 0);
+
+       DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
+
+       if (status1 == 6 && status2 == 7) {
+               up->port.type = PORT_16750;
+               up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
+               return;
+       }
+
+       /*
+        * Try writing and reading the UART_IER_UUE bit (b6).
+        * If it works, this is probably one of the Xscale platform's
+        * internal UARTs.
+        * We're going to explicitly set the UUE bit to 0 before
+        * trying to write and read a 1 just to make sure it's not
+        * already a 1 and maybe locked there before we even start start.
+        */
+       iersave = serial_in(up, UART_IER);
+       serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
+       if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+               /*
+                * OK it's in a known zero state, try writing and reading
+                * without disturbing the current state of the other bits.
+                */
+               serial_outp(up, UART_IER, iersave | UART_IER_UUE);
+               if (serial_in(up, UART_IER) & UART_IER_UUE) {
+                       /*
+                        * It's an Xscale.
+                        * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+                        */
+                       DEBUG_AUTOCONF("Xscale ");
+                       up->port.type = PORT_XSCALE;
+                       up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
+                       return;
+               }
+       } else {
+               /*
+                * If we got here we couldn't force the IER_UUE bit to 0.
+                * Log it and continue.
+                */
+               DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+       }
+       serial_outp(up, UART_IER, iersave);
+
+       /*
+        * Exar uarts have EFR in a weird location
+        */
+       if (up->port.flags & UPF_EXAR_EFR) {
+               up->port.type = PORT_XR17D15X;
+               up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
+       }
+
+       /*
+        * We distinguish between 16550A and U6 16550A by counting
+        * how many bytes are in the FIFO.
+        */
+       if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
+               up->port.type = PORT_U6_16550A;
+               up->capabilities |= UART_CAP_AFE;
+       }
+}
+
+/*
+ * This routine is called by rs_init() to initialize a specific serial
+ * port.  It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A.  The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+{
+       unsigned char status1, scratch, scratch2, scratch3;
+       unsigned char save_lcr, save_mcr;
+       unsigned long flags;
+
+       if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
+               return;
+
+       DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
+                      serial_index(&up->port), up->port.iobase, up->port.membase);
+
+       /*
+        * We really do need global IRQs disabled here - we're going to
+        * be frobbing the chips IRQ enable register to see if it exists.
+        */
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       up->capabilities = 0;
+       up->bugs = 0;
+
+       if (!(up->port.flags & UPF_BUGGY_UART)) {
+               /*
+                * Do a simple existence test first; if we fail this,
+                * there's no point trying anything else.
+                *
+                * 0x80 is used as a nonsense port to prevent against
+                * false positives due to ISA bus float.  The
+                * assumption is that 0x80 is a non-existent port;
+                * which should be safe since include/asm/io.h also
+                * makes this assumption.
+                *
+                * Note: this is safe as long as MCR bit 4 is clear
+                * and the device is in "PC" mode.
+                */
+               scratch = serial_inp(up, UART_IER);
+               serial_outp(up, UART_IER, 0);
+#ifdef __i386__
+               outb(0xff, 0x080);
+#endif
+               /*
+                * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+                * 16C754B) allow only to modify them if an EFR bit is set.
+                */
+               scratch2 = serial_inp(up, UART_IER) & 0x0f;
+               serial_outp(up, UART_IER, 0x0F);
+#ifdef __i386__
+               outb(0, 0x080);
+#endif
+               scratch3 = serial_inp(up, UART_IER) & 0x0f;
+               serial_outp(up, UART_IER, scratch);
+               if (scratch2 != 0 || scratch3 != 0x0F) {
+                       /*
+                        * We failed; there's nothing here
+                        */
+                       DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
+                                      scratch2, scratch3);
+                       goto out;
+               }
+       }
+
+       save_mcr = serial_in(up, UART_MCR);
+       save_lcr = serial_in(up, UART_LCR);
+
+       /*
+        * Check to see if a UART is really there.  Certain broken
+        * internal modems based on the Rockwell chipset fail this
+        * test, because they apparently don't implement the loopback
+        * test mode.  So this test is skipped on the COM 1 through
+        * COM 4 ports.  This *should* be safe, since no board
+        * manufacturer would be stupid enough to design a board
+        * that conflicts with COM 1-4 --- we hope!
+        */
+       if (!(up->port.flags & UPF_SKIP_TEST)) {
+               serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
+               status1 = serial_inp(up, UART_MSR) & 0xF0;
+               serial_outp(up, UART_MCR, save_mcr);
+               if (status1 != 0x90) {
+                       DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+                                      status1);
+                       goto out;
+               }
+       }
+
+       /*
+        * We're pretty sure there's a port here.  Lets find out what
+        * type of port it is.  The IIR top two bits allows us to find
+        * out if it's 8250 or 16450, 16550, 16550A or later.  This
+        * determines what we test for next.
+        *
+        * We also initialise the EFR (if any) to zero for later.  The
+        * EFR occupies the same register location as the FCR and IIR.
+        */
+       serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       serial_outp(up, UART_EFR, 0);
+       serial_outp(up, UART_LCR, 0);
+
+       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       scratch = serial_in(up, UART_IIR) >> 6;
+
+       DEBUG_AUTOCONF("iir=%d ", scratch);
+
+       switch (scratch) {
+       case 0:
+               autoconfig_8250(up);
+               break;
+       case 1:
+               up->port.type = PORT_UNKNOWN;
+               break;
+       case 2:
+               up->port.type = PORT_16550;
+               break;
+       case 3:
+               autoconfig_16550a(up);
+               break;
+       }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+       /*
+        * Only probe for RSA ports if we got the region.
+        */
+       if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
+               int i;
+
+               for (i = 0 ; i < probe_rsa_count; ++i) {
+                       if (probe_rsa[i] == up->port.iobase &&
+                           __enable_rsa(up)) {
+                               up->port.type = PORT_RSA;
+                               break;
+                       }
+               }
+       }
+#endif
+
+       serial_outp(up, UART_LCR, save_lcr);
+
+       if (up->capabilities != uart_config[up->port.type].flags) {
+               printk(KERN_WARNING
+                      "ttyS%d: detected caps %08x should be %08x\n",
+                      serial_index(&up->port), up->capabilities,
+                      uart_config[up->port.type].flags);
+       }
+
+       up->port.fifosize = uart_config[up->port.type].fifo_size;
+       up->capabilities = uart_config[up->port.type].flags;
+       up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+
+       if (up->port.type == PORT_UNKNOWN)
+               goto out;
+
+       /*
+        * Reset the UART.
+        */
+#ifdef CONFIG_SERIAL_8250_RSA
+       if (up->port.type == PORT_RSA)
+               serial_outp(up, UART_RSA_FRR, 0);
+#endif
+       serial_outp(up, UART_MCR, save_mcr);
+       serial8250_clear_fifos(up);
+       serial_in(up, UART_RX);
+       if (up->capabilities & UART_CAP_UUE)
+               serial_outp(up, UART_IER, UART_IER_UUE);
+       else
+               serial_outp(up, UART_IER, 0);
+
+ out:
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
+}
+
+static void autoconfig_irq(struct uart_8250_port *up)
+{
+       unsigned char save_mcr, save_ier;
+       unsigned char save_ICP = 0;
+       unsigned int ICP = 0;
+       unsigned long irqs;
+       int irq;
+
+       if (up->port.flags & UPF_FOURPORT) {
+               ICP = (up->port.iobase & 0xfe0) | 0x1f;
+               save_ICP = inb_p(ICP);
+               outb_p(0x80, ICP);
+               (void) inb_p(ICP);
+       }
+
+       /* forget possible initially masked and pending IRQ */
+       probe_irq_off(probe_irq_on());
+       save_mcr = serial_inp(up, UART_MCR);
+       save_ier = serial_inp(up, UART_IER);
+       serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+       irqs = probe_irq_on();
+       serial_outp(up, UART_MCR, 0);
+       udelay(10);
+       if (up->port.flags & UPF_FOURPORT) {
+               serial_outp(up, UART_MCR,
+                           UART_MCR_DTR | UART_MCR_RTS);
+       } else {
+               serial_outp(up, UART_MCR,
+                           UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+       }
+       serial_outp(up, UART_IER, 0x0f);        /* enable all intrs */
+       (void)serial_inp(up, UART_LSR);
+       (void)serial_inp(up, UART_RX);
+       (void)serial_inp(up, UART_IIR);
+       (void)serial_inp(up, UART_MSR);
+       serial_outp(up, UART_TX, 0xFF);
+       udelay(20);
+       irq = probe_irq_off(irqs);
+
+       serial_outp(up, UART_MCR, save_mcr);
+       serial_outp(up, UART_IER, save_ier);
+
+       if (up->port.flags & UPF_FOURPORT)
+               outb_p(save_ICP, ICP);
+
+       up->port.irq = (irq > 0) ? irq : 0;
+}
+
+static inline void __stop_tx(struct uart_8250_port *p)
+{
+       if (p->ier & UART_IER_THRI) {
+               p->ier &= ~UART_IER_THRI;
+               serial_out(p, UART_IER, p->ier);
+       }
+}
+
+static void serial8250_stop_tx(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       __stop_tx(up);
+
+       /*
+        * We really want to stop the transmitter from sending.
+        */
+       if (up->port.type == PORT_16C950) {
+               up->acr |= UART_ACR_TXDIS;
+               serial_icr_write(up, UART_ACR, up->acr);
+       }
+}
+
+static void serial8250_start_tx(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       if (!(up->ier & UART_IER_THRI)) {
+               up->ier |= UART_IER_THRI;
+               serial_out(up, UART_IER, up->ier);
+
+               if (up->bugs & UART_BUG_TXEN) {
+                       unsigned char lsr;
+                       lsr = serial_in(up, UART_LSR);
+                       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+                       if ((up->port.type == PORT_RM9000) ?
+                               (lsr & UART_LSR_THRE) :
+                               (lsr & UART_LSR_TEMT))
+                               serial8250_tx_chars(up);
+               }
+       }
+
+       /*
+        * Re-enable the transmitter if we disabled it.
+        */
+       if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
+               up->acr &= ~UART_ACR_TXDIS;
+               serial_icr_write(up, UART_ACR, up->acr);
+       }
+}
+
+static void serial8250_stop_rx(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       up->ier &= ~UART_IER_RLSI;
+       up->port.read_status_mask &= ~UART_LSR_DR;
+       serial_out(up, UART_IER, up->ier);
+}
+
+static void serial8250_enable_ms(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       /* no MSR capabilities */
+       if (up->bugs & UART_BUG_NOMSR)
+               return;
+
+       up->ier |= UART_IER_MSI;
+       serial_out(up, UART_IER, up->ier);
+}
+
+/*
+ * Clear the Tegra rx fifo after a break
+ *
+ * FIXME: This needs to become a port specific callback once we have a
+ * framework for this
+ */
+static void clear_rx_fifo(struct uart_8250_port *up)
+{
+       unsigned int status, tmout = 10000;
+       do {
+               status = serial_in(up, UART_LSR);
+               if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+                       status = serial_in(up, UART_RX);
+               else
+                       break;
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       } while (1);
+}
+
+/*
+ * serial8250_rx_chars: processes according to the passed in LSR
+ * value, and returns the remaining LSR bits not handled
+ * by this Rx routine.
+ */
+unsigned char
+serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+{
+       struct tty_struct *tty = up->port.state->port.tty;
+       unsigned char ch;
+       int max_count = 256;
+       char flag;
+
+       do {
+               if (likely(lsr & UART_LSR_DR))
+                       ch = serial_inp(up, UART_RX);
+               else
+                       /*
+                        * Intel 82571 has a Serial Over Lan device that will
+                        * set UART_LSR_BI without setting UART_LSR_DR when
+                        * it receives a break. To avoid reading from the
+                        * receive buffer without UART_LSR_DR bit set, we
+                        * just force the read character to be 0
+                        */
+                       ch = 0;
+
+               flag = TTY_NORMAL;
+               up->port.icount.rx++;
+
+               lsr |= up->lsr_saved_flags;
+               up->lsr_saved_flags = 0;
+
+               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+                       /*
+                        * For statistics only
+                        */
+                       if (lsr & UART_LSR_BI) {
+                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+                               up->port.icount.brk++;
+                               /*
+                                * If tegra port then clear the rx fifo to
+                                * accept another break/character.
+                                */
+                               if (up->port.type == PORT_TEGRA)
+                                       clear_rx_fifo(up);
+
+                               /*
+                                * We do the SysRQ and SAK checking
+                                * here because otherwise the break
+                                * may get masked by ignore_status_mask
+                                * or read_status_mask.
+                                */
+                               if (uart_handle_break(&up->port))
+                                       goto ignore_char;
+                       } else if (lsr & UART_LSR_PE)
+                               up->port.icount.parity++;
+                       else if (lsr & UART_LSR_FE)
+                               up->port.icount.frame++;
+                       if (lsr & UART_LSR_OE)
+                               up->port.icount.overrun++;
+
+                       /*
+                        * Mask off conditions which should be ignored.
+                        */
+                       lsr &= up->port.read_status_mask;
+
+                       if (lsr & UART_LSR_BI) {
+                               DEBUG_INTR("handling break....");
+                               flag = TTY_BREAK;
+                       } else if (lsr & UART_LSR_PE)
+                               flag = TTY_PARITY;
+                       else if (lsr & UART_LSR_FE)
+                               flag = TTY_FRAME;
+               }
+               if (uart_handle_sysrq_char(&up->port, ch))
+                       goto ignore_char;
+
+               uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+
+ignore_char:
+               lsr = serial_inp(up, UART_LSR);
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+       spin_unlock(&up->port.lock);
+       tty_flip_buffer_push(tty);
+       spin_lock(&up->port.lock);
+       return lsr;
+}
+EXPORT_SYMBOL_GPL(serial8250_rx_chars);
+
+void serial8250_tx_chars(struct uart_8250_port *up)
+{
+       struct circ_buf *xmit = &up->port.state->xmit;
+       int count;
+
+       if (up->port.x_char) {
+               serial_outp(up, UART_TX, up->port.x_char);
+               up->port.icount.tx++;
+               up->port.x_char = 0;
+               return;
+       }
+       if (uart_tx_stopped(&up->port)) {
+               serial8250_stop_tx(&up->port);
+               return;
+       }
+       if (uart_circ_empty(xmit)) {
+               __stop_tx(up);
+               return;
+       }
+
+       count = up->tx_loadsz;
+       do {
+               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               up->port.icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+       } while (--count > 0);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&up->port);
+
+       DEBUG_INTR("THRE...");
+
+       if (uart_circ_empty(xmit))
+               __stop_tx(up);
+}
+EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+
+unsigned int serial8250_modem_status(struct uart_8250_port *up)
+{
+       unsigned int status = serial_in(up, UART_MSR);
+
+       status |= up->msr_saved_flags;
+       up->msr_saved_flags = 0;
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+           up->port.state != NULL) {
+               if (status & UART_MSR_TERI)
+                       up->port.icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       up->port.icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+               if (status & UART_MSR_DCTS)
+                       uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+
+               wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+       }
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(serial8250_modem_status);
+
+/*
+ * This handles the interrupt from one port.
+ */
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+       unsigned char status;
+       unsigned long flags;
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       if (iir & UART_IIR_NO_INT)
+               return 0;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       status = serial_inp(up, UART_LSR);
+
+       DEBUG_INTR("status = %x...", status);
+
+       if (status & (UART_LSR_DR | UART_LSR_BI))
+               status = serial8250_rx_chars(up, status);
+       serial8250_modem_status(up);
+       if (status & UART_LSR_THRE)
+               serial8250_tx_chars(up);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+static int serial8250_default_handle_irq(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned int iir = serial_in(up, UART_IIR);
+
+       return serial8250_handle_irq(port, iir);
+}
+
+/*
+ * This is the serial driver's interrupt routine.
+ *
+ * Arjan thinks the old way was overly complex, so it got simplified.
+ * Alan disagrees, saying that need the complexity to handle the weird
+ * nature of ISA shared interrupts.  (This is a special exception.)
+ *
+ * In order to handle ISA shared interrupts properly, we need to check
+ * that all ports have been serviced, and therefore the ISA interrupt
+ * line has been de-asserted.
+ *
+ * This means we need to loop through all ports. checking that they
+ * don't have an interrupt pending.
+ */
+static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
+{
+       struct irq_info *i = dev_id;
+       struct list_head *l, *end = NULL;
+       int pass_counter = 0, handled = 0;
+
+       DEBUG_INTR("serial8250_interrupt(%d)...", irq);
+
+       spin_lock(&i->lock);
+
+       l = i->head;
+       do {
+               struct uart_8250_port *up;
+               struct uart_port *port;
+               bool skip;
+
+               up = list_entry(l, struct uart_8250_port, list);
+               port = &up->port;
+               skip = pass_counter && up->port.flags & UPF_IIR_ONCE;
+
+               if (!skip && port->handle_irq(port)) {
+                       handled = 1;
+                       end = NULL;
+               } else if (end == NULL)
+                       end = l;
+
+               l = l->next;
+
+               if (l == i->head && pass_counter++ > PASS_LIMIT) {
+                       /* If we hit this, we're dead. */
+                       printk_ratelimited(KERN_ERR
+                               "serial8250: too much work for irq%d\n", irq);
+                       break;
+               }
+       } while (l != end);
+
+       spin_unlock(&i->lock);
+
+       DEBUG_INTR("end.\n");
+
+       return IRQ_RETVAL(handled);
+}
+
+/*
+ * To support ISA shared interrupts, we need to have one interrupt
+ * handler that ensures that the IRQ line has been deasserted
+ * before returning.  Failing to do this will result in the IRQ
+ * line being stuck active, and, since ISA irqs are edge triggered,
+ * no more IRQs will be seen.
+ */
+static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
+{
+       spin_lock_irq(&i->lock);
+
+       if (!list_empty(i->head)) {
+               if (i->head == &up->list)
+                       i->head = i->head->next;
+               list_del(&up->list);
+       } else {
+               BUG_ON(i->head != &up->list);
+               i->head = NULL;
+       }
+       spin_unlock_irq(&i->lock);
+       /* List empty so throw away the hash node */
+       if (i->head == NULL) {
+               hlist_del(&i->node);
+               kfree(i);
+       }
+}
+
+static int serial_link_irq_chain(struct uart_8250_port *up)
+{
+       struct hlist_head *h;
+       struct hlist_node *n;
+       struct irq_info *i;
+       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+
+       mutex_lock(&hash_mutex);
+
+       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+       hlist_for_each(n, h) {
+               i = hlist_entry(n, struct irq_info, node);
+               if (i->irq == up->port.irq)
+                       break;
+       }
+
+       if (n == NULL) {
+               i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+               if (i == NULL) {
+                       mutex_unlock(&hash_mutex);
+                       return -ENOMEM;
+               }
+               spin_lock_init(&i->lock);
+               i->irq = up->port.irq;
+               hlist_add_head(&i->node, h);
+       }
+       mutex_unlock(&hash_mutex);
+
+       spin_lock_irq(&i->lock);
+
+       if (i->head) {
+               list_add(&up->list, i->head);
+               spin_unlock_irq(&i->lock);
+
+               ret = 0;
+       } else {
+               INIT_LIST_HEAD(&up->list);
+               i->head = &up->list;
+               spin_unlock_irq(&i->lock);
+               irq_flags |= up->port.irqflags;
+               ret = request_irq(up->port.irq, serial8250_interrupt,
+                                 irq_flags, "serial", i);
+               if (ret < 0)
+                       serial_do_unlink(i, up);
+       }
+
+       return ret;
+}
+
+static void serial_unlink_irq_chain(struct uart_8250_port *up)
+{
+       struct irq_info *i;
+       struct hlist_node *n;
+       struct hlist_head *h;
+
+       mutex_lock(&hash_mutex);
+
+       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+       hlist_for_each(n, h) {
+               i = hlist_entry(n, struct irq_info, node);
+               if (i->irq == up->port.irq)
+                       break;
+       }
+
+       BUG_ON(n == NULL);
+       BUG_ON(i->head == NULL);
+
+       if (list_empty(i->head))
+               free_irq(up->port.irq, i);
+
+       serial_do_unlink(i, up);
+       mutex_unlock(&hash_mutex);
+}
+
+/*
+ * This function is used to handle ports that do not have an
+ * interrupt.  This doesn't work very well for 16450's, but gives
+ * barely passable results for a 16550A.  (Although at the expense
+ * of much CPU overhead).
+ */
+static void serial8250_timeout(unsigned long data)
+{
+       struct uart_8250_port *up = (struct uart_8250_port *)data;
+
+       up->port.handle_irq(&up->port);
+       mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
+}
+
+static void serial8250_backup_timeout(unsigned long data)
+{
+       struct uart_8250_port *up = (struct uart_8250_port *)data;
+       unsigned int iir, ier = 0, lsr;
+       unsigned long flags;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       /*
+        * Must disable interrupts or else we risk racing with the interrupt
+        * based handler.
+        */
+       if (is_real_interrupt(up->port.irq)) {
+               ier = serial_in(up, UART_IER);
+               serial_out(up, UART_IER, 0);
+       }
+
+       iir = serial_in(up, UART_IIR);
+
+       /*
+        * This should be a safe test for anyone who doesn't trust the
+        * IIR bits on their UART, but it's specifically designed for
+        * the "Diva" UART used on the management processor on many HP
+        * ia64 and parisc boxes.
+        */
+       lsr = serial_in(up, UART_LSR);
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+       if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+           (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
+           (lsr & UART_LSR_THRE)) {
+               iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+               iir |= UART_IIR_THRI;
+       }
+
+       if (!(iir & UART_IIR_NO_INT))
+               serial8250_tx_chars(up);
+
+       if (is_real_interrupt(up->port.irq))
+               serial_out(up, UART_IER, ier);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       /* Standard timer interval plus 0.2s to keep the port running */
+       mod_timer(&up->timer,
+               jiffies + uart_poll_timeout(&up->port) + HZ / 5);
+}
+
+static unsigned int serial8250_tx_empty(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned long flags;
+       unsigned int lsr;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       lsr = serial_in(up, UART_LSR);
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int serial8250_get_mctrl(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned int status;
+       unsigned int ret;
+
+       status = serial8250_modem_status(up);
+
+       ret = 0;
+       if (status & UART_MSR_DCD)
+               ret |= TIOCM_CAR;
+       if (status & UART_MSR_RI)
+               ret |= TIOCM_RNG;
+       if (status & UART_MSR_DSR)
+               ret |= TIOCM_DSR;
+       if (status & UART_MSR_CTS)
+               ret |= TIOCM_CTS;
+       return ret;
+}
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned char mcr = 0;
+
+       if (mctrl & TIOCM_RTS)
+               mcr |= UART_MCR_RTS;
+       if (mctrl & TIOCM_DTR)
+               mcr |= UART_MCR_DTR;
+       if (mctrl & TIOCM_OUT1)
+               mcr |= UART_MCR_OUT1;
+       if (mctrl & TIOCM_OUT2)
+               mcr |= UART_MCR_OUT2;
+       if (mctrl & TIOCM_LOOP)
+               mcr |= UART_MCR_LOOP;
+
+       mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
+
+       serial_out(up, UART_MCR, mcr);
+}
+
+static void serial8250_break_ctl(struct uart_port *port, int break_state)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       if (break_state == -1)
+               up->lcr |= UART_LCR_SBC;
+       else
+               up->lcr &= ~UART_LCR_SBC;
+       serial_out(up, UART_LCR, up->lcr);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+/*
+ *     Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+       unsigned int status, tmout = 10000;
+
+       /* Wait up to 10ms for the character(s) to be sent. */
+       for (;;) {
+               status = serial_in(up, UART_LSR);
+
+               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
+
+               if ((status & bits) == bits)
+                       break;
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       }
+
+       /* Wait up to 1s for flow control if necessary */
+       if (up->port.flags & UPF_CONS_FLOW) {
+               unsigned int tmout;
+               for (tmout = 1000000; tmout; tmout--) {
+                       unsigned int msr = serial_in(up, UART_MSR);
+                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+                       if (msr & UART_MSR_CTS)
+                               break;
+                       udelay(1);
+                       touch_nmi_watchdog();
+               }
+       }
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial8250_get_poll_char(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned char lsr = serial_inp(up, UART_LSR);
+
+       if (!(lsr & UART_LSR_DR))
+               return NO_POLL_CHAR;
+
+       return serial_inp(up, UART_RX);
+}
+
+
+static void serial8250_put_poll_char(struct uart_port *port,
+                        unsigned char c)
+{
+       unsigned int ier;
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       /*
+        *      First save the IER then disable the interrupts
+        */
+       ier = serial_in(up, UART_IER);
+       if (up->capabilities & UART_CAP_UUE)
+               serial_out(up, UART_IER, UART_IER_UUE);
+       else
+               serial_out(up, UART_IER, 0);
+
+       wait_for_xmitr(up, BOTH_EMPTY);
+       /*
+        *      Send the character out.
+        *      If a LF, also do CR...
+        */
+       serial_out(up, UART_TX, c);
+       if (c == 10) {
+               wait_for_xmitr(up, BOTH_EMPTY);
+               serial_out(up, UART_TX, 13);
+       }
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore the IER
+        */
+       wait_for_xmitr(up, BOTH_EMPTY);
+       serial_out(up, UART_IER, ier);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+static int serial8250_startup(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned long flags;
+       unsigned char lsr, iir;
+       int retval;
+
+       up->port.fifosize = uart_config[up->port.type].fifo_size;
+       up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+       up->capabilities = uart_config[up->port.type].flags;
+       up->mcr = 0;
+
+       if (up->port.iotype != up->cur_iotype)
+               set_io_from_upio(port);
+
+       if (up->port.type == PORT_16C950) {
+               /* Wake up and initialize UART */
+               up->acr = 0;
+               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+               serial_outp(up, UART_EFR, UART_EFR_ECB);
+               serial_outp(up, UART_IER, 0);
+               serial_outp(up, UART_LCR, 0);
+               serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+               serial_outp(up, UART_EFR, UART_EFR_ECB);
+               serial_outp(up, UART_LCR, 0);
+       }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+       /*
+        * If this is an RSA port, see if we can kick it up to the
+        * higher speed clock.
+        */
+       enable_rsa(up);
+#endif
+
+       /*
+        * Clear the FIFO buffers and disable them.
+        * (they will be reenabled in set_termios())
+        */
+       serial8250_clear_fifos(up);
+
+       /*
+        * Clear the interrupt registers.
+        */
+       (void) serial_inp(up, UART_LSR);
+       (void) serial_inp(up, UART_RX);
+       (void) serial_inp(up, UART_IIR);
+       (void) serial_inp(up, UART_MSR);
+
+       /*
+        * At this point, there's no way the LSR could still be 0xff;
+        * if it is, then bail out, because there's likely no UART
+        * here.
+        */
+       if (!(up->port.flags & UPF_BUGGY_UART) &&
+           (serial_inp(up, UART_LSR) == 0xff)) {
+               printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+                                  serial_index(&up->port));
+               return -ENODEV;
+       }
+
+       /*
+        * For a XR16C850, we need to set the trigger levels
+        */
+       if (up->port.type == PORT_16850) {
+               unsigned char fctr;
+
+               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+               fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+               serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+               serial_outp(up, UART_TRG, UART_TRG_96);
+               serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+               serial_outp(up, UART_TRG, UART_TRG_96);
+
+               serial_outp(up, UART_LCR, 0);
+       }
+
+       if (is_real_interrupt(up->port.irq)) {
+               unsigned char iir1;
+               /*
+                * Test for UARTs that do not reassert THRE when the
+                * transmitter is idle and the interrupt has already
+                * been cleared.  Real 16550s should always reassert
+                * this interrupt whenever the transmitter is idle and
+                * the interrupt is enabled.  Delays are necessary to
+                * allow register changes to become visible.
+                */
+               spin_lock_irqsave(&up->port.lock, flags);
+               if (up->port.irqflags & IRQF_SHARED)
+                       disable_irq_nosync(up->port.irq);
+
+               wait_for_xmitr(up, UART_LSR_THRE);
+               serial_out_sync(up, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow THRE to set */
+               iir1 = serial_in(up, UART_IIR);
+               serial_out(up, UART_IER, 0);
+               serial_out_sync(up, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow a working UART time to re-assert THRE */
+               iir = serial_in(up, UART_IIR);
+               serial_out(up, UART_IER, 0);
+
+               if (up->port.irqflags & IRQF_SHARED)
+                       enable_irq(up->port.irq);
+               spin_unlock_irqrestore(&up->port.lock, flags);
+
+               /*
+                * If the interrupt is not reasserted, setup a timer to
+                * kick the UART on a regular basis.
+                */
+               if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
+                       up->bugs |= UART_BUG_THRE;
+                       pr_debug("ttyS%d - using backup timer\n",
+                                serial_index(port));
+               }
+       }
+
+       /*
+        * The above check will only give an accurate result the first time
+        * the port is opened so this value needs to be preserved.
+        */
+       if (up->bugs & UART_BUG_THRE) {
+               up->timer.function = serial8250_backup_timeout;
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies +
+                       uart_poll_timeout(port) + HZ / 5);
+       }
+
+       /*
+        * If the "interrupt" for this port doesn't correspond with any
+        * hardware interrupt, we use a timer-based system.  The original
+        * driver used to do this with IRQ0.
+        */
+       if (!is_real_interrupt(up->port.irq)) {
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+       } else {
+               retval = serial_link_irq_chain(up);
+               if (retval)
+                       return retval;
+       }
+
+       /*
+        * Now, initialize the UART
+        */
+       serial_outp(up, UART_LCR, UART_LCR_WLEN8);
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       if (up->port.flags & UPF_FOURPORT) {
+               if (!is_real_interrupt(up->port.irq))
+                       up->port.mctrl |= TIOCM_OUT1;
+       } else
+               /*
+                * Most PC uarts need OUT2 raised to enable interrupts.
+                */
+               if (is_real_interrupt(up->port.irq))
+                       up->port.mctrl |= TIOCM_OUT2;
+
+       serial8250_set_mctrl(&up->port, up->port.mctrl);
+
+       /* Serial over Lan (SoL) hack:
+          Intel 8257x Gigabit ethernet chips have a
+          16550 emulation, to be used for Serial Over Lan.
+          Those chips take a longer time than a normal
+          serial device to signalize that a transmission
+          data was queued. Due to that, the above test generally
+          fails. One solution would be to delay the reading of
+          iir. However, this is not reliable, since the timeout
+          is variable. So, let's just don't test if we receive
+          TX irq. This way, we'll never enable UART_BUG_TXEN.
+        */
+       if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
+               goto dont_test_tx_en;
+
+       /*
+        * Do a quick test to see if we receive an
+        * interrupt when we enable the TX irq.
+        */
+       serial_outp(up, UART_IER, UART_IER_THRI);
+       lsr = serial_in(up, UART_LSR);
+       iir = serial_in(up, UART_IIR);
+       serial_outp(up, UART_IER, 0);
+
+       if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+               if (!(up->bugs & UART_BUG_TXEN)) {
+                       up->bugs |= UART_BUG_TXEN;
+                       pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+                                serial_index(port));
+               }
+       } else {
+               up->bugs &= ~UART_BUG_TXEN;
+       }
+
+dont_test_tx_en:
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       /*
+        * Clear the interrupt registers again for luck, and clear the
+        * saved flags to avoid getting false values from polling
+        * routines or the previous session.
+        */
+       serial_inp(up, UART_LSR);
+       serial_inp(up, UART_RX);
+       serial_inp(up, UART_IIR);
+       serial_inp(up, UART_MSR);
+       up->lsr_saved_flags = 0;
+       up->msr_saved_flags = 0;
+
+       /*
+        * Finally, enable interrupts.  Note: Modem status interrupts
+        * are set via set_termios(), which will be occurring imminently
+        * anyway, so we don't enable them here.
+        */
+       up->ier = UART_IER_RLSI | UART_IER_RDI;
+       serial_outp(up, UART_IER, up->ier);
+
+       if (up->port.flags & UPF_FOURPORT) {
+               unsigned int icp;
+               /*
+                * Enable interrupts on the AST Fourport board
+                */
+               icp = (up->port.iobase & 0xfe0) | 0x01f;
+               outb_p(0x80, icp);
+               (void) inb_p(icp);
+       }
+
+       return 0;
+}
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned long flags;
+
+       /*
+        * Disable interrupts from this port
+        */
+       up->ier = 0;
+       serial_outp(up, UART_IER, 0);
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       if (up->port.flags & UPF_FOURPORT) {
+               /* reset interrupts on the AST Fourport board */
+               inb((up->port.iobase & 0xfe0) | 0x1f);
+               up->port.mctrl |= TIOCM_OUT1;
+       } else
+               up->port.mctrl &= ~TIOCM_OUT2;
+
+       serial8250_set_mctrl(&up->port, up->port.mctrl);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       /*
+        * Disable break condition and FIFOs
+        */
+       serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
+       serial8250_clear_fifos(up);
+
+#ifdef CONFIG_SERIAL_8250_RSA
+       /*
+        * Reset the RSA board back to 115kbps compat mode.
+        */
+       disable_rsa(up);
+#endif
+
+       /*
+        * Read data port to reset things, and then unlink from
+        * the IRQ chain.
+        */
+       (void) serial_in(up, UART_RX);
+
+       del_timer_sync(&up->timer);
+       up->timer.function = serial8250_timeout;
+       if (is_real_interrupt(up->port.irq))
+               serial_unlink_irq_chain(up);
+}
+
+static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
+{
+       unsigned int quot;
+
+       /*
+        * Handle magic divisors for baud rates above baud_base on
+        * SMSC SuperIO chips.
+        */
+       if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+           baud == (port->uartclk/4))
+               quot = 0x8001;
+       else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+                baud == (port->uartclk/8))
+               quot = 0x8002;
+       else
+               quot = uart_get_divisor(port, baud);
+
+       return quot;
+}
+
+void
+serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+                         struct ktermios *old)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned char cval, fcr = 0;
+       unsigned long flags;
+       unsigned int baud, quot;
+
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               cval = UART_LCR_WLEN5;
+               break;
+       case CS6:
+               cval = UART_LCR_WLEN6;
+               break;
+       case CS7:
+               cval = UART_LCR_WLEN7;
+               break;
+       default:
+       case CS8:
+               cval = UART_LCR_WLEN8;
+               break;
+       }
+
+       if (termios->c_cflag & CSTOPB)
+               cval |= UART_LCR_STOP;
+       if (termios->c_cflag & PARENB)
+               cval |= UART_LCR_PARITY;
+       if (!(termios->c_cflag & PARODD))
+               cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+       if (termios->c_cflag & CMSPAR)
+               cval |= UART_LCR_SPAR;
+#endif
+
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+       baud = uart_get_baud_rate(port, termios, old,
+                                 port->uartclk / 16 / 0xffff,
+                                 port->uartclk / 16);
+       quot = serial8250_get_divisor(port, baud);
+
+       /*
+        * Oxford Semi 952 rev B workaround
+        */
+       if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
+               quot++;
+
+       if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
+               if (baud < 2400)
+                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+               else
+                       fcr = uart_config[up->port.type].fcr;
+       }
+
+       /*
+        * MCR-based auto flow control.  When AFE is enabled, RTS will be
+        * deasserted when the receive FIFO contains more characters than
+        * the trigger, or the MCR RTS bit is cleared.  In the case where
+        * the remote UART is not using CTS auto flow control, we must
+        * have sufficient FIFO entries for the latency of the remote
+        * UART to respond.  IOW, at least 32 bytes of FIFO.
+        */
+       if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
+               up->mcr &= ~UART_MCR_AFE;
+               if (termios->c_cflag & CRTSCTS)
+                       up->mcr |= UART_MCR_AFE;
+       }
+
+       /*
+        * Ok, we're now changing the port state.  Do it with
+        * interrupts disabled.
+        */
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+       if (termios->c_iflag & INPCK)
+               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+       if (termios->c_iflag & (BRKINT | PARMRK))
+               up->port.read_status_mask |= UART_LSR_BI;
+
+       /*
+        * Characteres to ignore
+        */
+       up->port.ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+       if (termios->c_iflag & IGNBRK) {
+               up->port.ignore_status_mask |= UART_LSR_BI;
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       up->port.ignore_status_mask |= UART_LSR_OE;
+       }
+
+       /*
+        * ignore all characters if CREAD is not set
+        */
+       if ((termios->c_cflag & CREAD) == 0)
+               up->port.ignore_status_mask |= UART_LSR_DR;
+
+       /*
+        * CTS flow control flag and modem status interrupts
+        */
+       up->ier &= ~UART_IER_MSI;
+       if (!(up->bugs & UART_BUG_NOMSR) &&
+                       UART_ENABLE_MS(&up->port, termios->c_cflag))
+               up->ier |= UART_IER_MSI;
+       if (up->capabilities & UART_CAP_UUE)
+               up->ier |= UART_IER_UUE;
+       if (up->capabilities & UART_CAP_RTOIE)
+               up->ier |= UART_IER_RTOIE;
+
+       serial_out(up, UART_IER, up->ier);
+
+       if (up->capabilities & UART_CAP_EFR) {
+               unsigned char efr = 0;
+               /*
+                * TI16C752/Startech hardware flow control.  FIXME:
+                * - TI16C752 requires control thresholds to be set.
+                * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
+                */
+               if (termios->c_cflag & CRTSCTS)
+                       efr |= UART_EFR_CTS;
+
+               serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+               if (up->port.flags & UPF_EXAR_EFR)
+                       serial_outp(up, UART_XR_EFR, efr);
+               else
+                       serial_outp(up, UART_EFR, efr);
+       }
+
+#ifdef CONFIG_ARCH_OMAP
+       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+       if (cpu_is_omap1510() && is_omap_port(up)) {
+               if (baud == 115200) {
+                       quot = 1;
+                       serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
+               } else
+                       serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
+       }
+#endif
+
+       if (up->capabilities & UART_NATSEMI) {
+               /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
+               serial_outp(up, UART_LCR, 0xe0);
+       } else {
+               serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+       }
+
+       serial_dl_write(up, quot);
+
+       /*
+        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+        * is written without DLAB set, this mode will be disabled.
+        */
+       if (up->port.type == PORT_16750)
+               serial_outp(up, UART_FCR, fcr);
+
+       serial_outp(up, UART_LCR, cval);                /* reset DLAB */
+       up->lcr = cval;                                 /* Save LCR */
+       if (up->port.type != PORT_16750) {
+               if (fcr & UART_FCR_ENABLE_FIFO) {
+                       /* emulated UARTs (Lucent Venus 167x) need two steps */
+                       serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+               }
+               serial_outp(up, UART_FCR, fcr);         /* set fcr */
+       }
+       serial8250_set_mctrl(&up->port, up->port.mctrl);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       /* Don't rewrite B0 */
+       if (tty_termios_baud_rate(termios))
+               tty_termios_encode_baud_rate(termios, baud, baud);
+}
+EXPORT_SYMBOL(serial8250_do_set_termios);
+
+static void
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
+{
+       if (port->set_termios)
+               port->set_termios(port, termios, old);
+       else
+               serial8250_do_set_termios(port, termios, old);
+}
+
+static void
+serial8250_set_ldisc(struct uart_port *port, int new)
+{
+       if (new == N_PPS) {
+               port->flags |= UPF_HARDPPS_CD;
+               serial8250_enable_ms(port);
+       } else
+               port->flags &= ~UPF_HARDPPS_CD;
+}
+
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+                     unsigned int oldstate)
+{
+       struct uart_8250_port *p =
+               container_of(port, struct uart_8250_port, port);
+
+       serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
+
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+             unsigned int oldstate)
+{
+       if (port->pm)
+               port->pm(port, state, oldstate);
+       else
+               serial8250_do_pm(port, state, oldstate);
+}
+
+static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+{
+       if (pt->port.iotype == UPIO_AU)
+               return 0x1000;
+#ifdef CONFIG_ARCH_OMAP
+       if (is_omap_port(pt))
+               return 0x16 << pt->port.regshift;
+#endif
+       return 8 << pt->port.regshift;
+}
+
+/*
+ * Resource handling.
+ */
+static int serial8250_request_std_resource(struct uart_8250_port *up)
+{
+       unsigned int size = serial8250_port_size(up);
+       int ret = 0;
+
+       switch (up->port.iotype) {
+       case UPIO_AU:
+       case UPIO_TSI:
+       case UPIO_MEM32:
+       case UPIO_MEM:
+               if (!up->port.mapbase)
+                       break;
+
+               if (!request_mem_region(up->port.mapbase, size, "serial")) {
+                       ret = -EBUSY;
+                       break;
+               }
+
+               if (up->port.flags & UPF_IOREMAP) {
+                       up->port.membase = ioremap_nocache(up->port.mapbase,
+                                                                       size);
+                       if (!up->port.membase) {
+                               release_mem_region(up->port.mapbase, size);
+                               ret = -ENOMEM;
+                       }
+               }
+               break;
+
+       case UPIO_HUB6:
+       case UPIO_PORT:
+               if (!request_region(up->port.iobase, size, "serial"))
+                       ret = -EBUSY;
+               break;
+       }
+       return ret;
+}
+
+static void serial8250_release_std_resource(struct uart_8250_port *up)
+{
+       unsigned int size = serial8250_port_size(up);
+
+       switch (up->port.iotype) {
+       case UPIO_AU:
+       case UPIO_TSI:
+       case UPIO_MEM32:
+       case UPIO_MEM:
+               if (!up->port.mapbase)
+                       break;
+
+               if (up->port.flags & UPF_IOREMAP) {
+                       iounmap(up->port.membase);
+                       up->port.membase = NULL;
+               }
+
+               release_mem_region(up->port.mapbase, size);
+               break;
+
+       case UPIO_HUB6:
+       case UPIO_PORT:
+               release_region(up->port.iobase, size);
+               break;
+       }
+}
+
+static int serial8250_request_rsa_resource(struct uart_8250_port *up)
+{
+       unsigned long start = UART_RSA_BASE << up->port.regshift;
+       unsigned int size = 8 << up->port.regshift;
+       int ret = -EINVAL;
+
+       switch (up->port.iotype) {
+       case UPIO_HUB6:
+       case UPIO_PORT:
+               start += up->port.iobase;
+               if (request_region(start, size, "serial-rsa"))
+                       ret = 0;
+               else
+                       ret = -EBUSY;
+               break;
+       }
+
+       return ret;
+}
+
+static void serial8250_release_rsa_resource(struct uart_8250_port *up)
+{
+       unsigned long offset = UART_RSA_BASE << up->port.regshift;
+       unsigned int size = 8 << up->port.regshift;
+
+       switch (up->port.iotype) {
+       case UPIO_HUB6:
+       case UPIO_PORT:
+               release_region(up->port.iobase + offset, size);
+               break;
+       }
+}
+
+static void serial8250_release_port(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       serial8250_release_std_resource(up);
+       if (up->port.type == PORT_RSA)
+               serial8250_release_rsa_resource(up);
+}
+
+static int serial8250_request_port(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       int ret = 0;
+
+       ret = serial8250_request_std_resource(up);
+       if (ret == 0 && up->port.type == PORT_RSA) {
+               ret = serial8250_request_rsa_resource(up);
+               if (ret < 0)
+                       serial8250_release_std_resource(up);
+       }
+
+       return ret;
+}
+
+static void serial8250_config_port(struct uart_port *port, int flags)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       int probeflags = PROBE_ANY;
+       int ret;
+
+       /*
+        * Find the region that we can probe for.  This in turn
+        * tells us whether we can probe for the type of port.
+        */
+       ret = serial8250_request_std_resource(up);
+       if (ret < 0)
+               return;
+
+       ret = serial8250_request_rsa_resource(up);
+       if (ret < 0)
+               probeflags &= ~PROBE_RSA;
+
+       if (up->port.iotype != up->cur_iotype)
+               set_io_from_upio(port);
+
+       if (flags & UART_CONFIG_TYPE)
+               autoconfig(up, probeflags);
+
+       /* if access method is AU, it is a 16550 with a quirk */
+       if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
+               up->bugs |= UART_BUG_NOMSR;
+
+       if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
+               autoconfig_irq(up);
+
+       if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
+               serial8250_release_rsa_resource(up);
+       if (up->port.type == PORT_UNKNOWN)
+               serial8250_release_std_resource(up);
+}
+
+static int
+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       if (ser->irq >= nr_irqs || ser->irq < 0 ||
+           ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+           ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
+           ser->type == PORT_STARTECH)
+               return -EINVAL;
+       return 0;
+}
+
+static const char *
+serial8250_type(struct uart_port *port)
+{
+       int type = port->type;
+
+       if (type >= ARRAY_SIZE(uart_config))
+               type = 0;
+       return uart_config[type].name;
+}
+
+static struct uart_ops serial8250_pops = {
+       .tx_empty       = serial8250_tx_empty,
+       .set_mctrl      = serial8250_set_mctrl,
+       .get_mctrl      = serial8250_get_mctrl,
+       .stop_tx        = serial8250_stop_tx,
+       .start_tx       = serial8250_start_tx,
+       .stop_rx        = serial8250_stop_rx,
+       .enable_ms      = serial8250_enable_ms,
+       .break_ctl      = serial8250_break_ctl,
+       .startup        = serial8250_startup,
+       .shutdown       = serial8250_shutdown,
+       .set_termios    = serial8250_set_termios,
+       .set_ldisc      = serial8250_set_ldisc,
+       .pm             = serial8250_pm,
+       .type           = serial8250_type,
+       .release_port   = serial8250_release_port,
+       .request_port   = serial8250_request_port,
+       .config_port    = serial8250_config_port,
+       .verify_port    = serial8250_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = serial8250_get_poll_char,
+       .poll_put_char = serial8250_put_poll_char,
+#endif
+};
+
+static struct uart_8250_port serial8250_ports[UART_NR];
+
+static void (*serial8250_isa_config)(int port, struct uart_port *up,
+       unsigned short *capabilities);
+
+void serial8250_set_isa_configurator(
+       void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
+{
+       serial8250_isa_config = v;
+}
+EXPORT_SYMBOL(serial8250_set_isa_configurator);
+
+static void __init serial8250_isa_init_ports(void)
+{
+       struct uart_8250_port *up;
+       static int first = 1;
+       int i, irqflag = 0;
+
+       if (!first)
+               return;
+       first = 0;
+
+       for (i = 0; i < nr_uarts; i++) {
+               struct uart_8250_port *up = &serial8250_ports[i];
+
+               up->port.line = i;
+               spin_lock_init(&up->port.lock);
+
+               init_timer(&up->timer);
+               up->timer.function = serial8250_timeout;
+
+               /*
+                * ALPHA_KLUDGE_MCR needs to be killed.
+                */
+               up->mcr_mask = ~ALPHA_KLUDGE_MCR;
+               up->mcr_force = ALPHA_KLUDGE_MCR;
+
+               up->port.ops = &serial8250_pops;
+       }
+
+       if (share_irqs)
+               irqflag = IRQF_SHARED;
+
+       for (i = 0, up = serial8250_ports;
+            i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
+            i++, up++) {
+               up->port.iobase   = old_serial_port[i].port;
+               up->port.irq      = irq_canonicalize(old_serial_port[i].irq);
+               up->port.irqflags = old_serial_port[i].irqflags;
+               up->port.uartclk  = old_serial_port[i].baud_base * 16;
+               up->port.flags    = old_serial_port[i].flags;
+               up->port.hub6     = old_serial_port[i].hub6;
+               up->port.membase  = old_serial_port[i].iomem_base;
+               up->port.iotype   = old_serial_port[i].io_type;
+               up->port.regshift = old_serial_port[i].iomem_reg_shift;
+               set_io_from_upio(&up->port);
+               up->port.irqflags |= irqflag;
+               if (serial8250_isa_config != NULL)
+                       serial8250_isa_config(i, &up->port, &up->capabilities);
+
+       }
+}
+
+static void
+serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
+{
+       up->port.type = type;
+       up->port.fifosize = uart_config[type].fifo_size;
+       up->capabilities = uart_config[type].flags;
+       up->tx_loadsz = uart_config[type].tx_loadsz;
+}
+
+static void __init
+serial8250_register_ports(struct uart_driver *drv, struct device *dev)
+{
+       int i;
+
+       for (i = 0; i < nr_uarts; i++) {
+               struct uart_8250_port *up = &serial8250_ports[i];
+               up->cur_iotype = 0xFF;
+       }
+
+       serial8250_isa_init_ports();
+
+       for (i = 0; i < nr_uarts; i++) {
+               struct uart_8250_port *up = &serial8250_ports[i];
+
+               up->port.dev = dev;
+
+               if (up->port.flags & UPF_FIXED_TYPE)
+                       serial8250_init_fixed_type_port(up, up->port.type);
+
+               uart_add_one_port(drv, &up->port);
+       }
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+
+static void serial8250_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       wait_for_xmitr(up, UART_LSR_THRE);
+       serial_out(up, UART_TX, ch);
+}
+
+/*
+ *     Print a string to the serial port trying not to disturb
+ *     any possible real use of the port...
+ *
+ *     The console_lock must be held when we get here.
+ */
+static void
+serial8250_console_write(struct console *co, const char *s, unsigned int count)
+{
+       struct uart_8250_port *up = &serial8250_ports[co->index];
+       unsigned long flags;
+       unsigned int ier;
+       int locked = 1;
+
+       touch_nmi_watchdog();
+
+       local_irq_save(flags);
+       if (up->port.sysrq) {
+               /* serial8250_handle_irq() already took the lock */
+               locked = 0;
+       } else if (oops_in_progress) {
+               locked = spin_trylock(&up->port.lock);
+       } else
+               spin_lock(&up->port.lock);
+
+       /*
+        *      First save the IER then disable the interrupts
+        */
+       ier = serial_in(up, UART_IER);
+
+       if (up->capabilities & UART_CAP_UUE)
+               serial_out(up, UART_IER, UART_IER_UUE);
+       else
+               serial_out(up, UART_IER, 0);
+
+       uart_console_write(&up->port, s, count, serial8250_console_putchar);
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore the IER
+        */
+       wait_for_xmitr(up, BOTH_EMPTY);
+       serial_out(up, UART_IER, ier);
+
+       /*
+        *      The receive handling will happen properly because the
+        *      receive ready bit will still be set; it is not cleared
+        *      on read.  However, modem control will not, we must
+        *      call it if we have saved something in the saved flags
+        *      while processing with interrupts off.
+        */
+       if (up->msr_saved_flags)
+               serial8250_modem_status(up);
+
+       if (locked)
+               spin_unlock(&up->port.lock);
+       local_irq_restore(flags);
+}
+
+static int __init serial8250_console_setup(struct console *co, char *options)
+{
+       struct uart_port *port;
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       /*
+        * Check whether an invalid uart number has been specified, and
+        * if so, search for the first available port that does have
+        * console support.
+        */
+       if (co->index >= nr_uarts)
+               co->index = 0;
+       port = &serial8250_ports[co->index].port;
+       if (!port->iobase && !port->membase)
+               return -ENODEV;
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static int serial8250_console_early_setup(void)
+{
+       return serial8250_find_port_for_earlycon();
+}
+
+static struct console serial8250_console = {
+       .name           = "ttyS",
+       .write          = serial8250_console_write,
+       .device         = uart_console_device,
+       .setup          = serial8250_console_setup,
+       .early_setup    = serial8250_console_early_setup,
+       .flags          = CON_PRINTBUFFER | CON_ANYTIME,
+       .index          = -1,
+       .data           = &serial8250_reg,
+};
+
+static int __init serial8250_console_init(void)
+{
+       if (nr_uarts > UART_NR)
+               nr_uarts = UART_NR;
+
+       serial8250_isa_init_ports();
+       register_console(&serial8250_console);
+       return 0;
+}
+console_initcall(serial8250_console_init);
+
+int serial8250_find_port(struct uart_port *p)
+{
+       int line;
+       struct uart_port *port;
+
+       for (line = 0; line < nr_uarts; line++) {
+               port = &serial8250_ports[line].port;
+               if (uart_match_port(p, port))
+                       return line;
+       }
+       return -ENODEV;
+}
+
+#define SERIAL8250_CONSOLE     &serial8250_console
+#else
+#define SERIAL8250_CONSOLE     NULL
+#endif
+
+static struct uart_driver serial8250_reg = {
+       .owner                  = THIS_MODULE,
+       .driver_name            = "serial",
+       .dev_name               = "ttyS",
+       .major                  = TTY_MAJOR,
+       .minor                  = 64,
+       .cons                   = SERIAL8250_CONSOLE,
+};
+
+/*
+ * early_serial_setup - early registration for 8250 ports
+ *
+ * Setup an 8250 port structure prior to console initialisation.  Use
+ * after console initialisation will cause undefined behaviour.
+ */
+int __init early_serial_setup(struct uart_port *port)
+{
+       struct uart_port *p;
+
+       if (port->line >= ARRAY_SIZE(serial8250_ports))
+               return -ENODEV;
+
+       serial8250_isa_init_ports();
+       p = &serial8250_ports[port->line].port;
+       p->iobase       = port->iobase;
+       p->membase      = port->membase;
+       p->irq          = port->irq;
+       p->irqflags     = port->irqflags;
+       p->uartclk      = port->uartclk;
+       p->fifosize     = port->fifosize;
+       p->regshift     = port->regshift;
+       p->iotype       = port->iotype;
+       p->flags        = port->flags;
+       p->mapbase      = port->mapbase;
+       p->private_data = port->private_data;
+       p->type         = port->type;
+       p->line         = port->line;
+
+       set_io_from_upio(p);
+       if (port->serial_in)
+               p->serial_in = port->serial_in;
+       if (port->serial_out)
+               p->serial_out = port->serial_out;
+       if (port->handle_irq)
+               p->handle_irq = port->handle_irq;
+       else
+               p->handle_irq = serial8250_default_handle_irq;
+
+       return 0;
+}
+
+/**
+ *     serial8250_suspend_port - suspend one serial port
+ *     @line:  serial line number
+ *
+ *     Suspend one serial port.
+ */
+void serial8250_suspend_port(int line)
+{
+       uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
+}
+
+/**
+ *     serial8250_resume_port - resume one serial port
+ *     @line:  serial line number
+ *
+ *     Resume one serial port.
+ */
+void serial8250_resume_port(int line)
+{
+       struct uart_8250_port *up = &serial8250_ports[line];
+
+       if (up->capabilities & UART_NATSEMI) {
+               /* Ensure it's still in high speed mode */
+               serial_outp(up, UART_LCR, 0xE0);
+
+               ns16550a_goto_highspeed(up);
+
+               serial_outp(up, UART_LCR, 0);
+               up->port.uartclk = 921600*16;
+       }
+       uart_resume_port(&serial8250_reg, &up->port);
+}
+
+/*
+ * Register a set of serial devices attached to a platform device.  The
+ * list is terminated with a zero flags entry, which means we expect
+ * all entries to have at least UPF_BOOT_AUTOCONF set.
+ */
+static int __devinit serial8250_probe(struct platform_device *dev)
+{
+       struct plat_serial8250_port *p = dev->dev.platform_data;
+       struct uart_port port;
+       int ret, i, irqflag = 0;
+
+       memset(&port, 0, sizeof(struct uart_port));
+
+       if (share_irqs)
+               irqflag = IRQF_SHARED;
+
+       for (i = 0; p && p->flags != 0; p++, i++) {
+               port.iobase             = p->iobase;
+               port.membase            = p->membase;
+               port.irq                = p->irq;
+               port.irqflags           = p->irqflags;
+               port.uartclk            = p->uartclk;
+               port.regshift           = p->regshift;
+               port.iotype             = p->iotype;
+               port.flags              = p->flags;
+               port.mapbase            = p->mapbase;
+               port.hub6               = p->hub6;
+               port.private_data       = p->private_data;
+               port.type               = p->type;
+               port.serial_in          = p->serial_in;
+               port.serial_out         = p->serial_out;
+               port.handle_irq         = p->handle_irq;
+               port.set_termios        = p->set_termios;
+               port.pm                 = p->pm;
+               port.dev                = &dev->dev;
+               port.irqflags           |= irqflag;
+               ret = serial8250_register_port(&port);
+               if (ret < 0) {
+                       dev_err(&dev->dev, "unable to register port at index %d "
+                               "(IO%lx MEM%llx IRQ%d): %d\n", i,
+                               p->iobase, (unsigned long long)p->mapbase,
+                               p->irq, ret);
+               }
+       }
+       return 0;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial8250_remove(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < nr_uarts; i++) {
+               struct uart_8250_port *up = &serial8250_ports[i];
+
+               if (up->port.dev == &dev->dev)
+                       serial8250_unregister_port(i);
+       }
+       return 0;
+}
+
+static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
+{
+       int i;
+
+       for (i = 0; i < UART_NR; i++) {
+               struct uart_8250_port *up = &serial8250_ports[i];
+
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+                       uart_suspend_port(&serial8250_reg, &up->port);
+       }
+
+       return 0;
+}
+
+static int serial8250_resume(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < UART_NR; i++) {
+               struct uart_8250_port *up = &serial8250_ports[i];
+
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+                       serial8250_resume_port(i);
+       }
+
+       return 0;
+}
+
+static struct platform_driver serial8250_isa_driver = {
+       .probe          = serial8250_probe,
+       .remove         = __devexit_p(serial8250_remove),
+       .suspend        = serial8250_suspend,
+       .resume         = serial8250_resume,
+       .driver         = {
+               .name   = "serial8250",
+               .owner  = THIS_MODULE,
+       },
+};
+
+/*
+ * This "device" covers _all_ ISA 8250-compatible serial devices listed
+ * in the table in include/asm/serial.h
+ */
+static struct platform_device *serial8250_isa_devs;
+
+/*
+ * serial8250_register_port and serial8250_unregister_port allows for
+ * 16x50 serial ports to be configured at run-time, to support PCMCIA
+ * modems and PCI multiport cards.
+ */
+static DEFINE_MUTEX(serial_mutex);
+
+static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
+{
+       int i;
+
+       /*
+        * First, find a port entry which matches.
+        */
+       for (i = 0; i < nr_uarts; i++)
+               if (uart_match_port(&serial8250_ports[i].port, port))
+                       return &serial8250_ports[i];
+
+       /*
+        * We didn't find a matching entry, so look for the first
+        * free entry.  We look for one which hasn't been previously
+        * used (indicated by zero iobase).
+        */
+       for (i = 0; i < nr_uarts; i++)
+               if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
+                   serial8250_ports[i].port.iobase == 0)
+                       return &serial8250_ports[i];
+
+       /*
+        * That also failed.  Last resort is to find any entry which
+        * doesn't have a real port associated with it.
+        */
+       for (i = 0; i < nr_uarts; i++)
+               if (serial8250_ports[i].port.type == PORT_UNKNOWN)
+                       return &serial8250_ports[i];
+
+       return NULL;
+}
+
+/**
+ *     serial8250_register_port - register a serial port
+ *     @port: serial port template
+ *
+ *     Configure the serial port specified by the request. If the
+ *     port exists and is in use, it is hung up and unregistered
+ *     first.
+ *
+ *     The port is then probed and if necessary the IRQ is autodetected
+ *     If this fails an error is returned.
+ *
+ *     On success the port is ready to use and the line number is returned.
+ */
+int serial8250_register_port(struct uart_port *port)
+{
+       struct uart_8250_port *uart;
+       int ret = -ENOSPC;
+
+       if (port->uartclk == 0)
+               return -EINVAL;
+
+       mutex_lock(&serial_mutex);
+
+       uart = serial8250_find_match_or_unused(port);
+       if (uart) {
+               uart_remove_one_port(&serial8250_reg, &uart->port);
+
+               uart->port.iobase       = port->iobase;
+               uart->port.membase      = port->membase;
+               uart->port.irq          = port->irq;
+               uart->port.irqflags     = port->irqflags;
+               uart->port.uartclk      = port->uartclk;
+               uart->port.fifosize     = port->fifosize;
+               uart->port.regshift     = port->regshift;
+               uart->port.iotype       = port->iotype;
+               uart->port.flags        = port->flags | UPF_BOOT_AUTOCONF;
+               uart->port.mapbase      = port->mapbase;
+               uart->port.private_data = port->private_data;
+               if (port->dev)
+                       uart->port.dev = port->dev;
+
+               if (port->flags & UPF_FIXED_TYPE)
+                       serial8250_init_fixed_type_port(uart, port->type);
+
+               set_io_from_upio(&uart->port);
+               /* Possibly override default I/O functions.  */
+               if (port->serial_in)
+                       uart->port.serial_in = port->serial_in;
+               if (port->serial_out)
+                       uart->port.serial_out = port->serial_out;
+               if (port->handle_irq)
+                       uart->port.handle_irq = port->handle_irq;
+               /*  Possibly override set_termios call */
+               if (port->set_termios)
+                       uart->port.set_termios = port->set_termios;
+               if (port->pm)
+                       uart->port.pm = port->pm;
+
+               if (serial8250_isa_config != NULL)
+                       serial8250_isa_config(0, &uart->port,
+                                       &uart->capabilities);
+
+               ret = uart_add_one_port(&serial8250_reg, &uart->port);
+               if (ret == 0)
+                       ret = uart->port.line;
+       }
+       mutex_unlock(&serial_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(serial8250_register_port);
+
+/**
+ *     serial8250_unregister_port - remove a 16x50 serial port at runtime
+ *     @line: serial line number
+ *
+ *     Remove one serial port.  This may not be called from interrupt
+ *     context.  We hand the port back to the our control.
+ */
+void serial8250_unregister_port(int line)
+{
+       struct uart_8250_port *uart = &serial8250_ports[line];
+
+       mutex_lock(&serial_mutex);
+       uart_remove_one_port(&serial8250_reg, &uart->port);
+       if (serial8250_isa_devs) {
+               uart->port.flags &= ~UPF_BOOT_AUTOCONF;
+               uart->port.type = PORT_UNKNOWN;
+               uart->port.dev = &serial8250_isa_devs->dev;
+               uart->capabilities = uart_config[uart->port.type].flags;
+               uart_add_one_port(&serial8250_reg, &uart->port);
+       } else {
+               uart->port.dev = NULL;
+       }
+       mutex_unlock(&serial_mutex);
+}
+EXPORT_SYMBOL(serial8250_unregister_port);
+
+static int __init serial8250_init(void)
+{
+       int ret;
+
+       if (nr_uarts > UART_NR)
+               nr_uarts = UART_NR;
+
+       printk(KERN_INFO "Serial: 8250/16550 driver, "
+               "%d ports, IRQ sharing %sabled\n", nr_uarts,
+               share_irqs ? "en" : "dis");
+
+#ifdef CONFIG_SPARC
+       ret = sunserial_register_minors(&serial8250_reg, UART_NR);
+#else
+       serial8250_reg.nr = UART_NR;
+       ret = uart_register_driver(&serial8250_reg);
+#endif
+       if (ret)
+               goto out;
+
+       serial8250_isa_devs = platform_device_alloc("serial8250",
+                                                   PLAT8250_DEV_LEGACY);
+       if (!serial8250_isa_devs) {
+               ret = -ENOMEM;
+               goto unreg_uart_drv;
+       }
+
+       ret = platform_device_add(serial8250_isa_devs);
+       if (ret)
+               goto put_dev;
+
+       serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
+
+       ret = platform_driver_register(&serial8250_isa_driver);
+       if (ret == 0)
+               goto out;
+
+       platform_device_del(serial8250_isa_devs);
+put_dev:
+       platform_device_put(serial8250_isa_devs);
+unreg_uart_drv:
+#ifdef CONFIG_SPARC
+       sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
+       uart_unregister_driver(&serial8250_reg);
+#endif
+out:
+       return ret;
+}
+
+static void __exit serial8250_exit(void)
+{
+       struct platform_device *isa_dev = serial8250_isa_devs;
+
+       /*
+        * This tells serial8250_unregister_port() not to re-register
+        * the ports (thereby making serial8250_isa_driver permanently
+        * in use.)
+        */
+       serial8250_isa_devs = NULL;
+
+       platform_driver_unregister(&serial8250_isa_driver);
+       platform_device_unregister(isa_dev);
+
+#ifdef CONFIG_SPARC
+       sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
+       uart_unregister_driver(&serial8250_reg);
+#endif
+}
+
+module_init(serial8250_init);
+module_exit(serial8250_exit);
+
+EXPORT_SYMBOL(serial8250_suspend_port);
+EXPORT_SYMBOL(serial8250_resume_port);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
+
+module_param(share_irqs, uint, 0644);
+MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
+       " (unsafe)");
+
+module_param(nr_uarts, uint, 0644);
+MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+
+module_param(skip_txen_test, uint, 0644);
+MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
+
+#ifdef CONFIG_SERIAL_8250_RSA
+module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
+MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
+#endif
+MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
new file mode 100644 (file)
index 0000000..ae027be
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  Driver for 8250/16550-type serial ports
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2001 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/serial_8250.h>
+
+struct uart_8250_port {
+       struct uart_port        port;
+       struct timer_list       timer;          /* "no irq" timer */
+       struct list_head        list;           /* ports on this IRQ */
+       unsigned short          capabilities;   /* port capabilities */
+       unsigned short          bugs;           /* port bugs */
+       unsigned int            tx_loadsz;      /* transmit fifo load size */
+       unsigned char           acr;
+       unsigned char           ier;
+       unsigned char           lcr;
+       unsigned char           mcr;
+       unsigned char           mcr_mask;       /* mask of user bits */
+       unsigned char           mcr_force;      /* mask of forced bits */
+       unsigned char           cur_iotype;     /* Running I/O type */
+
+       /*
+        * Some bits in registers are cleared on a read, so they must
+        * be saved whenever the register is read but the bits will not
+        * be immediately processed.
+        */
+#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
+       unsigned char           lsr_saved_flags;
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+       unsigned char           msr_saved_flags;
+};
+
+struct old_serial_port {
+       unsigned int uart;
+       unsigned int baud_base;
+       unsigned int port;
+       unsigned int irq;
+       unsigned int flags;
+       unsigned char hub6;
+       unsigned char io_type;
+       unsigned char *iomem_base;
+       unsigned short iomem_reg_shift;
+       unsigned long irqflags;
+};
+
+/*
+ * This replaces serial_uart_config in include/linux/serial.h
+ */
+struct serial8250_config {
+       const char      *name;
+       unsigned short  fifo_size;
+       unsigned short  tx_loadsz;
+       unsigned char   fcr;
+       unsigned int    flags;
+};
+
+#define UART_CAP_FIFO  (1 << 8)        /* UART has FIFO */
+#define UART_CAP_EFR   (1 << 9)        /* UART has EFR */
+#define UART_CAP_SLEEP (1 << 10)       /* UART has IER sleep */
+#define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
+#define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
+#define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, Tegra) */
+
+#define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
+#define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
+#define UART_BUG_NOMSR (1 << 2)        /* UART has buggy MSR status bits (Au1x00) */
+#define UART_BUG_THRE  (1 << 3)        /* UART has buggy THRE reassertion */
+
+#define PROBE_RSA      (1 << 0)
+#define PROBE_ANY      (~0)
+
+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+
+#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
+#define SERIAL8250_SHARE_IRQS 1
+#else
+#define SERIAL8250_SHARE_IRQS 0
+#endif
+
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+/*
+ * Digital did something really horribly wrong with the OUT1 and OUT2
+ * lines on at least some ALPHA's.  The failure mode is that if either
+ * is cleared, the machine locks up with endless interrupts.
+ */
+#define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
+#elif defined(CONFIG_SBC8560)
+/*
+ * WindRiver did something similarly broken on their SBC8560 board. The
+ * UART tristates its IRQ output while OUT2 is clear, but they pulled
+ * the interrupt line _up_ instead of down, so if we register the IRQ
+ * while the UART is in that state, we die in an IRQ storm. */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
+#else
+#define ALPHA_KLUDGE_MCR 0
+#endif
diff --git a/drivers/tty/serial/8250/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c
new file mode 100644 (file)
index 0000000..34b51c6
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq)                               \
+       {                                               \
+               .iobase         = _base,                \
+               .irq            = _irq,                 \
+               .uartclk        = 1843200,              \
+               .iotype         = UPIO_PORT,            \
+               .flags          = UPF_BOOT_AUTOCONF,    \
+       }
+
+static struct plat_serial8250_port accent_data[] = {
+       PORT(0x330, 4),
+       PORT(0x338, 4),
+       { },
+};
+
+static struct platform_device accent_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_ACCENT,
+       .dev                    = {
+               .platform_data  = accent_data,
+       },
+};
+
+static int __init accent_init(void)
+{
+       return platform_device_register(&accent_device);
+}
+
+module_init(accent_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for Accent Async cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
new file mode 100644 (file)
index 0000000..b0ce8c5
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  linux/drivers/serial/acorn.c
+ *
+ *  Copyright (C) 1996-2003 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/ecard.h>
+#include <asm/string.h>
+
+#include "8250.h"
+
+#define MAX_PORTS      3
+
+struct serial_card_type {
+       unsigned int    num_ports;
+       unsigned int    uartclk;
+       unsigned int    type;
+       unsigned int    offset[MAX_PORTS];
+};
+
+struct serial_card_info {
+       unsigned int    num_ports;
+       int             ports[MAX_PORTS];
+       void __iomem *vaddr;
+};
+
+static int __devinit
+serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+       struct serial_card_info *info;
+       struct serial_card_type *type = id->data;
+       struct uart_port port;
+       unsigned long bus_addr;
+       unsigned int i;
+
+       info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->num_ports = type->num_ports;
+
+       bus_addr = ecard_resource_start(ec, type->type);
+       info->vaddr = ecardm_iomap(ec, type->type, 0, 0);
+       if (!info->vaddr) {
+               kfree(info);
+               return -ENOMEM;
+       }
+
+       ecard_set_drvdata(ec, info);
+
+       memset(&port, 0, sizeof(struct uart_port));
+       port.irq        = ec->irq;
+       port.flags      = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+       port.uartclk    = type->uartclk;
+       port.iotype     = UPIO_MEM;
+       port.regshift   = 2;
+       port.dev        = &ec->dev;
+
+       for (i = 0; i < info->num_ports; i ++) {
+               port.membase = info->vaddr + type->offset[i];
+               port.mapbase = bus_addr + type->offset[i];
+
+               info->ports[i] = serial8250_register_port(&port);
+       }
+
+       return 0;
+}
+
+static void __devexit serial_card_remove(struct expansion_card *ec)
+{
+       struct serial_card_info *info = ecard_get_drvdata(ec);
+       int i;
+
+       ecard_set_drvdata(ec, NULL);
+
+       for (i = 0; i < info->num_ports; i++)
+               if (info->ports[i] > 0)
+                       serial8250_unregister_port(info->ports[i]);
+
+       kfree(info);
+}
+
+static struct serial_card_type atomwide_type = {
+       .num_ports      = 3,
+       .uartclk        = 7372800,
+       .type           = ECARD_RES_IOCSLOW,
+       .offset         = { 0x2800, 0x2400, 0x2000 },
+};
+
+static struct serial_card_type serport_type = {
+       .num_ports      = 2,
+       .uartclk        = 3686400,
+       .type           = ECARD_RES_IOCSLOW,
+       .offset         = { 0x2000, 0x2020 },
+};
+
+static const struct ecard_id serial_cids[] = {
+       { MANU_ATOMWIDE,        PROD_ATOMWIDE_3PSERIAL, &atomwide_type  },
+       { MANU_SERPORT,         PROD_SERPORT_DSPORT,    &serport_type   },
+       { 0xffff, 0xffff }
+};
+
+static struct ecard_driver serial_card_driver = {
+       .probe          = serial_card_probe,
+       .remove         = __devexit_p(serial_card_remove),
+       .id_table       = serial_cids,
+       .drv = {
+               .name   = "8250_acorn",
+       },
+};
+
+static int __init serial_card_init(void)
+{
+       return ecard_register_driver(&serial_card_driver);
+}
+
+static void __exit serial_card_exit(void)
+{
+       ecard_remove_driver(&serial_card_driver);
+}
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
+MODULE_LICENSE("GPL");
+
+module_init(serial_card_init);
+module_exit(serial_card_exit);
diff --git a/drivers/tty/serial/8250/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c
new file mode 100644 (file)
index 0000000..d125dc1
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq)                               \
+       {                                               \
+               .iobase         = _base,                \
+               .irq            = _irq,                 \
+               .uartclk        = 1843200,              \
+               .iotype         = UPIO_PORT,            \
+               .flags          = UPF_BOOT_AUTOCONF,    \
+       }
+
+static struct plat_serial8250_port boca_data[] = {
+       PORT(0x100, 12),
+       PORT(0x108, 12),
+       PORT(0x110, 12),
+       PORT(0x118, 12),
+       PORT(0x120, 12),
+       PORT(0x128, 12),
+       PORT(0x130, 12),
+       PORT(0x138, 12),
+       PORT(0x140, 12),
+       PORT(0x148, 12),
+       PORT(0x150, 12),
+       PORT(0x158, 12),
+       PORT(0x160, 12),
+       PORT(0x168, 12),
+       PORT(0x170, 12),
+       PORT(0x178, 12),
+       { },
+};
+
+static struct platform_device boca_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_BOCA,
+       .dev                    = {
+               .platform_data  = boca_data,
+       },
+};
+
+static int __init boca_init(void)
+{
+       return platform_device_register(&boca_device);
+}
+
+module_init(boca_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for Boca cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
new file mode 100644 (file)
index 0000000..f574eef
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Synopsys DesignWare 8250 driver.
+ *
+ * Copyright 2011 Picochip, Jamie Iles.
+ *
+ * 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.
+ *
+ * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
+ * LCR is written whilst busy.  If it is, then a busy detect interrupt is
+ * raised, the LCR needs to be rewritten and the uart status register read.
+ */
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct dw8250_data {
+       int     last_lcr;
+       int     line;
+};
+
+static void dw8250_serial_out(struct uart_port *p, int offset, int value)
+{
+       struct dw8250_data *d = p->private_data;
+
+       if (offset == UART_LCR)
+               d->last_lcr = value;
+
+       offset <<= p->regshift;
+       writeb(value, p->membase + offset);
+}
+
+static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
+{
+       offset <<= p->regshift;
+
+       return readb(p->membase + offset);
+}
+
+static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
+{
+       struct dw8250_data *d = p->private_data;
+
+       if (offset == UART_LCR)
+               d->last_lcr = value;
+
+       offset <<= p->regshift;
+       writel(value, p->membase + offset);
+}
+
+static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
+{
+       offset <<= p->regshift;
+
+       return readl(p->membase + offset);
+}
+
+/* Offset for the DesignWare's UART Status Register. */
+#define UART_USR       0x1f
+
+static int dw8250_handle_irq(struct uart_port *p)
+{
+       struct dw8250_data *d = p->private_data;
+       unsigned int iir = p->serial_in(p, UART_IIR);
+
+       if (serial8250_handle_irq(p, iir)) {
+               return 1;
+       } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+               /* Clear the USR and write the LCR again. */
+               (void)p->serial_in(p, UART_USR);
+               p->serial_out(p, d->last_lcr, UART_LCR);
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static int __devinit dw8250_probe(struct platform_device *pdev)
+{
+       struct uart_port port = {};
+       struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       struct device_node *np = pdev->dev.of_node;
+       u32 val;
+       struct dw8250_data *data;
+
+       if (!regs || !irq) {
+               dev_err(&pdev->dev, "no registers/irq defined\n");
+               return -EINVAL;
+       }
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       port.private_data = data;
+
+       spin_lock_init(&port.lock);
+       port.mapbase = regs->start;
+       port.irq = irq->start;
+       port.handle_irq = dw8250_handle_irq;
+       port.type = PORT_8250;
+       port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+               UPF_FIXED_PORT | UPF_FIXED_TYPE;
+       port.dev = &pdev->dev;
+
+       port.iotype = UPIO_MEM;
+       port.serial_in = dw8250_serial_in;
+       port.serial_out = dw8250_serial_out;
+       if (!of_property_read_u32(np, "reg-io-width", &val)) {
+               switch (val) {
+               case 1:
+                       break;
+               case 4:
+                       port.iotype = UPIO_MEM32;
+                       port.serial_in = dw8250_serial_in32;
+                       port.serial_out = dw8250_serial_out32;
+                       break;
+               default:
+                       dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
+                               val);
+                       return -EINVAL;
+               }
+       }
+
+       if (!of_property_read_u32(np, "reg-shift", &val))
+               port.regshift = val;
+
+       if (of_property_read_u32(np, "clock-frequency", &val)) {
+               dev_err(&pdev->dev, "no clock-frequency property set\n");
+               return -EINVAL;
+       }
+       port.uartclk = val;
+
+       data->line = serial8250_register_port(&port);
+       if (data->line < 0)
+               return data->line;
+
+       platform_set_drvdata(pdev, data);
+
+       return 0;
+}
+
+static int __devexit dw8250_remove(struct platform_device *pdev)
+{
+       struct dw8250_data *data = platform_get_drvdata(pdev);
+
+       serial8250_unregister_port(data->line);
+
+       return 0;
+}
+
+static const struct of_device_id dw8250_match[] = {
+       { .compatible = "snps,dw-apb-uart" },
+       { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dw8250_match);
+
+static struct platform_driver dw8250_platform_driver = {
+       .driver = {
+               .name           = "dw-apb-uart",
+               .owner          = THIS_MODULE,
+               .of_match_table = dw8250_match,
+       },
+       .probe                  = dw8250_probe,
+       .remove                 = __devexit_p(dw8250_remove),
+};
+
+module_platform_driver(dw8250_platform_driver);
+
+MODULE_AUTHOR("Jamie Iles");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
new file mode 100644 (file)
index 0000000..eaafb98
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Early serial console for 8250/16550 devices
+ *
+ * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
+ *     Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
+ * and on early_printk.c by Andi Kleen.
+ *
+ * This is for use before the serial driver has initialized, in
+ * particular, before the UARTs have been discovered and named.
+ * Instead of specifying the console device as, e.g., "ttyS0",
+ * we locate the device directly by its MMIO or I/O port address.
+ *
+ * The user can specify the device directly, e.g.,
+ *     earlycon=uart8250,io,0x3f8,9600n8
+ *     earlycon=uart8250,mmio,0xff5e0000,115200n8
+ *     earlycon=uart8250,mmio32,0xff5e0000,115200n8
+ * or
+ *     console=uart8250,io,0x3f8,9600n8
+ *     console=uart8250,mmio,0xff5e0000,115200n8
+ *     console=uart8250,mmio32,0xff5e0000,115200n8
+ */
+
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <asm/io.h>
+#include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
+
+struct early_serial8250_device {
+       struct uart_port port;
+       char options[16];               /* e.g., 115200n8 */
+       unsigned int baud;
+};
+
+static struct early_serial8250_device early_device;
+
+static unsigned int __init serial_in(struct uart_port *port, int offset)
+{
+       switch (port->iotype) {
+       case UPIO_MEM:
+               return readb(port->membase + offset);
+       case UPIO_MEM32:
+               return readl(port->membase + (offset << 2));
+       case UPIO_PORT:
+               return inb(port->iobase + offset);
+       default:
+               return 0;
+       }
+}
+
+static void __init serial_out(struct uart_port *port, int offset, int value)
+{
+       switch (port->iotype) {
+       case UPIO_MEM:
+               writeb(value, port->membase + offset);
+               break;
+       case UPIO_MEM32:
+               writel(value, port->membase + (offset << 2));
+               break;
+       case UPIO_PORT:
+               outb(value, port->iobase + offset);
+               break;
+       }
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void __init wait_for_xmitr(struct uart_port *port)
+{
+       unsigned int status;
+
+       for (;;) {
+               status = serial_in(port, UART_LSR);
+               if ((status & BOTH_EMPTY) == BOTH_EMPTY)
+                       return;
+               cpu_relax();
+       }
+}
+
+static void __init serial_putc(struct uart_port *port, int c)
+{
+       wait_for_xmitr(port);
+       serial_out(port, UART_TX, c);
+}
+
+static void __init early_serial8250_write(struct console *console,
+                                       const char *s, unsigned int count)
+{
+       struct uart_port *port = &early_device.port;
+       unsigned int ier;
+
+       /* Save the IER and disable interrupts */
+       ier = serial_in(port, UART_IER);
+       serial_out(port, UART_IER, 0);
+
+       uart_console_write(port, s, count, serial_putc);
+
+       /* Wait for transmitter to become empty and restore the IER */
+       wait_for_xmitr(port);
+       serial_out(port, UART_IER, ier);
+}
+
+static unsigned int __init probe_baud(struct uart_port *port)
+{
+       unsigned char lcr, dll, dlm;
+       unsigned int quot;
+
+       lcr = serial_in(port, UART_LCR);
+       serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+       dll = serial_in(port, UART_DLL);
+       dlm = serial_in(port, UART_DLM);
+       serial_out(port, UART_LCR, lcr);
+
+       quot = (dlm << 8) | dll;
+       return (port->uartclk / 16) / quot;
+}
+
+static void __init init_port(struct early_serial8250_device *device)
+{
+       struct uart_port *port = &device->port;
+       unsigned int divisor;
+       unsigned char c;
+
+       serial_out(port, UART_LCR, 0x3);        /* 8n1 */
+       serial_out(port, UART_IER, 0);          /* no interrupt */
+       serial_out(port, UART_FCR, 0);          /* no fifo */
+       serial_out(port, UART_MCR, 0x3);        /* DTR + RTS */
+
+       divisor = port->uartclk / (16 * device->baud);
+       c = serial_in(port, UART_LCR);
+       serial_out(port, UART_LCR, c | UART_LCR_DLAB);
+       serial_out(port, UART_DLL, divisor & 0xff);
+       serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
+       serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
+}
+
+static int __init parse_options(struct early_serial8250_device *device,
+                                                               char *options)
+{
+       struct uart_port *port = &device->port;
+       int mmio, mmio32, length;
+
+       if (!options)
+               return -ENODEV;
+
+       port->uartclk = BASE_BAUD * 16;
+
+       mmio = !strncmp(options, "mmio,", 5);
+       mmio32 = !strncmp(options, "mmio32,", 7);
+       if (mmio || mmio32) {
+               port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
+               port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
+                                              &options, 0);
+               if (mmio32)
+                       port->regshift = 2;
+#ifdef CONFIG_FIX_EARLYCON_MEM
+               set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
+                                       port->mapbase & PAGE_MASK);
+               port->membase =
+                       (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+               port->membase += port->mapbase & ~PAGE_MASK;
+#else
+               port->membase = ioremap_nocache(port->mapbase, 64);
+               if (!port->membase) {
+                       printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
+                               __func__,
+                              (unsigned long long) port->mapbase);
+                       return -ENOMEM;
+               }
+#endif
+       } else if (!strncmp(options, "io,", 3)) {
+               port->iotype = UPIO_PORT;
+               port->iobase = simple_strtoul(options + 3, &options, 0);
+               mmio = 0;
+       } else
+               return -EINVAL;
+
+       options = strchr(options, ',');
+       if (options) {
+               options++;
+               device->baud = simple_strtoul(options, NULL, 0);
+               length = min(strcspn(options, " "), sizeof(device->options));
+               strncpy(device->options, options, length);
+       } else {
+               device->baud = probe_baud(port);
+               snprintf(device->options, sizeof(device->options), "%u",
+                       device->baud);
+       }
+
+       if (mmio || mmio32)
+               printk(KERN_INFO
+                      "Early serial console at MMIO%s 0x%llx (options '%s')\n",
+                       mmio32 ? "32" : "",
+                       (unsigned long long)port->mapbase,
+                       device->options);
+       else
+               printk(KERN_INFO
+                     "Early serial console at I/O port 0x%lx (options '%s')\n",
+                       port->iobase,
+                       device->options);
+
+       return 0;
+}
+
+static struct console early_serial8250_console __initdata = {
+       .name   = "uart",
+       .write  = early_serial8250_write,
+       .flags  = CON_PRINTBUFFER | CON_BOOT,
+       .index  = -1,
+};
+
+static int __init early_serial8250_setup(char *options)
+{
+       struct early_serial8250_device *device = &early_device;
+       int err;
+
+       if (device->port.membase || device->port.iobase)
+               return 0;
+
+       err = parse_options(device, options);
+       if (err < 0)
+               return err;
+
+       init_port(device);
+       return 0;
+}
+
+int __init setup_early_serial8250_console(char *cmdline)
+{
+       char *options;
+       int err;
+
+       options = strstr(cmdline, "uart8250,");
+       if (!options) {
+               options = strstr(cmdline, "uart,");
+               if (!options)
+                       return 0;
+       }
+
+       options = strchr(cmdline, ',') + 1;
+       err = early_serial8250_setup(options);
+       if (err < 0)
+               return err;
+
+       register_console(&early_serial8250_console);
+
+       return 0;
+}
+
+int serial8250_find_port_for_earlycon(void)
+{
+       struct early_serial8250_device *device = &early_device;
+       struct uart_port *port = &device->port;
+       int line;
+       int ret;
+
+       if (!device->port.membase && !device->port.iobase)
+               return -ENODEV;
+
+       line = serial8250_find_port(port);
+       if (line < 0)
+               return -ENODEV;
+
+       ret = update_console_cmdline("uart", 8250,
+                            "ttyS", line, device->options);
+       if (ret < 0)
+               ret = update_console_cmdline("uart", 0,
+                                    "ttyS", line, device->options);
+
+       return ret;
+}
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/tty/serial/8250/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c
new file mode 100644 (file)
index 0000000..bf53aab
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
+ *  Based on 8250_boca.
+ *
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq)                               \
+       {                                               \
+               .iobase         = _base,                \
+               .irq            = _irq,                 \
+               .uartclk        = 1843200,              \
+               .iotype         = UPIO_PORT,            \
+               .flags          = UPF_BOOT_AUTOCONF,    \
+       }
+
+static struct plat_serial8250_port exar_data[] = {
+       PORT(0x100, 5),
+       PORT(0x108, 5),
+       PORT(0x110, 5),
+       PORT(0x118, 5),
+       { },
+};
+
+static struct platform_device exar_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_EXAR_ST16C554,
+       .dev                    = {
+               .platform_data  = exar_data,
+       },
+};
+
+static int __init exar_init(void)
+{
+       return platform_device_register(&exar_device);
+}
+
+module_init(exar_init);
+
+MODULE_AUTHOR("Paul B Schroeder");
+MODULE_DESCRIPTION("8250 serial probe module for Exar cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c
new file mode 100644 (file)
index 0000000..be15826
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq)                                               \
+       {                                                               \
+               .iobase         = _base,                                \
+               .irq            = _irq,                                 \
+               .uartclk        = 1843200,                              \
+               .iotype         = UPIO_PORT,                            \
+               .flags          = UPF_BOOT_AUTOCONF | UPF_FOURPORT,     \
+       }
+
+static struct plat_serial8250_port fourport_data[] = {
+       PORT(0x1a0, 9),
+       PORT(0x1a8, 9),
+       PORT(0x1b0, 9),
+       PORT(0x1b8, 9),
+       PORT(0x2a0, 5),
+       PORT(0x2a8, 5),
+       PORT(0x2b0, 5),
+       PORT(0x2b8, 5),
+       { },
+};
+
+static struct platform_device fourport_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_FOURPORT,
+       .dev                    = {
+               .platform_data  = fourport_data,
+       },
+};
+
+static int __init fourport_init(void)
+{
+       return platform_device_register(&fourport_device);
+}
+
+module_init(fourport_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for AST Fourport cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
new file mode 100644 (file)
index 0000000..f4d3c47
--- /dev/null
@@ -0,0 +1,63 @@
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
+
+#include "8250.h"
+
+/*
+ * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker.
+ *
+ * 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 isn't a full driver; it just provides an alternate IRQ
+ * handler to deal with an errata.  Everything else is just
+ * using the bog standard 8250 support.
+ *
+ * We follow code flow of serial8250_default_handle_irq() but add
+ * a check for a break and insert a dummy read on the Rx for the
+ * immediately following IRQ event.
+ *
+ * We re-use the already existing "bug handling" lsr_saved_flags
+ * field to carry the "what we just did" information from the one
+ * IRQ event to the next one.
+ */
+
+int fsl8250_handle_irq(struct uart_port *port)
+{
+       unsigned char lsr, orig_lsr;
+       unsigned long flags;
+       unsigned int iir;
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       iir = port->serial_in(port, UART_IIR);
+       if (iir & UART_IIR_NO_INT) {
+               spin_unlock_irqrestore(&up->port.lock, flags);
+               return 0;
+       }
+
+       /* This is the WAR; if last event was BRK, then read and return */
+       if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
+               up->lsr_saved_flags &= ~UART_LSR_BI;
+               port->serial_in(port, UART_RX);
+               spin_unlock_irqrestore(&up->port.lock, flags);
+               return 1;
+       }
+
+       lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR);
+
+       if (lsr & (UART_LSR_DR | UART_LSR_BI))
+               lsr = serial8250_rx_chars(up, lsr);
+
+       serial8250_modem_status(up);
+
+       if (lsr & UART_LSR_THRE)
+               serial8250_tx_chars(up);
+
+       up->lsr_saved_flags = orig_lsr;
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       return 1;
+}
diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
new file mode 100644 (file)
index 0000000..d8c0ffb
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *     Serial Device Initialisation for Lasi/Asp/Wax/Dino
+ *
+ *     (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/serial_core.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+
+#include <asm/hardware.h>
+#include <asm/parisc-device.h>
+#include <asm/io.h>
+
+#include "8250.h"
+
+static int __init serial_init_chip(struct parisc_device *dev)
+{
+       struct uart_port port;
+       unsigned long address;
+       int err;
+
+       if (!dev->irq) {
+               /* We find some unattached serial ports by walking native
+                * busses.  These should be silently ignored.  Otherwise,
+                * what we have here is a missing parent device, so tell
+                * the user what they're missing.
+                */
+               if (parisc_parent(dev)->id.hw_type != HPHW_IOA)
+                       printk(KERN_INFO
+                               "Serial: device 0x%llx not configured.\n"
+                               "Enable support for Wax, Lasi, Asp or Dino.\n",
+                               (unsigned long long)dev->hpa.start);
+               return -ENODEV;
+       }
+
+       address = dev->hpa.start;
+       if (dev->id.sversion != 0x8d)
+               address += 0x800;
+
+       memset(&port, 0, sizeof(port));
+       port.iotype     = UPIO_MEM;
+       /* 7.272727MHz on Lasi.  Assumed the same for Dino, Wax and Timi. */
+       port.uartclk    = 7272727;
+       port.mapbase    = address;
+       port.membase    = ioremap_nocache(address, 16);
+       port.irq        = dev->irq;
+       port.flags      = UPF_BOOT_AUTOCONF;
+       port.dev        = &dev->dev;
+
+       err = serial8250_register_port(&port);
+       if (err < 0) {
+               printk(KERN_WARNING
+                       "serial8250_register_port returned error %d\n", err);
+               iounmap(port.membase);
+               return err;
+       }
+
+       return 0;
+}
+
+static struct parisc_device_id serial_tbl[] = {
+       { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 },
+       { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c },
+       { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d },
+       { 0 }
+};
+
+/* Hack.  Some machines have SERIAL_0 attached to Lasi and SERIAL_1
+ * attached to Dino.  Unfortunately, Dino appears before Lasi in the device
+ * tree.  To ensure that ttyS0 == SERIAL_0, we register two drivers; one
+ * which only knows about Lasi and then a second which will find all the
+ * other serial ports.  HPUX ignores this problem.
+ */
+static struct parisc_device_id lasi_tbl[] = {
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */
+       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */
+       { 0 }
+};
+
+
+MODULE_DEVICE_TABLE(parisc, serial_tbl);
+
+static struct parisc_driver lasi_driver = {
+       .name           = "serial_1",
+       .id_table       = lasi_tbl,
+       .probe          = serial_init_chip,
+};
+
+static struct parisc_driver serial_driver = {
+       .name           = "serial",
+       .id_table       = serial_tbl,
+       .probe          = serial_init_chip,
+};
+
+static int __init probe_serial_gsc(void)
+{
+       register_parisc_driver(&lasi_driver);
+       register_parisc_driver(&serial_driver);
+       return 0;
+}
+
+module_init(probe_serial_gsc);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
new file mode 100644 (file)
index 0000000..c13438c
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Driver for the 98626/98644/internal serial interface on hp300/hp400
+ * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
+ *
+ * Ported from 2.2 and modified to use the normal 8250 driver
+ * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/delay.h>
+#include <linux/dio.h>
+#include <linux/console.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#include "8250.h"
+
+#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
+#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
+#endif
+
+#ifdef CONFIG_HPAPCI
+struct hp300_port
+{
+       struct hp300_port *next;        /* next port */
+       int line;                       /* line (tty) number */
+};
+
+static struct hp300_port *hp300_ports;
+#endif
+
+#ifdef CONFIG_HPDCA
+
+static int __devinit hpdca_init_one(struct dio_dev *d,
+                                       const struct dio_device_id *ent);
+static void __devexit hpdca_remove_one(struct dio_dev *d);
+
+static struct dio_device_id hpdca_dio_tbl[] = {
+       { DIO_ID_DCA0 },
+       { DIO_ID_DCA0REM },
+       { DIO_ID_DCA1 },
+       { DIO_ID_DCA1REM },
+       { 0 }
+};
+
+static struct dio_driver hpdca_driver = {
+       .name      = "hpdca",
+       .id_table  = hpdca_dio_tbl,
+       .probe     = hpdca_init_one,
+       .remove    = __devexit_p(hpdca_remove_one),
+};
+
+#endif
+
+static unsigned int num_ports;
+
+extern int hp300_uart_scode;
+
+/* Offset to UART registers from base of DCA */
+#define UART_OFFSET    17
+
+#define DCA_ID         0x01    /* ID (read), reset (write) */
+#define DCA_IC         0x03    /* Interrupt control        */
+
+/* Interrupt control */
+#define DCA_IC_IE      0x80    /* Master interrupt enable  */
+
+#define HPDCA_BAUD_BASE 153600
+
+/* Base address of the Frodo part */
+#define FRODO_BASE     (0x41c000)
+
+/*
+ * Where we find the 8250-like APCI ports, and how far apart they are.
+ */
+#define FRODO_APCIBASE         0x0
+#define FRODO_APCISPACE                0x20
+#define FRODO_APCI_OFFSET(x)   (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
+
+#define HPAPCI_BAUD_BASE 500400
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+/*
+ * Parse the bootinfo to find descriptions for headless console and
+ * debug serial ports and register them with the 8250 driver.
+ * This function should be called before serial_console_init() is called
+ * to make sure the serial console will be available for use. IA-64 kernel
+ * calls this function from setup_arch() after the EFI and ACPI tables have
+ * been parsed.
+ */
+int __init hp300_setup_serial_console(void)
+{
+       int scode;
+       struct uart_port port;
+
+       memset(&port, 0, sizeof(port));
+
+       if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
+               return 0;
+
+       if (DIO_SCINHOLE(hp300_uart_scode))
+               return 0;
+
+       scode = hp300_uart_scode;
+
+       /* Memory mapped I/O */
+       port.iotype = UPIO_MEM;
+       port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+       port.type = PORT_UNKNOWN;
+
+       /* Check for APCI console */
+       if (scode == 256) {
+#ifdef CONFIG_HPAPCI
+               printk(KERN_INFO "Serial console is HP APCI 1\n");
+
+               port.uartclk = HPAPCI_BAUD_BASE * 16;
+               port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
+               port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+               port.regshift = 2;
+               add_preferred_console("ttyS", port.line, "9600n8");
+#else
+               printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
+               return 0;
+#endif
+       } else {
+#ifdef CONFIG_HPDCA
+               unsigned long pa = dio_scodetophysaddr(scode);
+               if (!pa)
+                       return 0;
+
+               printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
+
+               port.uartclk = HPDCA_BAUD_BASE * 16;
+               port.mapbase = (pa + UART_OFFSET);
+               port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+               port.regshift = 1;
+               port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
+
+               /* Enable board-interrupts */
+               out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
+
+               if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
+                       add_preferred_console("ttyS", port.line, "9600n8");
+#else
+               printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
+               return 0;
+#endif
+       }
+
+       if (early_serial_setup(&port) < 0)
+               printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
+       return 0;
+}
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+#ifdef CONFIG_HPDCA
+static int __devinit hpdca_init_one(struct dio_dev *d,
+                               const struct dio_device_id *ent)
+{
+       struct uart_port port;
+       int line;
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       if (hp300_uart_scode == d->scode) {
+               /* Already got it. */
+               return 0;
+       }
+#endif
+       memset(&port, 0, sizeof(struct uart_port));
+
+       /* Memory mapped I/O */
+       port.iotype = UPIO_MEM;
+       port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+       port.irq = d->ipl;
+       port.uartclk = HPDCA_BAUD_BASE * 16;
+       port.mapbase = (d->resource.start + UART_OFFSET);
+       port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+       port.regshift = 1;
+       port.dev = &d->dev;
+       line = serial8250_register_port(&port);
+
+       if (line < 0) {
+               printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
+                      " irq %d failed\n", d->scode, port.irq);
+               return -ENOMEM;
+       }
+
+       /* Enable board-interrupts */
+       out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
+       dio_set_drvdata(d, (void *)line);
+
+       /* Reset the DCA */
+       out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
+       udelay(100);
+
+       num_ports++;
+
+       return 0;
+}
+#endif
+
+static int __init hp300_8250_init(void)
+{
+       static int called;
+#ifdef CONFIG_HPAPCI
+       int line;
+       unsigned long base;
+       struct uart_port uport;
+       struct hp300_port *port;
+       int i;
+#endif
+       if (called)
+               return -ENODEV;
+       called = 1;
+
+       if (!MACH_IS_HP300)
+               return -ENODEV;
+
+#ifdef CONFIG_HPDCA
+       dio_register_driver(&hpdca_driver);
+#endif
+#ifdef CONFIG_HPAPCI
+       if (hp300_model < HP_400) {
+               if (!num_ports)
+                       return -ENODEV;
+               return 0;
+       }
+       /* These models have the Frodo chip.
+        * Port 0 is reserved for the Apollo Domain keyboard.
+        * Port 1 is either the console or the DCA.
+        */
+       for (i = 1; i < 4; i++) {
+               /* Port 1 is the console on a 425e, on other machines it's
+                * mapped to DCA.
+                */
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+               if (i == 1)
+                       continue;
+#endif
+
+               /* Create new serial device */
+               port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
+               if (!port)
+                       return -ENOMEM;
+
+               memset(&uport, 0, sizeof(struct uart_port));
+
+               base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
+
+               /* Memory mapped I/O */
+               uport.iotype = UPIO_MEM;
+               uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
+                             | UPF_BOOT_AUTOCONF;
+               /* XXX - no interrupt support yet */
+               uport.irq = 0;
+               uport.uartclk = HPAPCI_BAUD_BASE * 16;
+               uport.mapbase = base;
+               uport.membase = (char *)(base + DIO_VIRADDRBASE);
+               uport.regshift = 2;
+
+               line = serial8250_register_port(&uport);
+
+               if (line < 0) {
+                       printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
+                              " %d irq %d failed\n", i, uport.irq);
+                       kfree(port);
+                       continue;
+               }
+
+               port->line = line;
+               port->next = hp300_ports;
+               hp300_ports = port;
+
+               num_ports++;
+       }
+#endif
+
+       /* Any boards found? */
+       if (!num_ports)
+               return -ENODEV;
+
+       return 0;
+}
+
+#ifdef CONFIG_HPDCA
+static void __devexit hpdca_remove_one(struct dio_dev *d)
+{
+       int line;
+
+       line = (int) dio_get_drvdata(d);
+       if (d->resource.start) {
+               /* Disable board-interrupts */
+               out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
+       }
+       serial8250_unregister_port(line);
+}
+#endif
+
+static void __exit hp300_8250_exit(void)
+{
+#ifdef CONFIG_HPAPCI
+       struct hp300_port *port, *to_free;
+
+       for (port = hp300_ports; port; ) {
+               serial8250_unregister_port(port->line);
+               to_free = port;
+               port = port->next;
+               kfree(to_free);
+       }
+
+       hp300_ports = NULL;
+#endif
+#ifdef CONFIG_HPDCA
+       dio_unregister_driver(&hpdca_driver);
+#endif
+}
+
+module_init(hp300_8250_init);
+module_exit(hp300_8250_exit);
+MODULE_DESCRIPTION("HP DCA/APCI serial driver");
+MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
new file mode 100644 (file)
index 0000000..a5c778e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define HUB6(card,port)                                                        \
+       {                                                               \
+               .iobase         = 0x302,                                \
+               .irq            = 3,                                    \
+               .uartclk        = 1843200,                              \
+               .iotype         = UPIO_HUB6,                            \
+               .flags          = UPF_BOOT_AUTOCONF,                    \
+               .hub6           = (card) << 6 | (port) << 3 | 1,        \
+       }
+
+static struct plat_serial8250_port hub6_data[] = {
+       HUB6(0, 0),
+       HUB6(0, 1),
+       HUB6(0, 2),
+       HUB6(0, 3),
+       HUB6(0, 4),
+       HUB6(0, 5),
+       HUB6(1, 0),
+       HUB6(1, 1),
+       HUB6(1, 2),
+       HUB6(1, 3),
+       HUB6(1, 4),
+       HUB6(1, 5),
+       { },
+};
+
+static struct platform_device hub6_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_HUB6,
+       .dev                    = {
+               .platform_data  = hub6_data,
+       },
+};
+
+static int __init hub6_init(void)
+{
+       return platform_device_register(&hub6_device);
+}
+
+module_init(hub6_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for Hub6 cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_mca.c b/drivers/tty/serial/8250/8250_mca.c
new file mode 100644 (file)
index 0000000..d20abf0
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mca.h>
+#include <linux/serial_8250.h>
+
+/*
+ * FIXME: Should we be doing AUTO_IRQ here?
+ */
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
+#define MCA_FLAGS      UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ
+#else
+#define MCA_FLAGS      UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
+#endif
+
+#define PORT(_base,_irq)                       \
+       {                                       \
+               .iobase         = _base,        \
+               .irq            = _irq,         \
+               .uartclk        = 1843200,      \
+               .iotype         = UPIO_PORT,    \
+               .flags          = MCA_FLAGS,    \
+       }
+
+static struct plat_serial8250_port mca_data[] = {
+       PORT(0x3220, 3),
+       PORT(0x3228, 3),
+       PORT(0x4220, 3),
+       PORT(0x4228, 3),
+       PORT(0x5220, 3),
+       PORT(0x5228, 3),
+       { },
+};
+
+static struct platform_device mca_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_MCA,
+       .dev                    = {
+               .platform_data  = mca_data,
+       },
+};
+
+static int __init mca_init(void)
+{
+       if (!MCA_bus)
+               return -ENODEV;
+       return platform_device_register(&mca_device);
+}
+
+module_init(mca_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("8250 serial probe module for MCA ports");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
new file mode 100644 (file)
index 0000000..da2b0b0
--- /dev/null
@@ -0,0 +1,4223 @@
+/*
+ *  Probe module for 8250/16550-type PCI serial ports.
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/8250_pci.h>
+#include <linux/bitops.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include "8250.h"
+
+#undef SERIAL_DEBUG_PCI
+
+/*
+ * init function returns:
+ *  > 0 - number of ports
+ *  = 0 - use board->num_ports
+ *  < 0 - error
+ */
+struct pci_serial_quirk {
+       u32     vendor;
+       u32     device;
+       u32     subvendor;
+       u32     subdevice;
+       int     (*probe)(struct pci_dev *dev);
+       int     (*init)(struct pci_dev *dev);
+       int     (*setup)(struct serial_private *,
+                        const struct pciserial_board *,
+                        struct uart_port *, int);
+       void    (*exit)(struct pci_dev *dev);
+};
+
+#define PCI_NUM_BAR_RESOURCES  6
+
+struct serial_private {
+       struct pci_dev          *dev;
+       unsigned int            nr;
+       void __iomem            *remapped_bar[PCI_NUM_BAR_RESOURCES];
+       struct pci_serial_quirk *quirk;
+       int                     line[0];
+};
+
+static int pci_default_setup(struct serial_private*,
+         const struct pciserial_board*, struct uart_port*, int);
+
+static void moan_device(const char *str, struct pci_dev *dev)
+{
+       printk(KERN_WARNING
+              "%s: %s\n"
+              "Please send the output of lspci -vv, this\n"
+              "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+              "manufacturer and name of serial board or\n"
+              "modem board to rmk+serial@arm.linux.org.uk.\n",
+              pci_name(dev), str, dev->vendor, dev->device,
+              dev->subsystem_vendor, dev->subsystem_device);
+}
+
+static int
+setup_port(struct serial_private *priv, struct uart_port *port,
+          int bar, int offset, int regshift)
+{
+       struct pci_dev *dev = priv->dev;
+       unsigned long base, len;
+
+       if (bar >= PCI_NUM_BAR_RESOURCES)
+               return -EINVAL;
+
+       base = pci_resource_start(dev, bar);
+
+       if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
+               len =  pci_resource_len(dev, bar);
+
+               if (!priv->remapped_bar[bar])
+                       priv->remapped_bar[bar] = ioremap_nocache(base, len);
+               if (!priv->remapped_bar[bar])
+                       return -ENOMEM;
+
+               port->iotype = UPIO_MEM;
+               port->iobase = 0;
+               port->mapbase = base + offset;
+               port->membase = priv->remapped_bar[bar] + offset;
+               port->regshift = regshift;
+       } else {
+               port->iotype = UPIO_PORT;
+               port->iobase = base + offset;
+               port->mapbase = 0;
+               port->membase = NULL;
+               port->regshift = 0;
+       }
+       return 0;
+}
+
+/*
+ * ADDI-DATA GmbH communication cards <info@addi-data.com>
+ */
+static int addidata_apci7800_setup(struct serial_private *priv,
+                               const struct pciserial_board *board,
+                               struct uart_port *port, int idx)
+{
+       unsigned int bar = 0, offset = board->first_offset;
+       bar = FL_GET_BASE(board->flags);
+
+       if (idx < 2) {
+               offset += idx * board->uart_offset;
+       } else if ((idx >= 2) && (idx < 4)) {
+               bar += 1;
+               offset += ((idx - 2) * board->uart_offset);
+       } else if ((idx >= 4) && (idx < 6)) {
+               bar += 2;
+               offset += ((idx - 4) * board->uart_offset);
+       } else if (idx >= 6) {
+               bar += 3;
+               offset += ((idx - 6) * board->uart_offset);
+       }
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * AFAVLAB uses a different mixture of BARs and offsets
+ * Not that ugly ;) -- HW
+ */
+static int
+afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
+             struct uart_port *port, int idx)
+{
+       unsigned int bar, offset = board->first_offset;
+
+       bar = FL_GET_BASE(board->flags);
+       if (idx < 4)
+               bar += idx;
+       else {
+               bar = 4;
+               offset += (idx - 4) * board->uart_offset;
+       }
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * HP's Remote Management Console.  The Diva chip came in several
+ * different versions.  N-class, L2000 and A500 have two Diva chips, each
+ * with 3 UARTs (the third UART on the second chip is unused).  Superdome
+ * and Keystone have one Diva chip with 3 UARTs.  Some later machines have
+ * one Diva chip, but it has been expanded to 5 UARTs.
+ */
+static int pci_hp_diva_init(struct pci_dev *dev)
+{
+       int rc = 0;
+
+       switch (dev->subsystem_device) {
+       case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
+       case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
+       case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
+       case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+               rc = 3;
+               break;
+       case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
+               rc = 2;
+               break;
+       case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+               rc = 4;
+               break;
+       case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
+       case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
+               rc = 1;
+               break;
+       }
+
+       return rc;
+}
+
+/*
+ * HP's Diva chip puts the 4th/5th serial port further out, and
+ * some serial ports are supposed to be hidden on certain models.
+ */
+static int
+pci_hp_diva_setup(struct serial_private *priv,
+               const struct pciserial_board *board,
+               struct uart_port *port, int idx)
+{
+       unsigned int offset = board->first_offset;
+       unsigned int bar = FL_GET_BASE(board->flags);
+
+       switch (priv->dev->subsystem_device) {
+       case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+               if (idx == 3)
+                       idx++;
+               break;
+       case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+               if (idx > 0)
+                       idx++;
+               if (idx > 2)
+                       idx++;
+               break;
+       }
+       if (idx > 2)
+               offset = 0x18;
+
+       offset += idx * board->uart_offset;
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * Added for EKF Intel i960 serial boards
+ */
+static int pci_inteli960ni_init(struct pci_dev *dev)
+{
+       unsigned long oldval;
+
+       if (!(dev->subsystem_device & 0x1000))
+               return -ENODEV;
+
+       /* is firmware started? */
+       pci_read_config_dword(dev, 0x44, (void *)&oldval);
+       if (oldval == 0x00001000L) { /* RESET value */
+               printk(KERN_DEBUG "Local i960 firmware missing");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+/*
+ * Some PCI serial cards using the PLX 9050 PCI interface chip require
+ * that the card interrupt be explicitly enabled or disabled.  This
+ * seems to be mainly needed on card using the PLX which also use I/O
+ * mapped memory.
+ */
+static int pci_plx9050_init(struct pci_dev *dev)
+{
+       u8 irq_config;
+       void __iomem *p;
+
+       if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
+               moan_device("no memory in bar 0", dev);
+               return 0;
+       }
+
+       irq_config = 0x41;
+       if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
+           dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
+               irq_config = 0x43;
+
+       if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
+           (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
+               /*
+                * As the megawolf cards have the int pins active
+                * high, and have 2 UART chips, both ints must be
+                * enabled on the 9050. Also, the UARTS are set in
+                * 16450 mode by default, so we have to enable the
+                * 16C950 'enhanced' mode so that we can use the
+                * deep FIFOs
+                */
+               irq_config = 0x5b;
+       /*
+        * enable/disable interrupts
+        */
+       p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
+       if (p == NULL)
+               return -ENOMEM;
+       writel(irq_config, p + 0x4c);
+
+       /*
+        * Read the register back to ensure that it took effect.
+        */
+       readl(p + 0x4c);
+       iounmap(p);
+
+       return 0;
+}
+
+static void __devexit pci_plx9050_exit(struct pci_dev *dev)
+{
+       u8 __iomem *p;
+
+       if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
+               return;
+
+       /*
+        * disable interrupts
+        */
+       p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
+       if (p != NULL) {
+               writel(0, p + 0x4c);
+
+               /*
+                * Read the register back to ensure that it took effect.
+                */
+               readl(p + 0x4c);
+               iounmap(p);
+       }
+}
+
+#define NI8420_INT_ENABLE_REG  0x38
+#define NI8420_INT_ENABLE_BIT  0x2000
+
+static void __devexit pci_ni8420_exit(struct pci_dev *dev)
+{
+       void __iomem *p;
+       unsigned long base, len;
+       unsigned int bar = 0;
+
+       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+               moan_device("no memory in bar", dev);
+               return;
+       }
+
+       base = pci_resource_start(dev, bar);
+       len =  pci_resource_len(dev, bar);
+       p = ioremap_nocache(base, len);
+       if (p == NULL)
+               return;
+
+       /* Disable the CPU Interrupt */
+       writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT),
+              p + NI8420_INT_ENABLE_REG);
+       iounmap(p);
+}
+
+
+/* MITE registers */
+#define MITE_IOWBSR1   0xc4
+#define MITE_IOWCR1    0xf4
+#define MITE_LCIMR1    0x08
+#define MITE_LCIMR2    0x10
+
+#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
+
+static void __devexit pci_ni8430_exit(struct pci_dev *dev)
+{
+       void __iomem *p;
+       unsigned long base, len;
+       unsigned int bar = 0;
+
+       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+               moan_device("no memory in bar", dev);
+               return;
+       }
+
+       base = pci_resource_start(dev, bar);
+       len =  pci_resource_len(dev, bar);
+       p = ioremap_nocache(base, len);
+       if (p == NULL)
+               return;
+
+       /* Disable the CPU Interrupt */
+       writel(MITE_LCIMR2_CLR_CPU_IE, p + MITE_LCIMR2);
+       iounmap(p);
+}
+
+/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
+static int
+sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
+               struct uart_port *port, int idx)
+{
+       unsigned int bar, offset = board->first_offset;
+
+       bar = 0;
+
+       if (idx < 4) {
+               /* first four channels map to 0, 0x100, 0x200, 0x300 */
+               offset += idx * board->uart_offset;
+       } else if (idx < 8) {
+               /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
+               offset += idx * board->uart_offset + 0xC00;
+       } else /* we have only 8 ports on PMC-OCTALPRO */
+               return 1;
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+* This does initialization for PMC OCTALPRO cards:
+* maps the device memory, resets the UARTs (needed, bc
+* if the module is removed and inserted again, the card
+* is in the sleep mode) and enables global interrupt.
+*/
+
+/* global control register offset for SBS PMC-OctalPro */
+#define OCT_REG_CR_OFF         0x500
+
+static int sbs_init(struct pci_dev *dev)
+{
+       u8 __iomem *p;
+
+       p = pci_ioremap_bar(dev, 0);
+
+       if (p == NULL)
+               return -ENOMEM;
+       /* Set bit-4 Control Register (UART RESET) in to reset the uarts */
+       writeb(0x10, p + OCT_REG_CR_OFF);
+       udelay(50);
+       writeb(0x0, p + OCT_REG_CR_OFF);
+
+       /* Set bit-2 (INTENABLE) of Control Register */
+       writeb(0x4, p + OCT_REG_CR_OFF);
+       iounmap(p);
+
+       return 0;
+}
+
+/*
+ * Disables the global interrupt of PMC-OctalPro
+ */
+
+static void __devexit sbs_exit(struct pci_dev *dev)
+{
+       u8 __iomem *p;
+
+       p = pci_ioremap_bar(dev, 0);
+       /* FIXME: What if resource_len < OCT_REG_CR_OFF */
+       if (p != NULL)
+               writeb(0, p + OCT_REG_CR_OFF);
+       iounmap(p);
+}
+
+/*
+ * SIIG serial cards have an PCI interface chip which also controls
+ * the UART clocking frequency. Each UART can be clocked independently
+ * (except cards equipped with 4 UARTs) and initial clocking settings
+ * are stored in the EEPROM chip. It can cause problems because this
+ * version of serial driver doesn't support differently clocked UART's
+ * on single PCI card. To prevent this, initialization functions set
+ * high frequency clocking for all UART's on given card. It is safe (I
+ * hope) because it doesn't touch EEPROM settings to prevent conflicts
+ * with other OSes (like M$ DOS).
+ *
+ *  SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
+ *
+ * There is two family of SIIG serial cards with different PCI
+ * interface chip and different configuration methods:
+ *     - 10x cards have control registers in IO and/or memory space;
+ *     - 20x cards have control registers in standard PCI configuration space.
+ *
+ * Note: all 10x cards have PCI device ids 0x10..
+ *       all 20x cards have PCI device ids 0x20..
+ *
+ * There are also Quartet Serial cards which use Oxford Semiconductor
+ * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
+ *
+ * Note: some SIIG cards are probed by the parport_serial object.
+ */
+
+#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
+#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
+
+static int pci_siig10x_init(struct pci_dev *dev)
+{
+       u16 data;
+       void __iomem *p;
+
+       switch (dev->device & 0xfff8) {
+       case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
+               data = 0xffdf;
+               break;
+       case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
+               data = 0xf7ff;
+               break;
+       default:                        /* 1S1P, 4S */
+               data = 0xfffb;
+               break;
+       }
+
+       p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
+       if (p == NULL)
+               return -ENOMEM;
+
+       writew(readw(p + 0x28) & data, p + 0x28);
+       readw(p + 0x28);
+       iounmap(p);
+       return 0;
+}
+
+#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
+#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
+
+static int pci_siig20x_init(struct pci_dev *dev)
+{
+       u8 data;
+
+       /* Change clock frequency for the first UART. */
+       pci_read_config_byte(dev, 0x6f, &data);
+       pci_write_config_byte(dev, 0x6f, data & 0xef);
+
+       /* If this card has 2 UART, we have to do the same with second UART. */
+       if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
+           ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
+               pci_read_config_byte(dev, 0x73, &data);
+               pci_write_config_byte(dev, 0x73, data & 0xef);
+       }
+       return 0;
+}
+
+static int pci_siig_init(struct pci_dev *dev)
+{
+       unsigned int type = dev->device & 0xff00;
+
+       if (type == 0x1000)
+               return pci_siig10x_init(dev);
+       else if (type == 0x2000)
+               return pci_siig20x_init(dev);
+
+       moan_device("Unknown SIIG card", dev);
+       return -ENODEV;
+}
+
+static int pci_siig_setup(struct serial_private *priv,
+                         const struct pciserial_board *board,
+                         struct uart_port *port, int idx)
+{
+       unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
+
+       if (idx > 3) {
+               bar = 4;
+               offset = (idx - 4) * 8;
+       }
+
+       return setup_port(priv, port, bar, offset, 0);
+}
+
+/*
+ * Timedia has an explosion of boards, and to avoid the PCI table from
+ * growing *huge*, we use this function to collapse some 70 entries
+ * in the PCI table into one, for sanity's and compactness's sake.
+ */
+static const unsigned short timedia_single_port[] = {
+       0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
+};
+
+static const unsigned short timedia_dual_port[] = {
+       0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
+       0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
+       0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
+       0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
+       0xD079, 0
+};
+
+static const unsigned short timedia_quad_port[] = {
+       0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
+       0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
+       0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
+       0xB157, 0
+};
+
+static const unsigned short timedia_eight_port[] = {
+       0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
+       0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
+};
+
+static const struct timedia_struct {
+       int num;
+       const unsigned short *ids;
+} timedia_data[] = {
+       { 1, timedia_single_port },
+       { 2, timedia_dual_port },
+       { 4, timedia_quad_port },
+       { 8, timedia_eight_port }
+};
+
+/*
+ * There are nearly 70 different Timedia/SUNIX PCI serial devices.  Instead of
+ * listing them individually, this driver merely grabs them all with
+ * PCI_ANY_ID.  Some of these devices, however, also feature a parallel port,
+ * and should be left free to be claimed by parport_serial instead.
+ */
+static int pci_timedia_probe(struct pci_dev *dev)
+{
+       /*
+        * Check the third digit of the subdevice ID
+        * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
+        */
+       if ((dev->subsystem_device & 0x00f0) >= 0x70) {
+               dev_info(&dev->dev,
+                       "ignoring Timedia subdevice %04x for parport_serial\n",
+                       dev->subsystem_device);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int pci_timedia_init(struct pci_dev *dev)
+{
+       const unsigned short *ids;
+       int i, j;
+
+       for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
+               ids = timedia_data[i].ids;
+               for (j = 0; ids[j]; j++)
+                       if (dev->subsystem_device == ids[j])
+                               return timedia_data[i].num;
+       }
+       return 0;
+}
+
+/*
+ * Timedia/SUNIX uses a mixture of BARs and offsets
+ * Ugh, this is ugly as all hell --- TYT
+ */
+static int
+pci_timedia_setup(struct serial_private *priv,
+                 const struct pciserial_board *board,
+                 struct uart_port *port, int idx)
+{
+       unsigned int bar = 0, offset = board->first_offset;
+
+       switch (idx) {
+       case 0:
+               bar = 0;
+               break;
+       case 1:
+               offset = board->uart_offset;
+               bar = 0;
+               break;
+       case 2:
+               bar = 1;
+               break;
+       case 3:
+               offset = board->uart_offset;
+               /* FALLTHROUGH */
+       case 4: /* BAR 2 */
+       case 5: /* BAR 3 */
+       case 6: /* BAR 4 */
+       case 7: /* BAR 5 */
+               bar = idx - 2;
+       }
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+/*
+ * Some Titan cards are also a little weird
+ */
+static int
+titan_400l_800l_setup(struct serial_private *priv,
+                     const struct pciserial_board *board,
+                     struct uart_port *port, int idx)
+{
+       unsigned int bar, offset = board->first_offset;
+
+       switch (idx) {
+       case 0:
+               bar = 1;
+               break;
+       case 1:
+               bar = 2;
+               break;
+       default:
+               bar = 4;
+               offset = (idx - 2) * board->uart_offset;
+       }
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+static int pci_xircom_init(struct pci_dev *dev)
+{
+       msleep(100);
+       return 0;
+}
+
+static int pci_ni8420_init(struct pci_dev *dev)
+{
+       void __iomem *p;
+       unsigned long base, len;
+       unsigned int bar = 0;
+
+       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+               moan_device("no memory in bar", dev);
+               return 0;
+       }
+
+       base = pci_resource_start(dev, bar);
+       len =  pci_resource_len(dev, bar);
+       p = ioremap_nocache(base, len);
+       if (p == NULL)
+               return -ENOMEM;
+
+       /* Enable CPU Interrupt */
+       writel(readl(p + NI8420_INT_ENABLE_REG) | NI8420_INT_ENABLE_BIT,
+              p + NI8420_INT_ENABLE_REG);
+
+       iounmap(p);
+       return 0;
+}
+
+#define MITE_IOWBSR1_WSIZE     0xa
+#define MITE_IOWBSR1_WIN_OFFSET        0x800
+#define MITE_IOWBSR1_WENAB     (1 << 7)
+#define MITE_LCIMR1_IO_IE_0    (1 << 24)
+#define MITE_LCIMR2_SET_CPU_IE (1 << 31)
+#define MITE_IOWCR1_RAMSEL_MASK        0xfffffffe
+
+static int pci_ni8430_init(struct pci_dev *dev)
+{
+       void __iomem *p;
+       unsigned long base, len;
+       u32 device_window;
+       unsigned int bar = 0;
+
+       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
+               moan_device("no memory in bar", dev);
+               return 0;
+       }
+
+       base = pci_resource_start(dev, bar);
+       len =  pci_resource_len(dev, bar);
+       p = ioremap_nocache(base, len);
+       if (p == NULL)
+               return -ENOMEM;
+
+       /* Set device window address and size in BAR0 */
+       device_window = ((base + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00)
+                       | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE;
+       writel(device_window, p + MITE_IOWBSR1);
+
+       /* Set window access to go to RAMSEL IO address space */
+       writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
+              p + MITE_IOWCR1);
+
+       /* Enable IO Bus Interrupt 0 */
+       writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
+
+       /* Enable CPU Interrupt */
+       writel(MITE_LCIMR2_SET_CPU_IE, p + MITE_LCIMR2);
+
+       iounmap(p);
+       return 0;
+}
+
+/* UART Port Control Register */
+#define NI8430_PORTCON 0x0f
+#define NI8430_PORTCON_TXVR_ENABLE     (1 << 3)
+
+static int
+pci_ni8430_setup(struct serial_private *priv,
+                const struct pciserial_board *board,
+                struct uart_port *port, int idx)
+{
+       void __iomem *p;
+       unsigned long base, len;
+       unsigned int bar, offset = board->first_offset;
+
+       if (idx >= board->num_ports)
+               return 1;
+
+       bar = FL_GET_BASE(board->flags);
+       offset += idx * board->uart_offset;
+
+       base = pci_resource_start(priv->dev, bar);
+       len =  pci_resource_len(priv->dev, bar);
+       p = ioremap_nocache(base, len);
+
+       /* enable the transceiver */
+       writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
+              p + offset + NI8430_PORTCON);
+
+       iounmap(p);
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+static int pci_netmos_9900_setup(struct serial_private *priv,
+                               const struct pciserial_board *board,
+                               struct uart_port *port, int idx)
+{
+       unsigned int bar;
+
+       if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
+               /* netmos apparently orders BARs by datasheet layout, so serial
+                * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
+                */
+               bar = 3 * idx;
+
+               return setup_port(priv, port, bar, 0, board->reg_shift);
+       } else {
+               return pci_default_setup(priv, board, port, idx);
+       }
+}
+
+/* the 99xx series comes with a range of device IDs and a variety
+ * of capabilities:
+ *
+ * 9900 has varying capabilities and can cascade to sub-controllers
+ *   (cascading should be purely internal)
+ * 9904 is hardwired with 4 serial ports
+ * 9912 and 9922 are hardwired with 2 serial ports
+ */
+static int pci_netmos_9900_numports(struct pci_dev *dev)
+{
+       unsigned int c = dev->class;
+       unsigned int pi;
+       unsigned short sub_serports;
+
+       pi = (c & 0xff);
+
+       if (pi == 2) {
+               return 1;
+       } else if ((pi == 0) &&
+                          (dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
+               /* two possibilities: 0x30ps encodes number of parallel and
+                * serial ports, or 0x1000 indicates *something*. This is not
+                * immediately obvious, since the 2s1p+4s configuration seems
+                * to offer all functionality on functions 0..2, while still
+                * advertising the same function 3 as the 4s+2s1p config.
+                */
+               sub_serports = dev->subsystem_device & 0xf;
+               if (sub_serports > 0) {
+                       return sub_serports;
+               } else {
+                       printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+                       return 0;
+               }
+       }
+
+       moan_device("unknown NetMos/Mostech program interface", dev);
+       return 0;
+}
+
+static int pci_netmos_init(struct pci_dev *dev)
+{
+       /* subdevice 0x00PS means <P> parallel, <S> serial */
+       unsigned int num_serial = dev->subsystem_device & 0xf;
+
+       if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
+               (dev->device == PCI_DEVICE_ID_NETMOS_9865))
+               return 0;
+
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
+                       dev->subsystem_device == 0x0299)
+               return 0;
+
+       switch (dev->device) { /* FALLTHROUGH on all */
+               case PCI_DEVICE_ID_NETMOS_9904:
+               case PCI_DEVICE_ID_NETMOS_9912:
+               case PCI_DEVICE_ID_NETMOS_9922:
+               case PCI_DEVICE_ID_NETMOS_9900:
+                       num_serial = pci_netmos_9900_numports(dev);
+                       break;
+
+               default:
+                       if (num_serial == 0 ) {
+                               moan_device("unknown NetMos/Mostech device", dev);
+                       }
+       }
+
+       if (num_serial == 0)
+               return -ENODEV;
+
+       return num_serial;
+}
+
+/*
+ * These chips are available with optionally one parallel port and up to
+ * two serial ports. Unfortunately they all have the same product id.
+ *
+ * Basic configuration is done over a region of 32 I/O ports. The base
+ * ioport is called INTA or INTC, depending on docs/other drivers.
+ *
+ * The region of the 32 I/O ports is configured in POSIO0R...
+ */
+
+/* registers */
+#define ITE_887x_MISCR         0x9c
+#define ITE_887x_INTCBAR       0x78
+#define ITE_887x_UARTBAR       0x7c
+#define ITE_887x_PS0BAR                0x10
+#define ITE_887x_POSIO0                0x60
+
+/* I/O space size */
+#define ITE_887x_IOSIZE                32
+/* I/O space size (bits 26-24; 8 bytes = 011b) */
+#define ITE_887x_POSIO_IOSIZE_8                (3 << 24)
+/* I/O space size (bits 26-24; 32 bytes = 101b) */
+#define ITE_887x_POSIO_IOSIZE_32       (5 << 24)
+/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */
+#define ITE_887x_POSIO_SPEED           (3 << 29)
+/* enable IO_Space bit */
+#define ITE_887x_POSIO_ENABLE          (1 << 31)
+
+static int pci_ite887x_init(struct pci_dev *dev)
+{
+       /* inta_addr are the configuration addresses of the ITE */
+       static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
+                                                       0x200, 0x280, 0 };
+       int ret, i, type;
+       struct resource *iobase = NULL;
+       u32 miscr, uartbar, ioport;
+
+       /* search for the base-ioport */
+       i = 0;
+       while (inta_addr[i] && iobase == NULL) {
+               iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
+                                                               "ite887x");
+               if (iobase != NULL) {
+                       /* write POSIO0R - speed | size | ioport */
+                       pci_write_config_dword(dev, ITE_887x_POSIO0,
+                               ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
+                               ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]);
+                       /* write INTCBAR - ioport */
+                       pci_write_config_dword(dev, ITE_887x_INTCBAR,
+                                                               inta_addr[i]);
+                       ret = inb(inta_addr[i]);
+                       if (ret != 0xff) {
+                               /* ioport connected */
+                               break;
+                       }
+                       release_region(iobase->start, ITE_887x_IOSIZE);
+                       iobase = NULL;
+               }
+               i++;
+       }
+
+       if (!inta_addr[i]) {
+               printk(KERN_ERR "ite887x: could not find iobase\n");
+               return -ENODEV;
+       }
+
+       /* start of undocumented type checking (see parport_pc.c) */
+       type = inb(iobase->start + 0x18) & 0x0f;
+
+       switch (type) {
+       case 0x2:       /* ITE8871 (1P) */
+       case 0xa:       /* ITE8875 (1P) */
+               ret = 0;
+               break;
+       case 0xe:       /* ITE8872 (2S1P) */
+               ret = 2;
+               break;
+       case 0x6:       /* ITE8873 (1S) */
+               ret = 1;
+               break;
+       case 0x8:       /* ITE8874 (2S) */
+               ret = 2;
+               break;
+       default:
+               moan_device("Unknown ITE887x", dev);
+               ret = -ENODEV;
+       }
+
+       /* configure all serial ports */
+       for (i = 0; i < ret; i++) {
+               /* read the I/O port from the device */
+               pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),
+                                                               &ioport);
+               ioport &= 0x0000FF00;   /* the actual base address */
+               pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),
+                       ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
+                       ITE_887x_POSIO_IOSIZE_8 | ioport);
+
+               /* write the ioport to the UARTBAR */
+               pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);
+               uartbar &= ~(0xffff << (16 * i));       /* clear half the reg */
+               uartbar |= (ioport << (16 * i));        /* set the ioport */
+               pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);
+
+               /* get current config */
+               pci_read_config_dword(dev, ITE_887x_MISCR, &miscr);
+               /* disable interrupts (UARTx_Routing[3:0]) */
+               miscr &= ~(0xf << (12 - 4 * i));
+               /* activate the UART (UARTx_En) */
+               miscr |= 1 << (23 - i);
+               /* write new config with activated UART */
+               pci_write_config_dword(dev, ITE_887x_MISCR, miscr);
+       }
+
+       if (ret <= 0) {
+               /* the device has no UARTs if we get here */
+               release_region(iobase->start, ITE_887x_IOSIZE);
+       }
+
+       return ret;
+}
+
+static void __devexit pci_ite887x_exit(struct pci_dev *dev)
+{
+       u32 ioport;
+       /* the ioport is bit 0-15 in POSIO0R */
+       pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
+       ioport &= 0xffff;
+       release_region(ioport, ITE_887x_IOSIZE);
+}
+
+/*
+ * Oxford Semiconductor Inc.
+ * Check that device is part of the Tornado range of devices, then determine
+ * the number of ports available on the device.
+ */
+static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+{
+       u8 __iomem *p;
+       unsigned long deviceID;
+       unsigned int  number_uarts = 0;
+
+       /* OxSemi Tornado devices are all 0xCxxx */
+       if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+           (dev->device & 0xF000) != 0xC000)
+               return 0;
+
+       p = pci_iomap(dev, 0, 5);
+       if (p == NULL)
+               return -ENOMEM;
+
+       deviceID = ioread32(p);
+       /* Tornado device */
+       if (deviceID == 0x07000200) {
+               number_uarts = ioread8(p + 4);
+               printk(KERN_DEBUG
+                       "%d ports detected on Oxford PCI Express device\n",
+                                                               number_uarts);
+       }
+       pci_iounmap(dev, p);
+       return number_uarts;
+}
+
+static int
+pci_default_setup(struct serial_private *priv,
+                 const struct pciserial_board *board,
+                 struct uart_port *port, int idx)
+{
+       unsigned int bar, offset = board->first_offset, maxnr;
+
+       bar = FL_GET_BASE(board->flags);
+       if (board->flags & FL_BASE_BARS)
+               bar += idx;
+       else
+               offset += idx * board->uart_offset;
+
+       maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
+               (board->reg_shift + 3);
+
+       if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
+               return 1;
+
+       return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
+static int
+ce4100_serial_setup(struct serial_private *priv,
+                 const struct pciserial_board *board,
+                 struct uart_port *port, int idx)
+{
+       int ret;
+
+       ret = setup_port(priv, port, 0, 0, board->reg_shift);
+       port->iotype = UPIO_MEM32;
+       port->type = PORT_XSCALE;
+       port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+       port->regshift = 2;
+
+       return ret;
+}
+
+static int
+pci_omegapci_setup(struct serial_private *priv,
+                     const struct pciserial_board *board,
+                     struct uart_port *port, int idx)
+{
+       return setup_port(priv, port, 2, idx * 8, 0);
+}
+
+static int skip_tx_en_setup(struct serial_private *priv,
+                       const struct pciserial_board *board,
+                       struct uart_port *port, int idx)
+{
+       port->flags |= UPF_NO_TXEN_TEST;
+       printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
+                         "[%04x:%04x] subsystem [%04x:%04x]\n",
+                         priv->dev->vendor,
+                         priv->dev->device,
+                         priv->dev->subsystem_vendor,
+                         priv->dev->subsystem_device);
+
+       return pci_default_setup(priv, board, port, idx);
+}
+
+static int kt_serial_setup(struct serial_private *priv,
+                          const struct pciserial_board *board,
+                          struct uart_port *port, int idx)
+{
+       port->flags |= UPF_IIR_ONCE;
+       return skip_tx_en_setup(priv, board, port, idx);
+}
+
+static int pci_eg20t_init(struct pci_dev *dev)
+{
+#if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE)
+       return -ENODEV;
+#else
+       return 0;
+#endif
+}
+
+static int
+pci_xr17c154_setup(struct serial_private *priv,
+                 const struct pciserial_board *board,
+                 struct uart_port *port, int idx)
+{
+       port->flags |= UPF_EXAR_EFR;
+       return pci_default_setup(priv, board, port, idx);
+}
+
+static int try_enable_msi(struct pci_dev *dev)
+{
+       /* use msi if available, but fallback to legacy otherwise */
+       pci_enable_msi(dev);
+       return 0;
+}
+
+static void disable_msi(struct pci_dev *dev)
+{
+       pci_disable_msi(dev);
+}
+
+#define PCI_VENDOR_ID_SBSMODULARIO     0x124B
+#define PCI_SUBVENDOR_ID_SBSMODULARIO  0x124B
+#define PCI_DEVICE_ID_OCTPRO           0x0001
+#define PCI_SUBDEVICE_ID_OCTPRO232     0x0108
+#define PCI_SUBDEVICE_ID_OCTPRO422     0x0208
+#define PCI_SUBDEVICE_ID_POCTAL232     0x0308
+#define PCI_SUBDEVICE_ID_POCTAL422     0x0408
+#define PCI_VENDOR_ID_ADVANTECH                0x13fe
+#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
+#define PCI_DEVICE_ID_ADVANTECH_PCI3620        0x3620
+#define PCI_DEVICE_ID_TITAN_200I       0x8028
+#define PCI_DEVICE_ID_TITAN_400I       0x8048
+#define PCI_DEVICE_ID_TITAN_800I       0x8088
+#define PCI_DEVICE_ID_TITAN_800EH      0xA007
+#define PCI_DEVICE_ID_TITAN_800EHB     0xA008
+#define PCI_DEVICE_ID_TITAN_400EH      0xA009
+#define PCI_DEVICE_ID_TITAN_100E       0xA010
+#define PCI_DEVICE_ID_TITAN_200E       0xA012
+#define PCI_DEVICE_ID_TITAN_400E       0xA013
+#define PCI_DEVICE_ID_TITAN_800E       0xA014
+#define PCI_DEVICE_ID_TITAN_200EI      0xA016
+#define PCI_DEVICE_ID_TITAN_200EISI    0xA017
+#define PCI_DEVICE_ID_TITAN_400V3      0xA310
+#define PCI_DEVICE_ID_TITAN_410V3      0xA312
+#define PCI_DEVICE_ID_TITAN_800V3      0xA314
+#define PCI_DEVICE_ID_TITAN_800V3B     0xA315
+#define PCI_DEVICE_ID_OXSEMI_16PCI958  0x9538
+#define PCIE_DEVICE_ID_NEO_2_OX_IBM    0x00F6
+#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
+#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+
+/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
+
+/*
+ * Master list of serial port init/setup/exit quirks.
+ * This does not describe the general nature of the port.
+ * (ie, baud base, number and location of ports, etc)
+ *
+ * This list is ordered alphabetically by vendor then device.
+ * Specific entries must come before more generic entries.
+ */
+static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+       /*
+       * ADDI-DATA GmbH communication cards <info@addi-data.com>
+       */
+       {
+               .vendor         = PCI_VENDOR_ID_ADDIDATA_OLD,
+               .device         = PCI_DEVICE_ID_ADDIDATA_APCI7800,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = addidata_apci7800_setup,
+       },
+       /*
+        * AFAVLAB cards - these may be called via parport_serial
+        *  It is not clear whether this applies to all products.
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_AFAVLAB,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = afavlab_setup,
+       },
+       /*
+        * HP Diva
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_HP,
+               .device         = PCI_DEVICE_ID_HP_DIVA,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_hp_diva_init,
+               .setup          = pci_hp_diva_setup,
+       },
+       /*
+        * Intel
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_80960_RP,
+               .subvendor      = 0xe4bf,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_inteli960ni_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_8257X_SOL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = skip_tx_en_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_82573L_SOL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = skip_tx_en_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_82573E_SOL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = skip_tx_en_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_CE4100_UART,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = ce4100_serial_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = try_enable_msi,
+               .setup          = kt_serial_setup,
+               .exit           = disable_msi,
+       },
+       /*
+        * ITE
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_ITE,
+               .device         = PCI_DEVICE_ID_ITE_8872,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ite887x_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ite887x_exit),
+       },
+       /*
+        * National Instruments
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PCI23216,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PCI2328,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PCI2324,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PCI2322,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PCI2324I,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PCI2322I,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PXI8420_23216,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PXI8420_2328,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PXI8420_2324,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PXI8420_2322,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PXI8422_2324,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_DEVICE_ID_NI_PXI8422_2322,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8420_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_ni8420_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_NI,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_ni8430_init,
+               .setup          = pci_ni8430_setup,
+               .exit           = __devexit_p(pci_ni8430_exit),
+       },
+       /*
+        * Panacom
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_PANACOM,
+               .device         = PCI_DEVICE_ID_PANACOM_QUADMODEM,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_PANACOM,
+               .device         = PCI_DEVICE_ID_PANACOM_DUALMODEM,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
+       /*
+        * PLX
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_9030,
+               .subvendor      = PCI_SUBVENDOR_ID_PERLE,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_9050,
+               .subvendor      = PCI_SUBVENDOR_ID_EXSYS,
+               .subdevice      = PCI_SUBDEVICE_ID_EXSYS_4055,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_9050,
+               .subvendor      = PCI_SUBVENDOR_ID_KEYSPAN,
+               .subdevice      = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_9050,
+               .subvendor      = PCI_VENDOR_ID_PLX,
+               .subdevice      = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_ROMULUS,
+               .subvendor      = PCI_VENDOR_ID_PLX,
+               .subdevice      = PCI_DEVICE_ID_PLX_ROMULUS,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
+       /*
+        * SBS Technologies, Inc., PMC-OCTALPRO 232
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
+               .device         = PCI_DEVICE_ID_OCTPRO,
+               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
+               .subdevice      = PCI_SUBDEVICE_ID_OCTPRO232,
+               .init           = sbs_init,
+               .setup          = sbs_setup,
+               .exit           = __devexit_p(sbs_exit),
+       },
+       /*
+        * SBS Technologies, Inc., PMC-OCTALPRO 422
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
+               .device         = PCI_DEVICE_ID_OCTPRO,
+               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
+               .subdevice      = PCI_SUBDEVICE_ID_OCTPRO422,
+               .init           = sbs_init,
+               .setup          = sbs_setup,
+               .exit           = __devexit_p(sbs_exit),
+       },
+       /*
+        * SBS Technologies, Inc., P-Octal 232
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
+               .device         = PCI_DEVICE_ID_OCTPRO,
+               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
+               .subdevice      = PCI_SUBDEVICE_ID_POCTAL232,
+               .init           = sbs_init,
+               .setup          = sbs_setup,
+               .exit           = __devexit_p(sbs_exit),
+       },
+       /*
+        * SBS Technologies, Inc., P-Octal 422
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
+               .device         = PCI_DEVICE_ID_OCTPRO,
+               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
+               .subdevice      = PCI_SUBDEVICE_ID_POCTAL422,
+               .init           = sbs_init,
+               .setup          = sbs_setup,
+               .exit           = __devexit_p(sbs_exit),
+       },
+       /*
+        * SIIG cards - these may be called via parport_serial
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_SIIG,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_siig_init,
+               .setup          = pci_siig_setup,
+       },
+       /*
+        * Titan cards
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_TITAN,
+               .device         = PCI_DEVICE_ID_TITAN_400L,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = titan_400l_800l_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_TITAN,
+               .device         = PCI_DEVICE_ID_TITAN_800L,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = titan_400l_800l_setup,
+       },
+       /*
+        * Timedia cards
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_TIMEDIA,
+               .device         = PCI_DEVICE_ID_TIMEDIA_1889,
+               .subvendor      = PCI_VENDOR_ID_TIMEDIA,
+               .subdevice      = PCI_ANY_ID,
+               .probe          = pci_timedia_probe,
+               .init           = pci_timedia_init,
+               .setup          = pci_timedia_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_TIMEDIA,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_timedia_setup,
+       },
+       /*
+        * Exar cards
+        */
+       {
+               .vendor = PCI_VENDOR_ID_EXAR,
+               .device = PCI_DEVICE_ID_EXAR_XR17C152,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_xr17c154_setup,
+       },
+       {
+               .vendor = PCI_VENDOR_ID_EXAR,
+               .device = PCI_DEVICE_ID_EXAR_XR17C154,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_xr17c154_setup,
+       },
+       {
+               .vendor = PCI_VENDOR_ID_EXAR,
+               .device = PCI_DEVICE_ID_EXAR_XR17C158,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_xr17c154_setup,
+       },
+       /*
+        * Xircom cards
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_XIRCOM,
+               .device         = PCI_DEVICE_ID_XIRCOM_X3201_MDM,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_xircom_init,
+               .setup          = pci_default_setup,
+       },
+       /*
+        * Netmos cards - these may be called via parport_serial
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_NETMOS,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_netmos_init,
+               .setup          = pci_netmos_9900_setup,
+       },
+       /*
+        * For Oxford Semiconductor Tornado based devices
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_OXSEMI,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_oxsemi_tornado_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_MAINPINE,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .init           = pci_oxsemi_tornado_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_DIGI,
+               .device         = PCIE_DEVICE_ID_NEO_2_OX_IBM,
+               .subvendor              = PCI_SUBVENDOR_ID_IBM,
+               .subdevice              = PCI_ANY_ID,
+               .init                   = pci_oxsemi_tornado_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = 0x8811,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = 0x8812,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = 0x8813,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = 0x8814,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = 0x10DB,
+               .device         = 0x8027,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = 0x10DB,
+               .device         = 0x8028,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = 0x10DB,
+               .device         = 0x8029,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = 0x10DB,
+               .device         = 0x800C,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       {
+               .vendor         = 0x10DB,
+               .device         = 0x800D,
+               .init           = pci_eg20t_init,
+               .setup          = pci_default_setup,
+       },
+       /*
+        * Cronyx Omega PCI (PLX-chip based)
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_omegapci_setup,
+        },
+       /*
+        * Default "match everything" terminator entry
+        */
+       {
+               .vendor         = PCI_ANY_ID,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_default_setup,
+       }
+};
+
+static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
+{
+       return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
+}
+
+static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
+{
+       struct pci_serial_quirk *quirk;
+
+       for (quirk = pci_serial_quirks; ; quirk++)
+               if (quirk_id_matches(quirk->vendor, dev->vendor) &&
+                   quirk_id_matches(quirk->device, dev->device) &&
+                   quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
+                   quirk_id_matches(quirk->subdevice, dev->subsystem_device))
+                       break;
+       return quirk;
+}
+
+static inline int get_pci_irq(struct pci_dev *dev,
+                               const struct pciserial_board *board)
+{
+       if (board->flags & FL_NOIRQ)
+               return 0;
+       else
+               return dev->irq;
+}
+
+/*
+ * This is the configuration table for all of the PCI serial boards
+ * which we support.  It is directly indexed by the pci_board_num_t enum
+ * value, which is encoded in the pci_device_id PCI probe table's
+ * driver_data member.
+ *
+ * The makeup of these names are:
+ *  pbn_bn{_bt}_n_baud{_offsetinhex}
+ *
+ *  bn         = PCI BAR number
+ *  bt         = Index using PCI BARs
+ *  n          = number of serial ports
+ *  baud       = baud rate
+ *  offsetinhex        = offset for each sequential port (in hex)
+ *
+ * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
+ *
+ * Please note: in theory if n = 1, _bt infix should make no difference.
+ * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
+ */
+enum pci_board_num_t {
+       pbn_default = 0,
+
+       pbn_b0_1_115200,
+       pbn_b0_2_115200,
+       pbn_b0_4_115200,
+       pbn_b0_5_115200,
+       pbn_b0_8_115200,
+
+       pbn_b0_1_921600,
+       pbn_b0_2_921600,
+       pbn_b0_4_921600,
+
+       pbn_b0_2_1130000,
+
+       pbn_b0_4_1152000,
+
+       pbn_b0_2_1843200,
+       pbn_b0_4_1843200,
+
+       pbn_b0_2_1843200_200,
+       pbn_b0_4_1843200_200,
+       pbn_b0_8_1843200_200,
+
+       pbn_b0_1_4000000,
+
+       pbn_b0_bt_1_115200,
+       pbn_b0_bt_2_115200,
+       pbn_b0_bt_4_115200,
+       pbn_b0_bt_8_115200,
+
+       pbn_b0_bt_1_460800,
+       pbn_b0_bt_2_460800,
+       pbn_b0_bt_4_460800,
+
+       pbn_b0_bt_1_921600,
+       pbn_b0_bt_2_921600,
+       pbn_b0_bt_4_921600,
+       pbn_b0_bt_8_921600,
+
+       pbn_b1_1_115200,
+       pbn_b1_2_115200,
+       pbn_b1_4_115200,
+       pbn_b1_8_115200,
+       pbn_b1_16_115200,
+
+       pbn_b1_1_921600,
+       pbn_b1_2_921600,
+       pbn_b1_4_921600,
+       pbn_b1_8_921600,
+
+       pbn_b1_2_1250000,
+
+       pbn_b1_bt_1_115200,
+       pbn_b1_bt_2_115200,
+       pbn_b1_bt_4_115200,
+
+       pbn_b1_bt_2_921600,
+
+       pbn_b1_1_1382400,
+       pbn_b1_2_1382400,
+       pbn_b1_4_1382400,
+       pbn_b1_8_1382400,
+
+       pbn_b2_1_115200,
+       pbn_b2_2_115200,
+       pbn_b2_4_115200,
+       pbn_b2_8_115200,
+
+       pbn_b2_1_460800,
+       pbn_b2_4_460800,
+       pbn_b2_8_460800,
+       pbn_b2_16_460800,
+
+       pbn_b2_1_921600,
+       pbn_b2_4_921600,
+       pbn_b2_8_921600,
+
+       pbn_b2_8_1152000,
+
+       pbn_b2_bt_1_115200,
+       pbn_b2_bt_2_115200,
+       pbn_b2_bt_4_115200,
+
+       pbn_b2_bt_2_921600,
+       pbn_b2_bt_4_921600,
+
+       pbn_b3_2_115200,
+       pbn_b3_4_115200,
+       pbn_b3_8_115200,
+
+       pbn_b4_bt_2_921600,
+       pbn_b4_bt_4_921600,
+       pbn_b4_bt_8_921600,
+
+       /*
+        * Board-specific versions.
+        */
+       pbn_panacom,
+       pbn_panacom2,
+       pbn_panacom4,
+       pbn_exsys_4055,
+       pbn_plx_romulus,
+       pbn_oxsemi,
+       pbn_oxsemi_1_4000000,
+       pbn_oxsemi_2_4000000,
+       pbn_oxsemi_4_4000000,
+       pbn_oxsemi_8_4000000,
+       pbn_intel_i960,
+       pbn_sgi_ioc3,
+       pbn_computone_4,
+       pbn_computone_6,
+       pbn_computone_8,
+       pbn_sbsxrsio,
+       pbn_exar_XR17C152,
+       pbn_exar_XR17C154,
+       pbn_exar_XR17C158,
+       pbn_exar_ibm_saturn,
+       pbn_pasemi_1682M,
+       pbn_ni8430_2,
+       pbn_ni8430_4,
+       pbn_ni8430_8,
+       pbn_ni8430_16,
+       pbn_ADDIDATA_PCIe_1_3906250,
+       pbn_ADDIDATA_PCIe_2_3906250,
+       pbn_ADDIDATA_PCIe_4_3906250,
+       pbn_ADDIDATA_PCIe_8_3906250,
+       pbn_ce4100_1_115200,
+       pbn_omegapci,
+       pbn_NETMOS9900_2s_115200,
+};
+
+/*
+ * uart_offset - the space between channels
+ * reg_shift   - describes how the UART registers are mapped
+ *               to PCI memory by the card.
+ * For example IER register on SBS, Inc. PMC-OctPro is located at
+ * offset 0x10 from the UART base, while UART_IER is defined as 1
+ * in include/linux/serial_reg.h,
+ * see first lines of serial_in() and serial_out() in 8250.c
+*/
+
+static struct pciserial_board pci_boards[] __devinitdata = {
+       [pbn_default] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_1_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_2_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_4_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_5_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 5,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_8_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_1_921600] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_2_921600] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_4_921600] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_2_1130000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 1130000,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_4_1152000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 1152000,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_2_1843200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 1843200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_4_1843200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 1843200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_2_1843200_200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 1843200,
+               .uart_offset    = 0x200,
+       },
+       [pbn_b0_4_1843200_200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 1843200,
+               .uart_offset    = 0x200,
+       },
+       [pbn_b0_8_1843200_200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 1843200,
+               .uart_offset    = 0x200,
+       },
+       [pbn_b0_1_4000000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 4000000,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_bt_1_115200] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_2_115200] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_4_115200] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_8_115200] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_bt_1_460800] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_2_460800] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_4_460800] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b0_bt_1_921600] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_2_921600] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_4_921600] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b0_bt_8_921600] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b1_1_115200] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_2_115200] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_4_115200] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_8_115200] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_16_115200] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 16,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b1_1_921600] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_2_921600] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_4_921600] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_8_921600] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_2_1250000] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 2,
+               .base_baud      = 1250000,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b1_bt_1_115200] = {
+               .flags          = FL_BASE1|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_bt_2_115200] = {
+               .flags          = FL_BASE1|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_bt_4_115200] = {
+               .flags          = FL_BASE1|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b1_bt_2_921600] = {
+               .flags          = FL_BASE1|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b1_1_1382400] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 1,
+               .base_baud      = 1382400,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_2_1382400] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 2,
+               .base_baud      = 1382400,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_4_1382400] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 4,
+               .base_baud      = 1382400,
+               .uart_offset    = 8,
+       },
+       [pbn_b1_8_1382400] = {
+               .flags          = FL_BASE1,
+               .num_ports      = 8,
+               .base_baud      = 1382400,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b2_1_115200] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_2_115200] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_4_115200] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_8_115200] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b2_1_460800] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 1,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_4_460800] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 4,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_8_460800] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 8,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_16_460800] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 16,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+        },
+
+       [pbn_b2_1_921600] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_4_921600] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_8_921600] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b2_8_1152000] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 8,
+               .base_baud      = 1152000,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b2_bt_1_115200] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_bt_2_115200] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_bt_4_115200] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b2_bt_2_921600] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b2_bt_4_921600] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b3_2_115200] = {
+               .flags          = FL_BASE3,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b3_4_115200] = {
+               .flags          = FL_BASE3,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_b3_8_115200] = {
+               .flags          = FL_BASE3,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       [pbn_b4_bt_2_921600] = {
+               .flags          = FL_BASE4,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b4_bt_4_921600] = {
+               .flags          = FL_BASE4,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b4_bt_8_921600] = {
+               .flags          = FL_BASE4,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
+       /*
+        * Entries following this are board-specific.
+        */
+
+       /*
+        * Panacom - IOMEM
+        */
+       [pbn_panacom] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 0x400,
+               .reg_shift      = 7,
+       },
+       [pbn_panacom2] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 0x400,
+               .reg_shift      = 7,
+       },
+       [pbn_panacom4] = {
+               .flags          = FL_BASE2|FL_BASE_BARS,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 0x400,
+               .reg_shift      = 7,
+       },
+
+       [pbn_exsys_4055] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 4,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+
+       /* I think this entry is broken - the first_offset looks wrong --rmk */
+       [pbn_plx_romulus] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8 << 2,
+               .reg_shift      = 2,
+               .first_offset   = 0x03,
+       },
+
+       /*
+        * This board uses the size of PCI Base region 0 to
+        * signal now many ports are available
+        */
+       [pbn_oxsemi] = {
+               .flags          = FL_BASE0|FL_REGION_SZ_CAP,
+               .num_ports      = 32,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [pbn_oxsemi_1_4000000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 4000000,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_oxsemi_2_4000000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 4000000,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_oxsemi_4_4000000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 4000000,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_oxsemi_8_4000000] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 4000000,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+
+
+       /*
+        * EKF addition for i960 Boards form EKF with serial port.
+        * Max 256 ports.
+        */
+       [pbn_intel_i960] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 32,
+               .base_baud      = 921600,
+               .uart_offset    = 8 << 2,
+               .reg_shift      = 2,
+               .first_offset   = 0x10000,
+       },
+       [pbn_sgi_ioc3] = {
+               .flags          = FL_BASE0|FL_NOIRQ,
+               .num_ports      = 1,
+               .base_baud      = 458333,
+               .uart_offset    = 8,
+               .reg_shift      = 0,
+               .first_offset   = 0x20178,
+       },
+
+       /*
+        * Computone - uses IOMEM.
+        */
+       [pbn_computone_4] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 0x40,
+               .reg_shift      = 2,
+               .first_offset   = 0x200,
+       },
+       [pbn_computone_6] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 6,
+               .base_baud      = 921600,
+               .uart_offset    = 0x40,
+               .reg_shift      = 2,
+               .first_offset   = 0x200,
+       },
+       [pbn_computone_8] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 0x40,
+               .reg_shift      = 2,
+               .first_offset   = 0x200,
+       },
+       [pbn_sbsxrsio] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 460800,
+               .uart_offset    = 256,
+               .reg_shift      = 4,
+       },
+       /*
+        * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+        *  Only basic 16550A support.
+        *  XR17C15[24] are not tested, but they should work.
+        */
+       [pbn_exar_XR17C152] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 0x200,
+       },
+       [pbn_exar_XR17C154] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 0x200,
+       },
+       [pbn_exar_XR17C158] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 0x200,
+       },
+       [pbn_exar_ibm_saturn] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 0x200,
+       },
+
+       /*
+        * PA Semi PWRficient PA6T-1682M on-chip UART
+        */
+       [pbn_pasemi_1682M] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 8333333,
+       },
+       /*
+        * National Instruments 843x
+        */
+       [pbn_ni8430_16] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 16,
+               .base_baud      = 3686400,
+               .uart_offset    = 0x10,
+               .first_offset   = 0x800,
+       },
+       [pbn_ni8430_8] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 3686400,
+               .uart_offset    = 0x10,
+               .first_offset   = 0x800,
+       },
+       [pbn_ni8430_4] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 3686400,
+               .uart_offset    = 0x10,
+               .first_offset   = 0x800,
+       },
+       [pbn_ni8430_2] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 3686400,
+               .uart_offset    = 0x10,
+               .first_offset   = 0x800,
+       },
+       /*
+        * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
+        */
+       [pbn_ADDIDATA_PCIe_1_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ADDIDATA_PCIe_2_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ADDIDATA_PCIe_4_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ADDIDATA_PCIe_8_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ce4100_1_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .reg_shift      = 2,
+       },
+       [pbn_omegapci] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 0x200,
+       },
+       [pbn_NETMOS9900_2s_115200] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+       },
+};
+
+static const struct pci_device_id softmodem_blacklist[] = {
+       { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
+       { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
+       { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
+};
+
+/*
+ * Given a complete unknown PCI device, try to use some heuristics to
+ * guess what the configuration might be, based on the pitiful PCI
+ * serial specs.  Returns 0 on success, 1 on failure.
+ */
+static int __devinit
+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
+{
+       const struct pci_device_id *blacklist;
+       int num_iomem, num_port, first_port = -1, i;
+
+       /*
+        * If it is not a communications device or the programming
+        * interface is greater than 6, give up.
+        *
+        * (Should we try to make guesses for multiport serial devices
+        * later?)
+        */
+       if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
+            ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
+           (dev->class & 0xff) > 6)
+               return -ENODEV;
+
+       /*
+        * Do not access blacklisted devices that are known not to
+        * feature serial ports.
+        */
+       for (blacklist = softmodem_blacklist;
+            blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
+            blacklist++) {
+               if (dev->vendor == blacklist->vendor &&
+                   dev->device == blacklist->device)
+                       return -ENODEV;
+       }
+
+       num_iomem = num_port = 0;
+       for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+               if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
+                       num_port++;
+                       if (first_port == -1)
+                               first_port = i;
+               }
+               if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
+                       num_iomem++;
+       }
+
+       /*
+        * If there is 1 or 0 iomem regions, and exactly one port,
+        * use it.  We guess the number of ports based on the IO
+        * region size.
+        */
+       if (num_iomem <= 1 && num_port == 1) {
+               board->flags = first_port;
+               board->num_ports = pci_resource_len(dev, first_port) / 8;
+               return 0;
+       }
+
+       /*
+        * Now guess if we've got a board which indexes by BARs.
+        * Each IO BAR should be 8 bytes, and they should follow
+        * consecutively.
+        */
+       first_port = -1;
+       num_port = 0;
+       for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+               if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
+                   pci_resource_len(dev, i) == 8 &&
+                   (first_port == -1 || (first_port + num_port) == i)) {
+                       num_port++;
+                       if (first_port == -1)
+                               first_port = i;
+               }
+       }
+
+       if (num_port > 1) {
+               board->flags = first_port | FL_BASE_BARS;
+               board->num_ports = num_port;
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static inline int
+serial_pci_matches(const struct pciserial_board *board,
+                  const struct pciserial_board *guessed)
+{
+       return
+           board->num_ports == guessed->num_ports &&
+           board->base_baud == guessed->base_baud &&
+           board->uart_offset == guessed->uart_offset &&
+           board->reg_shift == guessed->reg_shift &&
+           board->first_offset == guessed->first_offset;
+}
+
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
+{
+       struct uart_port serial_port;
+       struct serial_private *priv;
+       struct pci_serial_quirk *quirk;
+       int rc, nr_ports, i;
+
+       nr_ports = board->num_ports;
+
+       /*
+        * Find an init and setup quirks.
+        */
+       quirk = find_quirk(dev);
+
+       /*
+        * Run the new-style initialization function.
+        * The initialization function returns:
+        *  <0  - error
+        *   0  - use board->num_ports
+        *  >0  - number of ports
+        */
+       if (quirk->init) {
+               rc = quirk->init(dev);
+               if (rc < 0) {
+                       priv = ERR_PTR(rc);
+                       goto err_out;
+               }
+               if (rc)
+                       nr_ports = rc;
+       }
+
+       priv = kzalloc(sizeof(struct serial_private) +
+                      sizeof(unsigned int) * nr_ports,
+                      GFP_KERNEL);
+       if (!priv) {
+               priv = ERR_PTR(-ENOMEM);
+               goto err_deinit;
+       }
+
+       priv->dev = dev;
+       priv->quirk = quirk;
+
+       memset(&serial_port, 0, sizeof(struct uart_port));
+       serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+       serial_port.uartclk = board->base_baud * 16;
+       serial_port.irq = get_pci_irq(dev, board);
+       serial_port.dev = &dev->dev;
+
+       for (i = 0; i < nr_ports; i++) {
+               if (quirk->setup(priv, board, &serial_port, i))
+                       break;
+
+#ifdef SERIAL_DEBUG_PCI
+               printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
+                      serial_port.iobase, serial_port.irq, serial_port.iotype);
+#endif
+
+               priv->line[i] = serial8250_register_port(&serial_port);
+               if (priv->line[i] < 0) {
+                       printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
+                       break;
+               }
+       }
+       priv->nr = i;
+       return priv;
+
+err_deinit:
+       if (quirk->exit)
+               quirk->exit(dev);
+err_out:
+       return priv;
+}
+EXPORT_SYMBOL_GPL(pciserial_init_ports);
+
+void pciserial_remove_ports(struct serial_private *priv)
+{
+       struct pci_serial_quirk *quirk;
+       int i;
+
+       for (i = 0; i < priv->nr; i++)
+               serial8250_unregister_port(priv->line[i]);
+
+       for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+               if (priv->remapped_bar[i])
+                       iounmap(priv->remapped_bar[i]);
+               priv->remapped_bar[i] = NULL;
+       }
+
+       /*
+        * Find the exit quirks.
+        */
+       quirk = find_quirk(priv->dev);
+       if (quirk->exit)
+               quirk->exit(priv->dev);
+
+       kfree(priv);
+}
+EXPORT_SYMBOL_GPL(pciserial_remove_ports);
+
+void pciserial_suspend_ports(struct serial_private *priv)
+{
+       int i;
+
+       for (i = 0; i < priv->nr; i++)
+               if (priv->line[i] >= 0)
+                       serial8250_suspend_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
+
+void pciserial_resume_ports(struct serial_private *priv)
+{
+       int i;
+
+       /*
+        * Ensure that the board is correctly configured.
+        */
+       if (priv->quirk->init)
+               priv->quirk->init(priv->dev);
+
+       for (i = 0; i < priv->nr; i++)
+               if (priv->line[i] >= 0)
+                       serial8250_resume_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_resume_ports);
+
+/*
+ * Probe one serial board.  Unfortunately, there is no rhyme nor reason
+ * to the arrangement of serial ports on a PCI card.
+ */
+static int __devinit
+pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+       struct pci_serial_quirk *quirk;
+       struct serial_private *priv;
+       const struct pciserial_board *board;
+       struct pciserial_board tmp;
+       int rc;
+
+       quirk = find_quirk(dev);
+       if (quirk->probe) {
+               rc = quirk->probe(dev);
+               if (rc)
+                       return rc;
+       }
+
+       if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+               printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
+                       ent->driver_data);
+               return -EINVAL;
+       }
+
+       board = &pci_boards[ent->driver_data];
+
+       rc = pci_enable_device(dev);
+       pci_save_state(dev);
+       if (rc)
+               return rc;
+
+       if (ent->driver_data == pbn_default) {
+               /*
+                * Use a copy of the pci_board entry for this;
+                * avoid changing entries in the table.
+                */
+               memcpy(&tmp, board, sizeof(struct pciserial_board));
+               board = &tmp;
+
+               /*
+                * We matched one of our class entries.  Try to
+                * determine the parameters of this board.
+                */
+               rc = serial_pci_guess_board(dev, &tmp);
+               if (rc)
+                       goto disable;
+       } else {
+               /*
+                * We matched an explicit entry.  If we are able to
+                * detect this boards settings with our heuristic,
+                * then we no longer need this entry.
+                */
+               memcpy(&tmp, &pci_boards[pbn_default],
+                      sizeof(struct pciserial_board));
+               rc = serial_pci_guess_board(dev, &tmp);
+               if (rc == 0 && serial_pci_matches(board, &tmp))
+                       moan_device("Redundant entry in serial pci_table.",
+                                   dev);
+       }
+
+       priv = pciserial_init_ports(dev, board);
+       if (!IS_ERR(priv)) {
+               pci_set_drvdata(dev, priv);
+               return 0;
+       }
+
+       rc = PTR_ERR(priv);
+
+ disable:
+       pci_disable_device(dev);
+       return rc;
+}
+
+static void __devexit pciserial_remove_one(struct pci_dev *dev)
+{
+       struct serial_private *priv = pci_get_drvdata(dev);
+
+       pci_set_drvdata(dev, NULL);
+
+       pciserial_remove_ports(priv);
+
+       pci_disable_device(dev);
+}
+
+#ifdef CONFIG_PM
+static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
+{
+       struct serial_private *priv = pci_get_drvdata(dev);
+
+       if (priv)
+               pciserial_suspend_ports(priv);
+
+       pci_save_state(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+       return 0;
+}
+
+static int pciserial_resume_one(struct pci_dev *dev)
+{
+       int err;
+       struct serial_private *priv = pci_get_drvdata(dev);
+
+       pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
+
+       if (priv) {
+               /*
+                * The device may have been disabled.  Re-enable it.
+                */
+               err = pci_enable_device(dev);
+               /* FIXME: We cannot simply error out here */
+               if (err)
+                       printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
+               pciserial_resume_ports(priv);
+       }
+       return 0;
+}
+#endif
+
+static struct pci_device_id serial_pci_tbl[] = {
+       /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
+       {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
+               PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
+               pbn_b2_8_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
+               pbn_b1_8_1382400 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
+               pbn_b1_4_1382400 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
+               pbn_b1_2_1382400 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
+               pbn_b1_8_1382400 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
+               pbn_b1_4_1382400 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
+               pbn_b1_2_1382400 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
+               pbn_b1_8_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
+               pbn_b1_8_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
+               pbn_b1_4_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
+               pbn_b1_4_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
+               pbn_b1_2_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
+               pbn_b1_8_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
+               pbn_b1_8_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
+               pbn_b1_4_921600 },
+       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
+               pbn_b1_2_1250000 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
+               pbn_b0_2_1843200 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
+               pbn_b0_4_1843200 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+               PCI_VENDOR_ID_AFAVLAB,
+               PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
+               pbn_b0_4_1152000 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
+               pbn_b0_2_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
+               pbn_b0_4_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
+               pbn_b0_8_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
+               pbn_b0_2_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
+               pbn_b0_4_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
+               pbn_b0_8_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
+               pbn_b0_2_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
+               pbn_b0_4_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
+               pbn_b0_8_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
+               pbn_b0_2_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
+               pbn_b0_4_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+               PCI_SUBVENDOR_ID_CONNECT_TECH,
+               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
+               pbn_b0_8_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
+               0, 0, pbn_exar_ibm_saturn },
+
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_1_115200 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_115200 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_4_115200 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_115200 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_4_115200 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_8_115200 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_8_460800 },
+       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_8_115200 },
+
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_115200 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_921600 },
+       /*
+        * VScom SPCOM800, from sl@s.pl
+        */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_8_921600 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_4_921600 },
+       /* Unknown card - subdevice 0x1584 */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_VENDOR_ID_PLX,
+               PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
+               pbn_b0_4_115200 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_KEYSPAN,
+               PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
+               pbn_panacom },
+       {       PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_panacom4 },
+       {       PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_panacom2 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+               PCI_VENDOR_ID_ESDGMBH,
+               PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0,
+               pbn_b2_4_115200 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+               PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
+               pbn_b2_4_460800 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+               PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
+               pbn_b2_8_460800 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+               PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
+               pbn_b2_16_460800 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+               PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
+               pbn_b2_16_460800 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+               PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
+               pbn_b2_4_460800 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+               PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
+               pbn_b2_8_460800 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_SUBVENDOR_ID_EXSYS,
+               PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
+               pbn_exsys_4055 },
+       /*
+        * Megawolf Romulus PCI Serial Card, from Mike Hudson
+        * (Exoray@isys.ca)
+        */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
+               0x10b5, 0x106a, 0, 0,
+               pbn_plx_romulus },
+       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_4_115200 },
+       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_2_115200 },
+       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_8_115200 },
+       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_8_115200 },
+       {       PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
+               PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
+               0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL,
+               0, 0,
+               pbn_b0_4_1152000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0x9505,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_921600 },
+
+               /*
+                * The below card is a little controversial since it is the
+                * subject of a PCI vendor/device ID clash.  (See
+                * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html).
+                * For now just used the hex ID 0x950a.
+                */
+       {       PCI_VENDOR_ID_OXSEMI, 0x950a,
+               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
+               pbn_b0_2_115200 },
+       {       PCI_VENDOR_ID_OXSEMI, 0x950a,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_2_1130000 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950,
+               PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0,
+               pbn_b0_1_921600 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_115200 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_921600 },
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
+               PCI_ANY_ID , PCI_ANY_ID, 0, 0,
+               pbn_b2_8_1152000 },
+
+       /*
+        * Oxford Semiconductor Inc. Tornado PCI express device range.
+        */
+       {       PCI_VENDOR_ID_OXSEMI, 0xc101,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc105,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc11b,    /* OXPCIe952 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc11f,    /* OXPCIe952 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc120,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc124,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc138,    /* OXPCIe952 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc13d,    /* OXPCIe952 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc140,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc141,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc144,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc145,    /* OXPCIe952 1 Legacy UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc158,    /* OXPCIe952 2 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc15d,    /* OXPCIe952 2 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc208,    /* OXPCIe954 4 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_4_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc20d,    /* OXPCIe954 4 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_4_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc308,    /* OXPCIe958 8 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_8_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc30d,    /* OXPCIe958 8 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_8_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc40b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc40f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc41b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc41f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc42b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc42f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc43b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc43f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc44b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc44f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc45b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc45f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc46b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc46f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc47b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc47f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc48b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc48f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc49b,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc49f,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc4ab,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc4af,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc4bb,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc4bf,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc4cb,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_OXSEMI, 0xc4cf,    /* OXPCIe200 1 Native UART */
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       /*
+        * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
+        */
+       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
+               PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
+               PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
+               PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
+               pbn_oxsemi_4_4000000 },
+       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
+               PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
+               pbn_oxsemi_8_4000000 },
+
+       /*
+        * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
+        */
+       {       PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+               PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+
+       /*
+        * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
+        * from skokodyn@yahoo.com
+        */
+       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0,
+               pbn_sbsxrsio },
+       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0,
+               pbn_sbsxrsio },
+       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0,
+               pbn_sbsxrsio },
+       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
+               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0,
+               pbn_sbsxrsio },
+
+       /*
+        * Digitan DS560-558, from jimd@esoft.com
+        */
+       {       PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_1_115200 },
+
+       /*
+        * Titan Electronic cards
+        *  The 400L and 800L have a custom setup quirk.
+        */
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_2_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_1_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_2_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_8_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b4_bt_2_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b4_bt_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b4_bt_8_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_4_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_8_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_410V3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_1_460800 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_1_460800 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_1_460800 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_4_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_4_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_4_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_4_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_4_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_4_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_8_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_8_921600 },
+       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_8_921600 },
+
+       /*
+        * Computone devices submitted by Doug McNash dmcnash@computone.com
+        */
+       {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+               PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
+               0, 0, pbn_computone_4 },
+       {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+               PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
+               0, 0, pbn_computone_8 },
+       {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+               PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
+               0, 0, pbn_computone_6 },
+
+       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi },
+       {       PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
+               PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_1_921600 },
+
+       /*
+        * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
+        */
+       {       PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_8_115200 },
+       {       PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_8_115200 },
+
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_115200 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_115200 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_115200 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_115200 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_115200 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_4_460800 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_4_460800 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_460800 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_460800 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_2_460800 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_1_115200 },
+       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_bt_1_460800 },
+
+       /*
+        * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
+        * Cards are identified by their subsystem vendor IDs, which
+        * (in hex) match the model number.
+        *
+        * Note that JC140x are RS422/485 cards which require ox950
+        * ACR = 0x10, and as such are not currently fully supported.
+        */
+       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+               0x1204, 0x0004, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+               0x1208, 0x0004, 0, 0,
+               pbn_b0_4_921600 },
+/*     {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+               0x1402, 0x0002, 0, 0,
+               pbn_b0_2_921600 }, */
+/*     {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+               0x1404, 0x0004, 0, 0,
+               pbn_b0_4_921600 }, */
+       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
+               0x1208, 0x0004, 0, 0,
+               pbn_b0_4_921600 },
+
+       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
+               0x1204, 0x0004, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
+               0x1208, 0x0004, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
+               0x1208, 0x0004, 0, 0,
+               pbn_b0_4_921600 },
+       /*
+        * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
+        */
+       {       PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_1_1382400 },
+
+       /*
+        * Dell Remote Access Card III - Tim_T_Murphy@Dell.com
+        */
+       {       PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_1_1382400 },
+
+       /*
+        * RAStel 2 port modem, gerg@moreton.com.au
+        */
+       {       PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_bt_2_115200 },
+
+       /*
+        * EKF addition for i960 Boards form EKF with serial port
+        */
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
+               0xE4BF, PCI_ANY_ID, 0, 0,
+               pbn_intel_i960 },
+
+       /*
+        * Xircom Cardbus/Ethernet combos
+        */
+       {       PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_115200 },
+       /*
+        * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
+        */
+       {       PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_115200 },
+
+       /*
+        * Untested PCI modems, sent in from various folks...
+        */
+
+       /*
+        * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
+        */
+       {       PCI_VENDOR_ID_ROCKWELL, 0x1004,
+               0x1048, 0x1500, 0, 0,
+               pbn_b1_1_115200 },
+
+       {       PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+               0xFF00, 0, 0, 0,
+               pbn_sgi_ioc3 },
+
+       /*
+        * HP Diva card
+        */
+       {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+               PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0,
+               pbn_b1_1_115200 },
+       {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_5_115200 },
+       {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b2_1_115200 },
+
+       {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b3_2_115200 },
+       {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b3_4_115200 },
+       {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b3_8_115200 },
+
+       /*
+        * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+        */
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_exar_XR17C152 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_exar_XR17C154 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_exar_XR17C158 },
+
+       /*
+        * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
+        */
+       {       PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_1_115200 },
+       /*
+        * ITE
+        */
+       {       PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0,
+               pbn_b1_bt_1_115200 },
+
+       /*
+        * IntaShield IS-200
+        */
+       {       PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,   /* 135a.0811 */
+               pbn_b2_2_115200 },
+       /*
+        * IntaShield IS-400
+        */
+       {       PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,    /* 135a.0dc0 */
+               pbn_b2_4_115200 },
+       /*
+        * Perle PCI-RAS cards
+        */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+               PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
+               0, 0, pbn_b2_4_921600 },
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+               PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
+               0, 0, pbn_b2_8_921600 },
+
+       /*
+        * Mainpine series cards: Fairly standard layout but fools
+        * parts of the autodetect in some cases and uses otherwise
+        * unmatched communications subclasses in the PCI Express case
+        */
+
+       {       /* RockForceDUO */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0200,
+               0, 0, pbn_b0_2_115200 },
+       {       /* RockForceQUATRO */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0300,
+               0, 0, pbn_b0_4_115200 },
+       {       /* RockForceDUO+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0400,
+               0, 0, pbn_b0_2_115200 },
+       {       /* RockForceQUATRO+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0500,
+               0, 0, pbn_b0_4_115200 },
+       {       /* RockForce+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0600,
+               0, 0, pbn_b0_2_115200 },
+       {       /* RockForce+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0700,
+               0, 0, pbn_b0_4_115200 },
+       {       /* RockForceOCTO+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0800,
+               0, 0, pbn_b0_8_115200 },
+       {       /* RockForceDUO+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0C00,
+               0, 0, pbn_b0_2_115200 },
+       {       /* RockForceQUARTRO+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x0D00,
+               0, 0, pbn_b0_4_115200 },
+       {       /* RockForceOCTO+ */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x1D00,
+               0, 0, pbn_b0_8_115200 },
+       {       /* RockForceD1 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2000,
+               0, 0, pbn_b0_1_115200 },
+       {       /* RockForceF1 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2100,
+               0, 0, pbn_b0_1_115200 },
+       {       /* RockForceD2 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2200,
+               0, 0, pbn_b0_2_115200 },
+       {       /* RockForceF2 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2300,
+               0, 0, pbn_b0_2_115200 },
+       {       /* RockForceD4 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2400,
+               0, 0, pbn_b0_4_115200 },
+       {       /* RockForceF4 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2500,
+               0, 0, pbn_b0_4_115200 },
+       {       /* RockForceD8 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2600,
+               0, 0, pbn_b0_8_115200 },
+       {       /* RockForceF8 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x2700,
+               0, 0, pbn_b0_8_115200 },
+       {       /* IQ Express D1 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3000,
+               0, 0, pbn_b0_1_115200 },
+       {       /* IQ Express F1 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3100,
+               0, 0, pbn_b0_1_115200 },
+       {       /* IQ Express D2 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3200,
+               0, 0, pbn_b0_2_115200 },
+       {       /* IQ Express F2 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3300,
+               0, 0, pbn_b0_2_115200 },
+       {       /* IQ Express D4 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3400,
+               0, 0, pbn_b0_4_115200 },
+       {       /* IQ Express F4 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3500,
+               0, 0, pbn_b0_4_115200 },
+       {       /* IQ Express D8 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3C00,
+               0, 0, pbn_b0_8_115200 },
+       {       /* IQ Express F8 */
+               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+               PCI_VENDOR_ID_MAINPINE, 0x3D00,
+               0, 0, pbn_b0_8_115200 },
+
+
+       /*
+        * PA Semi PA6T-1682M on-chip UART
+        */
+       {       PCI_VENDOR_ID_PASEMI, 0xa004,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pasemi_1682M },
+
+       /*
+        * National Instruments
+        */
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI23216,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_16_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2328,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_8_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_4_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_2_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_4_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_2_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_23216,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_16_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2328,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_8_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_4_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_2_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_4_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_bt_2_115200 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_2 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_2 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_4 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_4 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2328,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_8 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2328,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_8 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_23216,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_16 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_23216,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_16 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_2 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2322,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_2 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_4 },
+       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_ni8430_4 },
+
+       /*
+       * ADDI-DATA GmbH communication cards <info@addi-data.com>
+       */
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7500,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_4_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7420,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_2_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7300,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA_OLD,
+               PCI_DEVICE_ID_ADDIDATA_APCI7800,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b1_8_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7500_2,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_4_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7420_2,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_2_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7300_2,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7500_3,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_4_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7420_3,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_2_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7300_3,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCI7800_3,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_b0_8_115200 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7500,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_4_3906250 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7420,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_2_3906250 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7300,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_1_3906250 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7800,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_8_3906250 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+               PCI_VENDOR_ID_IBM, 0x0299,
+               0, 0, pbn_b0_bt_2_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
+       /* the 9901 is a rebranded 9912 */
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+               0xA000, 0x3002,
+               0, 0, pbn_NETMOS9900_2s_115200 },
+
+       /*
+        * Best Connectivity and Rosewill PCI Multi I/O cards
+        */
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+               0xA000, 0x3002,
+               0, 0, pbn_b0_bt_2_115200 },
+
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+               0xA000, 0x3004,
+               0, 0, pbn_b0_bt_4_115200 },
+       /* Intel CE4100 */
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
+               PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+               pbn_ce4100_1_115200 },
+
+       /*
+        * Cronyx Omega PCI
+        */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_omegapci },
+
+       /*
+        * These entries match devices with class COMMUNICATION_SERIAL,
+        * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
+        */
+       {       PCI_ANY_ID, PCI_ANY_ID,
+               PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_COMMUNICATION_SERIAL << 8,
+               0xffff00, pbn_default },
+       {       PCI_ANY_ID, PCI_ANY_ID,
+               PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_COMMUNICATION_MODEM << 8,
+               0xffff00, pbn_default },
+       {       PCI_ANY_ID, PCI_ANY_ID,
+               PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_COMMUNICATION_MULTISERIAL << 8,
+               0xffff00, pbn_default },
+       { 0, }
+};
+
+static pci_ers_result_t serial8250_io_error_detected(struct pci_dev *dev,
+                                               pci_channel_state_t state)
+{
+       struct serial_private *priv = pci_get_drvdata(dev);
+
+       if (state == pci_channel_io_perm_failure)
+               return PCI_ERS_RESULT_DISCONNECT;
+
+       if (priv)
+               pciserial_suspend_ports(priv);
+
+       pci_disable_device(dev);
+
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
+{
+       int rc;
+
+       rc = pci_enable_device(dev);
+
+       if (rc)
+               return PCI_ERS_RESULT_DISCONNECT;
+
+       pci_restore_state(dev);
+       pci_save_state(dev);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void serial8250_io_resume(struct pci_dev *dev)
+{
+       struct serial_private *priv = pci_get_drvdata(dev);
+
+       if (priv)
+               pciserial_resume_ports(priv);
+}
+
+static struct pci_error_handlers serial8250_err_handler = {
+       .error_detected = serial8250_io_error_detected,
+       .slot_reset = serial8250_io_slot_reset,
+       .resume = serial8250_io_resume,
+};
+
+static struct pci_driver serial_pci_driver = {
+       .name           = "serial",
+       .probe          = pciserial_init_one,
+       .remove         = __devexit_p(pciserial_remove_one),
+#ifdef CONFIG_PM
+       .suspend        = pciserial_suspend_one,
+       .resume         = pciserial_resume_one,
+#endif
+       .id_table       = serial_pci_tbl,
+       .err_handler    = &serial8250_err_handler,
+};
+
+static int __init serial8250_pci_init(void)
+{
+       return pci_register_driver(&serial_pci_driver);
+}
+
+static void __exit serial8250_pci_exit(void)
+{
+       pci_unregister_driver(&serial_pci_driver);
+}
+
+module_init(serial8250_pci_init);
+module_exit(serial8250_pci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
+MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
new file mode 100644 (file)
index 0000000..a2f2365
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ *  Probe module for 8250/16550-type ISAPNP serial ports.
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ *  Ported to the Linux PnP Layer - (C) Adam Belay.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pnp.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/serial_core.h>
+#include <linux/bitops.h>
+
+#include <asm/byteorder.h>
+
+#include "8250.h"
+
+#define UNKNOWN_DEV 0x3000
+
+
+static const struct pnp_device_id pnp_dev_table[] = {
+       /* Archtek America Corp. */
+       /* Archtek SmartLink Modem 3334BT Plug & Play */
+       {       "AAC000F",              0       },
+       /* Anchor Datacomm BV */
+       /* SXPro 144 External Data Fax Modem Plug & Play */
+       {       "ADC0001",              0       },
+       /* SXPro 288 External Data Fax Modem Plug & Play */
+       {       "ADC0002",              0       },
+       /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
+       {       "AEI0250",              0       },
+       /* Actiontec ISA PNP 56K X2 Fax Modem */
+       {       "AEI1240",              0       },
+       /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+       {       "AKY1021",              0 /*SPCI_FL_NO_SHIRQ*/  },
+       /* AZT3005 PnP SOUND DEVICE */
+       {       "AZT4001",              0       },
+       /* Best Data Products Inc. Smart One 336F PnP Modem */
+       {       "BDP3336",              0       },
+       /*  Boca Research */
+       /* Boca Complete Ofc Communicator 14.4 Data-FAX */
+       {       "BRI0A49",              0       },
+       /* Boca Research 33,600 ACF Modem */
+       {       "BRI1400",              0       },
+       /* Boca 33.6 Kbps Internal FD34FSVD */
+       {       "BRI3400",              0       },
+       /* Boca 33.6 Kbps Internal FD34FSVD */
+       {       "BRI0A49",              0       },
+       /* Best Data Products Inc. Smart One 336F PnP Modem */
+       {       "BDP3336",              0       },
+       /* Computer Peripherals Inc */
+       /* EuroViVa CommCenter-33.6 SP PnP */
+       {       "CPI4050",              0       },
+       /* Creative Labs */
+       /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
+       {       "CTL3001",              0       },
+       /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
+       {       "CTL3011",              0       },
+       /* Davicom ISA 33.6K Modem */
+       {       "DAV0336",              0       },
+       /* Creative */
+       /* Creative Modem Blaster Flash56 DI5601-1 */
+       {       "DMB1032",              0       },
+       /* Creative Modem Blaster V.90 DI5660 */
+       {       "DMB2001",              0       },
+       /* E-Tech */
+       /* E-Tech CyberBULLET PC56RVP */
+       {       "ETT0002",              0       },
+       /* FUJITSU */
+       /* Fujitsu 33600 PnP-I2 R Plug & Play */
+       {       "FUJ0202",              0       },
+       /* Fujitsu FMV-FX431 Plug & Play */
+       {       "FUJ0205",              0       },
+       /* Fujitsu 33600 PnP-I4 R Plug & Play */
+       {       "FUJ0206",              0       },
+       /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
+       {       "FUJ0209",              0       },
+       /* Archtek America Corp. */
+       /* Archtek SmartLink Modem 3334BT Plug & Play */
+       {       "GVC000F",              0       },
+       /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
+       {       "GVC0303",              0       },
+       /* Hayes */
+       /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
+       {       "HAY0001",              0       },
+       /* Hayes Optima 336 V.34 + FAX + Voice PnP */
+       {       "HAY000C",              0       },
+       /* Hayes Optima 336B V.34 + FAX + Voice PnP */
+       {       "HAY000D",              0       },
+       /* Hayes Accura 56K Ext Fax Modem PnP */
+       {       "HAY5670",              0       },
+       /* Hayes Accura 56K Ext Fax Modem PnP */
+       {       "HAY5674",              0       },
+       /* Hayes Accura 56K Fax Modem PnP */
+       {       "HAY5675",              0       },
+       /* Hayes 288, V.34 + FAX */
+       {       "HAYF000",              0       },
+       /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
+       {       "HAYF001",              0       },
+       /* IBM */
+       /* IBM Thinkpad 701 Internal Modem Voice */
+       {       "IBM0033",              0       },
+       /* Intermec */
+       /* Intermec CV60 touchscreen port */
+       {       "PNP4972",              0       },
+       /* Intertex */
+       /* Intertex 28k8 33k6 Voice EXT PnP */
+       {       "IXDC801",              0       },
+       /* Intertex 33k6 56k Voice EXT PnP */
+       {       "IXDC901",              0       },
+       /* Intertex 28k8 33k6 Voice SP EXT PnP */
+       {       "IXDD801",              0       },
+       /* Intertex 33k6 56k Voice SP EXT PnP */
+       {       "IXDD901",              0       },
+       /* Intertex 28k8 33k6 Voice SP INT PnP */
+       {       "IXDF401",              0       },
+       /* Intertex 28k8 33k6 Voice SP EXT PnP */
+       {       "IXDF801",              0       },
+       /* Intertex 33k6 56k Voice SP EXT PnP */
+       {       "IXDF901",              0       },
+       /* Kortex International */
+       /* KORTEX 28800 Externe PnP */
+       {       "KOR4522",              0       },
+       /* KXPro 33.6 Vocal ASVD PnP */
+       {       "KORF661",              0       },
+       /* Lasat */
+       /* LASAT Internet 33600 PnP */
+       {       "LAS4040",              0       },
+       /* Lasat Safire 560 PnP */
+       {       "LAS4540",              0       },
+       /* Lasat Safire 336  PnP */
+       {       "LAS5440",              0       },
+       /* Microcom, Inc. */
+       /* Microcom TravelPorte FAST V.34 Plug & Play */
+       {       "MNP0281",              0       },
+       /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
+       {       "MNP0336",              0       },
+       /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
+       {       "MNP0339",              0       },
+       /* Microcom DeskPorte 28.8P Plug & Play */
+       {       "MNP0342",              0       },
+       /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+       {       "MNP0500",              0       },
+       /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+       {       "MNP0501",              0       },
+       /* Microcom DeskPorte 28.8S Internal Plug & Play */
+       {       "MNP0502",              0       },
+       /* Motorola */
+       /* Motorola BitSURFR Plug & Play */
+       {       "MOT1105",              0       },
+       /* Motorola TA210 Plug & Play */
+       {       "MOT1111",              0       },
+       /* Motorola HMTA 200 (ISDN) Plug & Play */
+       {       "MOT1114",              0       },
+       /* Motorola BitSURFR Plug & Play */
+       {       "MOT1115",              0       },
+       /* Motorola Lifestyle 28.8 Internal */
+       {       "MOT1190",              0       },
+       /* Motorola V.3400 Plug & Play */
+       {       "MOT1501",              0       },
+       /* Motorola Lifestyle 28.8 V.34 Plug & Play */
+       {       "MOT1502",              0       },
+       /* Motorola Power 28.8 V.34 Plug & Play */
+       {       "MOT1505",              0       },
+       /* Motorola ModemSURFR External 28.8 Plug & Play */
+       {       "MOT1509",              0       },
+       /* Motorola Premier 33.6 Desktop Plug & Play */
+       {       "MOT150A",              0       },
+       /* Motorola VoiceSURFR 56K External PnP */
+       {       "MOT150F",              0       },
+       /* Motorola ModemSURFR 56K External PnP */
+       {       "MOT1510",              0       },
+       /* Motorola ModemSURFR 56K Internal PnP */
+       {       "MOT1550",              0       },
+       /* Motorola ModemSURFR Internal 28.8 Plug & Play */
+       {       "MOT1560",              0       },
+       /* Motorola Premier 33.6 Internal Plug & Play */
+       {       "MOT1580",              0       },
+       /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
+       {       "MOT15B0",              0       },
+       /* Motorola VoiceSURFR 56K Internal PnP */
+       {       "MOT15F0",              0       },
+       /* Com 1 */
+       /*  Deskline K56 Phone System PnP */
+       {       "MVX00A1",              0       },
+       /* PC Rider K56 Phone System PnP */
+       {       "MVX00F2",              0       },
+       /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
+       {       "nEC8241",              0       },
+       /* Pace 56 Voice Internal Plug & Play Modem */
+       {       "PMC2430",              0       },
+       /* Generic */
+       /* Generic standard PC COM port  */
+       {       "PNP0500",              0       },
+       /* Generic 16550A-compatible COM port */
+       {       "PNP0501",              0       },
+       /* Compaq 14400 Modem */
+       {       "PNPC000",              0       },
+       /* Compaq 2400/9600 Modem */
+       {       "PNPC001",              0       },
+       /* Dial-Up Networking Serial Cable between 2 PCs */
+       {       "PNPC031",              0       },
+       /* Dial-Up Networking Parallel Cable between 2 PCs */
+       {       "PNPC032",              0       },
+       /* Standard 9600 bps Modem */
+       {       "PNPC100",              0       },
+       /* Standard 14400 bps Modem */
+       {       "PNPC101",              0       },
+       /*  Standard 28800 bps Modem*/
+       {       "PNPC102",              0       },
+       /*  Standard Modem*/
+       {       "PNPC103",              0       },
+       /*  Standard 9600 bps Modem*/
+       {       "PNPC104",              0       },
+       /*  Standard 14400 bps Modem*/
+       {       "PNPC105",              0       },
+       /*  Standard 28800 bps Modem*/
+       {       "PNPC106",              0       },
+       /*  Standard Modem */
+       {       "PNPC107",              0       },
+       /* Standard 9600 bps Modem */
+       {       "PNPC108",              0       },
+       /* Standard 14400 bps Modem */
+       {       "PNPC109",              0       },
+       /* Standard 28800 bps Modem */
+       {       "PNPC10A",              0       },
+       /* Standard Modem */
+       {       "PNPC10B",              0       },
+       /* Standard 9600 bps Modem */
+       {       "PNPC10C",              0       },
+       /* Standard 14400 bps Modem */
+       {       "PNPC10D",              0       },
+       /* Standard 28800 bps Modem */
+       {       "PNPC10E",              0       },
+       /* Standard Modem */
+       {       "PNPC10F",              0       },
+       /* Standard PCMCIA Card Modem */
+       {       "PNP2000",              0       },
+       /* Rockwell */
+       /* Modular Technology */
+       /* Rockwell 33.6 DPF Internal PnP */
+       /* Modular Technology 33.6 Internal PnP */
+       {       "ROK0030",              0       },
+       /* Kortex International */
+       /* KORTEX 14400 Externe PnP */
+       {       "ROK0100",              0       },
+       /* Rockwell 28.8 */
+       {       "ROK4120",              0       },
+       /* Viking Components, Inc */
+       /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
+       {       "ROK4920",              0       },
+       /* Rockwell */
+       /* British Telecom */
+       /* Modular Technology */
+       /* Rockwell 33.6 DPF External PnP */
+       /* BT Prologue 33.6 External PnP */
+       /* Modular Technology 33.6 External PnP */
+       {       "RSS00A0",              0       },
+       /* Viking 56K FAX INT */
+       {       "RSS0262",              0       },
+       /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
+       {       "RSS0250",              0       },
+       /* SupraExpress 28.8 Data/Fax PnP modem */
+       {       "SUP1310",              0       },
+       /* SupraExpress 336i PnP Voice Modem */
+       {       "SUP1381",              0       },
+       /* SupraExpress 33.6 Data/Fax PnP modem */
+       {       "SUP1421",              0       },
+       /* SupraExpress 33.6 Data/Fax PnP modem */
+       {       "SUP1590",              0       },
+       /* SupraExpress 336i Sp ASVD */
+       {       "SUP1620",              0       },
+       /* SupraExpress 33.6 Data/Fax PnP modem */
+       {       "SUP1760",              0       },
+       /* SupraExpress 56i Sp Intl */
+       {       "SUP2171",              0       },
+       /* Phoebe Micro */
+       /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
+       {       "TEX0011",              0       },
+       /* Archtek America Corp. */
+       /* Archtek SmartLink Modem 3334BT Plug & Play */
+       {       "UAC000F",              0       },
+       /* 3Com Corp. */
+       /* Gateway Telepath IIvi 33.6 */
+       {       "USR0000",              0       },
+       /* U.S. Robotics Sporster 33.6K Fax INT PnP */
+       {       "USR0002",              0       },
+       /*  Sportster Vi 14.4 PnP FAX Voicemail */
+       {       "USR0004",              0       },
+       /* U.S. Robotics 33.6K Voice INT PnP */
+       {       "USR0006",              0       },
+       /* U.S. Robotics 33.6K Voice EXT PnP */
+       {       "USR0007",              0       },
+       /* U.S. Robotics Courier V.Everything INT PnP */
+       {       "USR0009",              0       },
+       /* U.S. Robotics 33.6K Voice INT PnP */
+       {       "USR2002",              0       },
+       /* U.S. Robotics 56K Voice INT PnP */
+       {       "USR2070",              0       },
+       /* U.S. Robotics 56K Voice EXT PnP */
+       {       "USR2080",              0       },
+       /* U.S. Robotics 56K FAX INT */
+       {       "USR3031",              0       },
+       /* U.S. Robotics 56K FAX INT */
+       {       "USR3050",              0       },
+       /* U.S. Robotics 56K Voice INT PnP */
+       {       "USR3070",              0       },
+       /* U.S. Robotics 56K Voice EXT PnP */
+       {       "USR3080",              0       },
+       /* U.S. Robotics 56K Voice INT PnP */
+       {       "USR3090",              0       },
+       /* U.S. Robotics 56K Message  */
+       {       "USR9100",              0       },
+       /* U.S. Robotics 56K FAX EXT PnP*/
+       {       "USR9160",              0       },
+       /* U.S. Robotics 56K FAX INT PnP*/
+       {       "USR9170",              0       },
+       /* U.S. Robotics 56K Voice EXT PnP*/
+       {       "USR9180",              0       },
+       /* U.S. Robotics 56K Voice INT PnP*/
+       {       "USR9190",              0       },
+       /* Wacom tablets */
+       {       "WACFXXX",              0       },
+       /* Compaq touchscreen */
+       {       "FPI2002",              0 },
+       /* Fujitsu Stylistic touchscreens */
+       {       "FUJ02B2",              0 },
+       {       "FUJ02B3",              0 },
+       /* Fujitsu Stylistic LT touchscreens */
+       {       "FUJ02B4",              0 },
+       /* Passive Fujitsu Stylistic touchscreens */
+       {       "FUJ02B6",              0 },
+       {       "FUJ02B7",              0 },
+       {       "FUJ02B8",              0 },
+       {       "FUJ02B9",              0 },
+       {       "FUJ02BC",              0 },
+       /* Fujitsu Wacom Tablet PC device */
+       {       "FUJ02E5",              0       },
+       /* Fujitsu P-series tablet PC device */
+       {       "FUJ02E6",              0       },
+       /* Fujitsu Wacom 2FGT Tablet PC device */
+       {       "FUJ02E7",              0       },
+       /* Fujitsu Wacom 1FGT Tablet PC device */
+       {       "FUJ02E9",              0       },
+       /*
+        * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
+        * disguise)
+        */
+       {       "LTS0001",              0       },
+       /* Rockwell's (PORALiNK) 33600 INT PNP */
+       {       "WCI0003",              0       },
+       /* Unknown PnP modems */
+       {       "PNPCXXX",              UNKNOWN_DEV     },
+       /* More unknown PnP modems */
+       {       "PNPDXXX",              UNKNOWN_DEV     },
+       {       "",                     0       }
+};
+
+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+
+static char *modem_names[] __devinitdata = {
+       "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
+       "56K", "56k", "K56", "33.6", "28.8", "14.4",
+       "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
+       "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
+};
+
+static int __devinit check_name(char *name)
+{
+       char **tmp;
+
+       for (tmp = modem_names; *tmp; tmp++)
+               if (strstr(name, *tmp))
+                       return 1;
+
+       return 0;
+}
+
+static int __devinit check_resources(struct pnp_dev *dev)
+{
+       resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(base); i++) {
+               if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * Given a complete unknown PnP device, try to use some heuristics to
+ * detect modems. Currently use such heuristic set:
+ *     - dev->name or dev->bus->name must contain "modem" substring;
+ *     - device must have only one IO region (8 byte long) with base address
+ *       0x2e8, 0x3e8, 0x2f8 or 0x3f8.
+ *
+ * Such detection looks very ugly, but can detect at least some of numerous
+ * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
+ * table.
+ */
+static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
+{
+       if (!(check_name(pnp_dev_name(dev)) ||
+               (dev->card && check_name(dev->card->name))))
+                       return -ENODEV;
+
+       if (check_resources(dev))
+               return 0;
+
+       return -ENODEV;
+}
+
+static int __devinit
+serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+{
+       struct uart_port port;
+       int ret, line, flags = dev_id->driver_data;
+
+       if (flags & UNKNOWN_DEV) {
+               ret = serial_pnp_guess_board(dev, &flags);
+               if (ret < 0)
+                       return ret;
+       }
+
+       memset(&port, 0, sizeof(struct uart_port));
+       if (pnp_irq_valid(dev, 0))
+               port.irq = pnp_irq(dev, 0);
+       if (pnp_port_valid(dev, 0)) {
+               port.iobase = pnp_port_start(dev, 0);
+               port.iotype = UPIO_PORT;
+       } else if (pnp_mem_valid(dev, 0)) {
+               port.mapbase = pnp_mem_start(dev, 0);
+               port.iotype = UPIO_MEM;
+               port.flags = UPF_IOREMAP;
+       } else
+               return -ENODEV;
+
+#ifdef SERIAL_DEBUG_PNP
+       printk(KERN_DEBUG
+               "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
+                      port.iobase, port.mapbase, port.irq, port.iotype);
+#endif
+
+       port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+       if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
+               port.flags |= UPF_SHARE_IRQ;
+       port.uartclk = 1843200;
+       port.dev = &dev->dev;
+
+       line = serial8250_register_port(&port);
+       if (line < 0)
+               return -ENODEV;
+
+       pnp_set_drvdata(dev, (void *)((long)line + 1));
+       return 0;
+}
+
+static void __devexit serial_pnp_remove(struct pnp_dev *dev)
+{
+       long line = (long)pnp_get_drvdata(dev);
+       if (line)
+               serial8250_unregister_port(line - 1);
+}
+
+#ifdef CONFIG_PM
+static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
+{
+       long line = (long)pnp_get_drvdata(dev);
+
+       if (!line)
+               return -ENODEV;
+       serial8250_suspend_port(line - 1);
+       return 0;
+}
+
+static int serial_pnp_resume(struct pnp_dev *dev)
+{
+       long line = (long)pnp_get_drvdata(dev);
+
+       if (!line)
+               return -ENODEV;
+       serial8250_resume_port(line - 1);
+       return 0;
+}
+#else
+#define serial_pnp_suspend NULL
+#define serial_pnp_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pnp_driver serial_pnp_driver = {
+       .name           = "serial",
+       .probe          = serial_pnp_probe,
+       .remove         = __devexit_p(serial_pnp_remove),
+       .suspend        = serial_pnp_suspend,
+       .resume         = serial_pnp_resume,
+       .id_table       = pnp_dev_table,
+};
+
+static int __init serial8250_pnp_init(void)
+{
+       return pnp_register_driver(&serial_pnp_driver);
+}
+
+static void __exit serial8250_pnp_exit(void)
+{
+       pnp_unregister_driver(&serial_pnp_driver);
+}
+
+module_init(serial8250_pnp_init);
+module_exit(serial8250_pnp_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
new file mode 100644 (file)
index 0000000..591f801
--- /dev/null
@@ -0,0 +1,280 @@
+#
+# The 8250/16550 serial drivers.  You shouldn't be in this list unless
+# you somehow have an implicit or explicit dependency on SERIAL_8250.
+#
+
+config SERIAL_8250
+       tristate "8250/16550 and compatible serial support"
+       select SERIAL_CORE
+       ---help---
+         This selects whether you want to include the driver for the standard
+         serial ports.  The standard answer is Y.  People who might say N
+         here are those that are setting up dedicated Ethernet WWW/FTP
+         servers, or users that have one of the various bus mice instead of a
+         serial mouse and don't intend to use their machine's standard serial
+         port for anything.  (Note that the Cyclades and Stallion multi
+         serial port drivers do not need this driver built in for them to
+         work.)
+
+         To compile this driver as a module, choose M here: the
+         module will be called 8250.
+         [WARNING: Do not compile this driver as a module if you are using
+         non-standard serial ports, since the configuration information will
+         be lost when the driver is unloaded.  This limitation may be lifted
+         in the future.]
+
+         BTW1: If you have a mouseman serial mouse which is not recognized by
+         the X window system, try running gpm first.
+
+         BTW2: If you intend to use a software modem (also called Winmodem)
+         under Linux, forget it.  These modems are crippled and require
+         proprietary drivers which are only available under Windows.
+
+         Most people will say Y or M here, so that they can use serial mice,
+         modems and similar devices connecting to the standard serial ports.
+
+config SERIAL_8250_CONSOLE
+       bool "Console on 8250/16550 and compatible serial port"
+       depends on SERIAL_8250=y
+       select SERIAL_CORE_CONSOLE
+       ---help---
+         If you say Y here, it will be possible to use a serial port as the
+         system console (the system console is the device which receives all
+         kernel messages and warnings and which allows logins in single user
+         mode). This could be useful if some terminal or printer is connected
+         to that serial port.
+
+         Even if you say Y here, the currently visible virtual console
+         (/dev/tty0) will still be used as the system console by default, but
+         you can alter that using a kernel command line option such as
+         "console=ttyS1". (Try "man bootparam" or see the documentation of
+         your boot loader (grub or lilo or loadlin) about how to pass options
+         to the kernel at boot time.)
+
+         If you don't have a VGA card installed and you say Y here, the
+         kernel will automatically use the first serial line, /dev/ttyS0, as
+         system console.
+
+         You can set that using a kernel command line option such as
+         "console=uart8250,io,0x3f8,9600n8"
+         "console=uart8250,mmio,0xff5e0000,115200n8".
+         and it will switch to normal serial console when the corresponding
+         port is ready.
+         "earlycon=uart8250,io,0x3f8,9600n8"
+         "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+         it will not only setup early console.
+
+         If unsure, say N.
+
+config FIX_EARLYCON_MEM
+       bool
+       depends on X86
+       default y
+
+config SERIAL_8250_GSC
+       tristate
+       depends on SERIAL_8250 && GSC
+       default SERIAL_8250
+
+config SERIAL_8250_PCI
+       tristate "8250/16550 PCI device support" if EXPERT
+       depends on SERIAL_8250 && PCI
+       default SERIAL_8250
+       help
+         This builds standard PCI serial support. You may be able to
+         disable this feature if you only need legacy serial support.
+         Saves about 9K.
+
+config SERIAL_8250_PNP
+       tristate "8250/16550 PNP device support" if EXPERT
+       depends on SERIAL_8250 && PNP
+       default SERIAL_8250
+       help
+         This builds standard PNP serial support. You may be able to
+         disable this feature if you only need legacy serial support.
+
+config SERIAL_8250_HP300
+       tristate
+       depends on SERIAL_8250 && HP300
+       default SERIAL_8250
+
+config SERIAL_8250_CS
+       tristate "8250/16550 PCMCIA device support"
+       depends on PCMCIA && SERIAL_8250
+       ---help---
+         Say Y here to enable support for 16-bit PCMCIA serial devices,
+         including serial port cards, modems, and the modem functions of
+         multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
+         credit-card size devices often used with laptops.)
+
+         To compile this driver as a module, choose M here: the
+         module will be called serial_cs.
+
+         If unsure, say N.
+
+config SERIAL_8250_NR_UARTS
+       int "Maximum number of 8250/16550 serial ports"
+       depends on SERIAL_8250
+       default "4"
+       help
+         Set this to the number of serial ports you want the driver
+         to support.  This includes any ports discovered via ACPI or
+         PCI enumeration and any ports that may be added at run-time
+         via hot-plug, or any ISA multi-port serial cards.
+
+config SERIAL_8250_RUNTIME_UARTS
+       int "Number of 8250/16550 serial ports to register at runtime"
+       depends on SERIAL_8250
+       range 0 SERIAL_8250_NR_UARTS
+       default "4"
+       help
+         Set this to the maximum number of serial ports you want
+         the kernel to register at boot time.  This can be overridden
+         with the module parameter "nr_uarts", or boot-time parameter
+         8250.nr_uarts
+
+config SERIAL_8250_EXTENDED
+       bool "Extended 8250/16550 serial driver options"
+       depends on SERIAL_8250
+       help
+         If you wish to use any non-standard features of the standard "dumb"
+         driver, say Y here. This includes HUB6 support, shared serial
+         interrupts, special multiport support, support for more than the
+         four COM 1/2/3/4 boards, etc.
+
+         Note that the answer to this question won't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about serial driver options. If unsure, say N.
+
+config SERIAL_8250_MANY_PORTS
+       bool "Support more than 4 legacy serial ports"
+       depends on SERIAL_8250_EXTENDED && !IA64
+       help
+         Say Y here if you have dumb serial boards other than the four
+         standard COM 1/2/3/4 ports. This may happen if you have an AST
+         FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
+         from <http://www.tldp.org/docs.html#howto>), or other custom
+         serial port hardware which acts similar to standard serial port
+         hardware. If you only use the standard COM 1/2/3/4 ports, you can
+         say N here to save some memory. You can also say Y if you have an
+         "intelligent" multiport card such as Cyclades, Digiboards, etc.
+
+#
+# Multi-port serial cards
+#
+
+config SERIAL_8250_FOURPORT
+       tristate "Support Fourport cards"
+       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+       help
+         Say Y here if you have an AST FourPort serial board.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_fourport.
+
+config SERIAL_8250_ACCENT
+       tristate "Support Accent cards"
+       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+       help
+         Say Y here if you have an Accent Async serial board.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_accent.
+
+config SERIAL_8250_BOCA
+       tristate "Support Boca cards"
+       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+       help
+         Say Y here if you have a Boca serial board.  Please read the Boca
+         mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_boca.
+
+config SERIAL_8250_EXAR_ST16C554
+       tristate "Support Exar ST16C554/554D Quad UART"
+       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+       help
+         The Uplogix Envoy TU301 uses this Exar Quad UART.  If you are
+         tinkering with your Envoy TU301, or have a machine with this UART,
+         say Y here.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_exar_st16c554.
+
+config SERIAL_8250_HUB6
+       tristate "Support Hub6 cards"
+       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+       help
+         Say Y here if you have a HUB6 serial board.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_hub6.
+
+#
+# Misc. options/drivers.
+#
+
+config SERIAL_8250_SHARE_IRQ
+       bool "Support for sharing serial interrupts"
+       depends on SERIAL_8250_EXTENDED
+       help
+         Some serial boards have hardware support which allows multiple dumb
+         serial ports on the same board to share a single IRQ. To enable
+         support for this in the serial driver, say Y here.
+
+config SERIAL_8250_DETECT_IRQ
+       bool "Autodetect IRQ on standard ports (unsafe)"
+       depends on SERIAL_8250_EXTENDED
+       help
+         Say Y here if you want the kernel to try to guess which IRQ
+         to use for your serial port.
+
+         This is considered unsafe; it is far better to configure the IRQ in
+         a boot script using the setserial command.
+
+         If unsure, say N.
+
+config SERIAL_8250_RSA
+       bool "Support RSA serial ports"
+       depends on SERIAL_8250_EXTENDED
+       help
+         ::: To be written :::
+
+config SERIAL_8250_MCA
+       tristate "Support 8250-type ports on MCA buses"
+       depends on SERIAL_8250 != n && MCA
+       help
+         Say Y here if you have a MCA serial ports.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_mca.
+
+config SERIAL_8250_ACORN
+       tristate "Acorn expansion card serial port support"
+       depends on ARCH_ACORN && SERIAL_8250
+       help
+         If you have an Atomwide Serial card or Serial Port card for an Acorn
+         system, say Y to this option.  The driver can handle 1, 2, or 3 port
+         cards.  If unsure, say N.
+
+config SERIAL_8250_RM9K
+       bool "Support for MIPS RM9xxx integrated serial port"
+       depends on SERIAL_8250 != n && SERIAL_RM9000
+       select SERIAL_8250_SHARE_IRQ
+       help
+         Selecting this option will add support for the integrated serial
+         port hardware found on MIPS RM9122 and similar processors.
+         If unsure, say N.
+
+config SERIAL_8250_FSL
+       bool
+       depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
+       default PPC
+
+config SERIAL_8250_DW
+       tristate "Support for Synopsys DesignWare 8250 quirks"
+       depends on SERIAL_8250 && OF
+       help
+         Selecting this option will enable handling of the extra features
+         present in the Synopsys DesignWare APB UART.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
new file mode 100644 (file)
index 0000000..867bba7
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the 8250 serial device drivers.
+#
+
+obj-$(CONFIG_SERIAL_8250)              += 8250.o
+obj-$(CONFIG_SERIAL_8250_PNP)          += 8250_pnp.o
+obj-$(CONFIG_SERIAL_8250_GSC)          += 8250_gsc.o
+obj-$(CONFIG_SERIAL_8250_PCI)          += 8250_pci.o
+obj-$(CONFIG_SERIAL_8250_HP300)                += 8250_hp300.o
+obj-$(CONFIG_SERIAL_8250_CS)           += serial_cs.o
+obj-$(CONFIG_SERIAL_8250_ACORN)                += 8250_acorn.o
+obj-$(CONFIG_SERIAL_8250_CONSOLE)      += 8250_early.o
+obj-$(CONFIG_SERIAL_8250_FOURPORT)     += 8250_fourport.o
+obj-$(CONFIG_SERIAL_8250_ACCENT)       += 8250_accent.o
+obj-$(CONFIG_SERIAL_8250_BOCA)         += 8250_boca.o
+obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)        += 8250_exar_st16c554.o
+obj-$(CONFIG_SERIAL_8250_HUB6)         += 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_MCA)          += 8250_mca.o
+obj-$(CONFIG_SERIAL_8250_FSL)          += 8250_fsl.o
+obj-$(CONFIG_SERIAL_8250_DW)           += 8250_dw.o
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
new file mode 100644 (file)
index 0000000..8609060
--- /dev/null
@@ -0,0 +1,870 @@
+/*======================================================================
+
+    A driver for PCMCIA serial devices
+
+    serial_cs.c 1.134 2002/05/04 05:48:53
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is David A. Hinds
+    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
+    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU General Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    and other provisions required by the GPL.  If you do not delete
+    the provisions above, a recipient may use your version of this
+    file under either the MPL or the GPL.
+    
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/serial_core.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include "8250.h"
+
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* Enable the speaker? */
+static int do_sound = 1;
+/* Skip strict UART tests? */
+static int buggy_uart;
+
+module_param(do_sound, int, 0444);
+module_param(buggy_uart, int, 0444);
+
+/*====================================================================*/
+
+/* Table of multi-port card ID's */
+
+struct serial_quirk {
+       unsigned int manfid;
+       unsigned int prodid;
+       int multi;              /* 1 = multifunction, > 1 = # ports */
+       void (*config)(struct pcmcia_device *);
+       void (*setup)(struct pcmcia_device *, struct uart_port *);
+       void (*wakeup)(struct pcmcia_device *);
+       int (*post)(struct pcmcia_device *);
+};
+
+struct serial_info {
+       struct pcmcia_device    *p_dev;
+       int                     ndev;
+       int                     multi;
+       int                     slave;
+       int                     manfid;
+       int                     prodid;
+       int                     c950ctrl;
+       int                     line[4];
+       const struct serial_quirk *quirk;
+};
+
+struct serial_cfg_mem {
+       tuple_t tuple;
+       cisparse_t parse;
+       u_char buf[256];
+};
+
+/*
+ * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6"
+ * manfid 0x0160, 0x0104
+ * This card appears to have a 14.7456MHz clock.
+ */
+/* Generic Modem: MD55x (GPRS/EDGE) have
+ * Elan VPU16551 UART with 14.7456MHz oscillator
+ * manfid 0x015D, 0x4C45
+ */
+static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
+{
+       port->uartclk = 14745600;
+}
+
+static int quirk_post_ibm(struct pcmcia_device *link)
+{
+       u8 val;
+       int ret;
+
+       ret = pcmcia_read_config_byte(link, 0x800, &val);
+       if (ret)
+               goto failed;
+
+       ret = pcmcia_write_config_byte(link, 0x800, val | 1);
+       if (ret)
+               goto failed;
+       return 0;
+
+ failed:
+       return -ENODEV;
+}
+
+/*
+ * Nokia cards are not really multiport cards.  Shouldn't this
+ * be handled by setting the quirk entry .multi = 0 | 1 ?
+ */
+static void quirk_config_nokia(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+
+       if (info->multi > 1)
+               info->multi = 1;
+}
+
+static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+
+       if (info->c950ctrl)
+               outb(12, info->c950ctrl + 1);
+}
+
+/* request_region? oxsemi branch does no request_region too... */
+/*
+ * This sequence is needed to properly initialize MC45 attached to OXCF950.
+ * I tried decreasing these msleep()s, but it worked properly (survived
+ * 1000 stop/start operations) with these timeouts (or bigger).
+ */
+static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       unsigned int ctrl = info->c950ctrl;
+
+       outb(0xA, ctrl + 1);
+       msleep(100);
+       outb(0xE, ctrl + 1);
+       msleep(300);
+       outb(0xC, ctrl + 1);
+       msleep(100);
+       outb(0xE, ctrl + 1);
+       msleep(200);
+       outb(0xF, ctrl + 1);
+       msleep(100);
+       outb(0xE, ctrl + 1);
+       msleep(100);
+       outb(0xC, ctrl + 1);
+}
+
+/*
+ * Socket Dual IO: this enables irq's for second port
+ */
+static void quirk_config_socket(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+
+       if (info->multi)
+               link->config_flags |= CONF_ENABLE_ESR;
+}
+
+static const struct serial_quirk quirks[] = {
+       {
+               .manfid = 0x0160,
+               .prodid = 0x0104,
+               .multi  = -1,
+               .setup  = quirk_setup_brainboxes_0104,
+       }, {
+               .manfid = 0x015D,
+               .prodid = 0x4C45,
+               .multi  = -1,
+               .setup  = quirk_setup_brainboxes_0104,
+       }, {
+               .manfid = MANFID_IBM,
+               .prodid = ~0,
+               .multi  = -1,
+               .post   = quirk_post_ibm,
+       }, {
+               .manfid = MANFID_INTEL,
+               .prodid = PRODID_INTEL_DUAL_RS232,
+               .multi  = 2,
+       }, {
+               .manfid = MANFID_NATINST,
+               .prodid = PRODID_NATINST_QUAD_RS232,
+               .multi  = 4,
+       }, {
+               .manfid = MANFID_NOKIA,
+               .prodid = ~0,
+               .multi  = -1,
+               .config = quirk_config_nokia,
+       }, {
+               .manfid = MANFID_OMEGA,
+               .prodid = PRODID_OMEGA_QSP_100,
+               .multi  = 4,
+       }, {
+               .manfid = MANFID_OXSEMI,
+               .prodid = ~0,
+               .multi  = -1,
+               .wakeup = quirk_wakeup_oxsemi,
+       }, {
+               .manfid = MANFID_POSSIO,
+               .prodid = PRODID_POSSIO_GCC,
+               .multi  = -1,
+               .wakeup = quirk_wakeup_possio_gcc,
+       }, {
+               .manfid = MANFID_QUATECH,
+               .prodid = PRODID_QUATECH_DUAL_RS232,
+               .multi  = 2,
+       }, {
+               .manfid = MANFID_QUATECH,
+               .prodid = PRODID_QUATECH_DUAL_RS232_D1,
+               .multi  = 2,
+       }, {
+               .manfid = MANFID_QUATECH,
+               .prodid = PRODID_QUATECH_DUAL_RS232_G,
+               .multi  = 2,
+       }, {
+               .manfid = MANFID_QUATECH,
+               .prodid = PRODID_QUATECH_QUAD_RS232,
+               .multi  = 4,
+       }, {
+               .manfid = MANFID_SOCKET,
+               .prodid = PRODID_SOCKET_DUAL_RS232,
+               .multi  = 2,
+               .config = quirk_config_socket,
+       }, {
+               .manfid = MANFID_SOCKET,
+               .prodid = ~0,
+               .multi  = -1,
+               .config = quirk_config_socket,
+       }
+};
+
+
+static int serial_config(struct pcmcia_device * link);
+
+
+static void serial_remove(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i;
+
+       dev_dbg(&link->dev, "serial_release\n");
+
+       /*
+        * Recheck to see if the device is still configured.
+        */
+       for (i = 0; i < info->ndev; i++)
+               serial8250_unregister_port(info->line[i]);
+
+       if (!info->slave)
+               pcmcia_disable_device(link);
+}
+
+static int serial_suspend(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i;
+
+       for (i = 0; i < info->ndev; i++)
+               serial8250_suspend_port(info->line[i]);
+
+       return 0;
+}
+
+static int serial_resume(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i;
+
+       for (i = 0; i < info->ndev; i++)
+               serial8250_resume_port(info->line[i]);
+
+       if (info->quirk && info->quirk->wakeup)
+               info->quirk->wakeup(link);
+
+       return 0;
+}
+
+static int serial_probe(struct pcmcia_device *link)
+{
+       struct serial_info *info;
+
+       dev_dbg(&link->dev, "serial_attach()\n");
+
+       /* Create new serial device */
+       info = kzalloc(sizeof (*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+       info->p_dev = link;
+       link->priv = info;
+
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+       if (do_sound)
+               link->config_flags |= CONF_ENABLE_SPKR;
+
+       return serial_config(link);
+}
+
+static void serial_detach(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+
+       dev_dbg(&link->dev, "serial_detach\n");
+
+       /*
+        * Ensure that the ports have been released.
+        */
+       serial_remove(link);
+
+       /* free bits */
+       kfree(info);
+}
+
+/*====================================================================*/
+
+static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
+                       unsigned int iobase, int irq)
+{
+       struct uart_port port;
+       int line;
+
+       memset(&port, 0, sizeof (struct uart_port));
+       port.iobase = iobase;
+       port.irq = irq;
+       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+       port.uartclk = 1843200;
+       port.dev = &handle->dev;
+       if (buggy_uart)
+               port.flags |= UPF_BUGGY_UART;
+
+       if (info->quirk && info->quirk->setup)
+               info->quirk->setup(handle, &port);
+
+       line = serial8250_register_port(&port);
+       if (line < 0) {
+               printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
+                      "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
+               return -EINVAL;
+       }
+
+       info->line[info->ndev] = line;
+       info->ndev++;
+
+       return 0;
+}
+
+/*====================================================================*/
+
+static int pfc_config(struct pcmcia_device *p_dev)
+{
+       unsigned int port = 0;
+       struct serial_info *info = p_dev->priv;
+
+       if ((p_dev->resource[1]->end != 0) &&
+               (resource_size(p_dev->resource[1]) == 8)) {
+               port = p_dev->resource[1]->start;
+               info->slave = 1;
+       } else if ((info->manfid == MANFID_OSITECH) &&
+               (resource_size(p_dev->resource[0]) == 0x40)) {
+               port = p_dev->resource[0]->start + 0x28;
+               info->slave = 1;
+       }
+       if (info->slave)
+               return setup_serial(p_dev, info, port, p_dev->irq);
+
+       dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
+       return -ENODEV;
+}
+
+static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
+{
+       static const int size_table[2] = { 8, 16 };
+       int *try = priv_data;
+
+       if (p_dev->resource[0]->start == 0)
+               return -ENODEV;
+
+       if ((*try & 0x1) == 0)
+               p_dev->io_lines = 16;
+
+       if (p_dev->resource[0]->end != size_table[(*try >> 1)])
+               return -ENODEV;
+
+       p_dev->resource[0]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       return pcmcia_request_io(p_dev);
+}
+
+static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
+                                       void *priv_data)
+{
+       static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+       int j;
+
+       if (p_dev->io_lines > 3)
+               return -ENODEV;
+
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = 8;
+
+       for (j = 0; j < 5; j++) {
+               p_dev->resource[0]->start = base[j];
+               p_dev->io_lines = base[j] ? 16 : 3;
+               if (!pcmcia_request_io(p_dev))
+                       return 0;
+       }
+       return -ENODEV;
+}
+
+static int simple_config(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i = -ENODEV, try;
+
+       /* First pass: look for a config entry that looks normal.
+        * Two tries: without IO aliases, then with aliases */
+       link->config_flags |= CONF_AUTO_SET_VPP;
+       for (try = 0; try < 4; try++)
+               if (!pcmcia_loop_config(link, simple_config_check, &try))
+                       goto found_port;
+
+       /* Second pass: try to find an entry that isn't picky about
+          its base address, then try to grab any standard serial port
+          address, and finally try to get any free port. */
+       if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
+               goto found_port;
+
+       dev_warn(&link->dev, "no usable port range found, giving up\n");
+       return -1;
+
+found_port:
+       if (info->multi && (info->manfid == MANFID_3COM))
+               link->config_index &= ~(0x08);
+
+       /*
+        * Apply any configuration quirks.
+        */
+       if (info->quirk && info->quirk->config)
+               info->quirk->config(link);
+
+       i = pcmcia_enable_device(link);
+       if (i != 0)
+               return -1;
+       return setup_serial(link, info, link->resource[0]->start, link->irq);
+}
+
+static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
+{
+       int *multi = priv_data;
+
+       if (p_dev->resource[1]->end)
+               return -EINVAL;
+
+       /* The quad port cards have bad CIS's, so just look for a
+          window larger than 8 ports and assume it will be right */
+       if (p_dev->resource[0]->end <= 8)
+               return -EINVAL;
+
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       p_dev->resource[0]->end = *multi * 8;
+
+       if (pcmcia_request_io(p_dev))
+               return -ENODEV;
+       return 0;
+}
+
+static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
+                                      void *priv_data)
+{
+       int *base2 = priv_data;
+
+       if (!p_dev->resource[0]->end || !p_dev->resource[1]->end ||
+               p_dev->resource[0]->start + 8 != p_dev->resource[1]->start)
+               return -ENODEV;
+
+       p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+       if (pcmcia_request_io(p_dev))
+               return -ENODEV;
+
+       *base2 = p_dev->resource[0]->start + 8;
+       return 0;
+}
+
+static int multi_config(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i, base2 = 0;
+
+       /* First, look for a generic full-sized window */
+       if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
+               base2 = link->resource[0]->start + 8;
+       else {
+               /* If that didn't work, look for two windows */
+               info->multi = 2;
+               if (pcmcia_loop_config(link, multi_config_check_notpicky,
+                                      &base2)) {
+                       dev_warn(&link->dev, "no usable port range "
+                              "found, giving up\n");
+                       return -ENODEV;
+               }
+       }
+
+       if (!link->irq)
+               dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
+
+       /*
+        * Apply any configuration quirks.
+        */
+       if (info->quirk && info->quirk->config)
+               info->quirk->config(link);
+
+       i = pcmcia_enable_device(link);
+       if (i != 0)
+               return -ENODEV;
+
+       /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
+        * 8 registers are for the UART, the others are extra registers.
+        * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
+        */
+       if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
+                               info->prodid == PRODID_POSSIO_GCC)) {
+               int err;
+
+               if (link->config_index == 1 ||
+                   link->config_index == 3) {
+                       err = setup_serial(link, info, base2,
+                                       link->irq);
+                       base2 = link->resource[0]->start;
+               } else {
+                       err = setup_serial(link, info, link->resource[0]->start,
+                                       link->irq);
+               }
+               info->c950ctrl = base2;
+
+               /*
+                * FIXME: We really should wake up the port prior to
+                * handing it over to the serial layer.
+                */
+               if (info->quirk && info->quirk->wakeup)
+                       info->quirk->wakeup(link);
+
+               return 0;
+       }
+
+       setup_serial(link, info, link->resource[0]->start, link->irq);
+       for (i = 0; i < info->multi - 1; i++)
+               setup_serial(link, info, base2 + (8 * i),
+                               link->irq);
+       return 0;
+}
+
+static int serial_check_for_multi(struct pcmcia_device *p_dev,  void *priv_data)
+{
+       struct serial_info *info = p_dev->priv;
+
+       if (!p_dev->resource[0]->end)
+               return -EINVAL;
+
+       if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
+               info->multi = p_dev->resource[0]->end >> 3;
+
+       if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
+               && (p_dev->resource[1]->end == 8))
+               info->multi = 2;
+
+       return 0; /* break */
+}
+
+
+static int serial_config(struct pcmcia_device * link)
+{
+       struct serial_info *info = link->priv;
+       int i;
+
+       dev_dbg(&link->dev, "serial_config\n");
+
+       /* Is this a compliant multifunction card? */
+       info->multi = (link->socket->functions > 1);
+
+       /* Is this a multiport card? */
+       info->manfid = link->manf_id;
+       info->prodid = link->card_id;
+
+       for (i = 0; i < ARRAY_SIZE(quirks); i++)
+               if ((quirks[i].manfid == ~0 ||
+                    quirks[i].manfid == info->manfid) &&
+                   (quirks[i].prodid == ~0 ||
+                    quirks[i].prodid == info->prodid)) {
+                       info->quirk = &quirks[i];
+                       break;
+               }
+
+       /* Another check for dual-serial cards: look for either serial or
+          multifunction cards that ask for appropriate IO port ranges */
+       if ((info->multi == 0) &&
+           (link->has_func_id) &&
+           (link->socket->pcmcia_pfc == 0) &&
+           ((link->func_id == CISTPL_FUNCID_MULTI) ||
+            (link->func_id == CISTPL_FUNCID_SERIAL)))
+               pcmcia_loop_config(link, serial_check_for_multi, info);
+
+       /*
+        * Apply any multi-port quirk.
+        */
+       if (info->quirk && info->quirk->multi != -1)
+               info->multi = info->quirk->multi;
+
+       dev_info(&link->dev,
+               "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
+               link->manf_id, link->card_id,
+               link->socket->pcmcia_pfc, info->multi, info->quirk);
+       if (link->socket->pcmcia_pfc)
+               i = pfc_config(link);
+       else if (info->multi > 1)
+               i = multi_config(link);
+       else
+               i = simple_config(link);
+
+       if (i || info->ndev == 0)
+               goto failed;
+
+       /*
+        * Apply any post-init quirk.  FIXME: This should really happen
+        * before we register the port, since it might already be in use.
+        */
+       if (info->quirk && info->quirk->post)
+               if (info->quirk->post(link))
+                       goto failed;
+
+       return 0;
+
+failed:
+       dev_warn(&link->dev, "failed to initialize\n");
+       serial_remove(link);
+       return -ENODEV;
+}
+
+static const struct pcmcia_device_id serial_ids[] = {
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
+       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
+       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
+       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
+       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
+       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
+       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
+       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
+       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
+       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0b05),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
+       PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
+       PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
+       PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
+       PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
+       PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
+       PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
+       PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
+       PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
+       PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
+       PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
+       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
+       PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
+       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
+       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
+       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
+       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
+       PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
+       PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
+       PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
+       PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
+       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
+       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
+       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
+       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
+       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
+       PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
+       PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
+       PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
+       PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
+       PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
+       PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
+       PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
+       PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
+       PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
+       PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
+       PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
+       PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
+       PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
+       PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
+       PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
+       PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
+       PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
+       PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
+       PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
+       PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
+       PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
+       PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
+       PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
+       PCMCIA_DEVICE_PROD_ID12("OEM      ", "C288MX     ", 0xb572d360, 0xd2385b7a),
+       PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA   ", "C336MX     ", 0x99bcafe9, 0xaa25bcab),
+       PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
+       PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
+       PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
+       PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
+       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC860", 0xd85f6206, 0x698f93db, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC860 3G Network Adapter R1 */
+       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"),  /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
+       PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+       PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
+       PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
+       PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
+       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100  1.00.",0x19ca78af,0xf964f42b),
+       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
+       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232  1.00.",0x19ca78af,0x69fb7490),
+       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235),
+       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3),
+       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676),
+       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+       PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+       PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+       PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
+       /* too generic */
+       /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
+       /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
+       PCMCIA_DEVICE_FUNC_ID(2),
+       PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, serial_ids);
+
+MODULE_FIRMWARE("cis/PCMLM28.cis");
+MODULE_FIRMWARE("cis/DP83903.cis");
+MODULE_FIRMWARE("cis/3CCFEM556.cis");
+MODULE_FIRMWARE("cis/3CXEM556.cis");
+MODULE_FIRMWARE("cis/SW_8xx_SER.cis");
+MODULE_FIRMWARE("cis/SW_7xx_SER.cis");
+MODULE_FIRMWARE("cis/SW_555_SER.cis");
+MODULE_FIRMWARE("cis/MT5634ZLX.cis");
+MODULE_FIRMWARE("cis/COMpad2.cis");
+MODULE_FIRMWARE("cis/COMpad4.cis");
+MODULE_FIRMWARE("cis/RS-COM-2P.cis");
+
+static struct pcmcia_driver serial_cs_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "serial_cs",
+       .probe          = serial_probe,
+       .remove         = serial_detach,
+       .id_table       = serial_ids,
+       .suspend        = serial_suspend,
+       .resume         = serial_resume,
+};
+
+static int __init init_serial_cs(void)
+{
+       return pcmcia_register_driver(&serial_cs_driver);
+}
+
+static void __exit exit_serial_cs(void)
+{
+       pcmcia_unregister_driver(&serial_cs_driver);
+}
+
+module_init(init_serial_cs);
+module_exit(exit_serial_cs);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250_accent.c
deleted file mode 100644 (file)
index 34b51c6..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  Copyright (C) 2005 Russell King.
- *  Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq)                               \
-       {                                               \
-               .iobase         = _base,                \
-               .irq            = _irq,                 \
-               .uartclk        = 1843200,              \
-               .iotype         = UPIO_PORT,            \
-               .flags          = UPF_BOOT_AUTOCONF,    \
-       }
-
-static struct plat_serial8250_port accent_data[] = {
-       PORT(0x330, 4),
-       PORT(0x338, 4),
-       { },
-};
-
-static struct platform_device accent_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_ACCENT,
-       .dev                    = {
-               .platform_data  = accent_data,
-       },
-};
-
-static int __init accent_init(void)
-{
-       return platform_device_register(&accent_device);
-}
-
-module_init(accent_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Accent Async cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_acorn.c b/drivers/tty/serial/8250_acorn.c
deleted file mode 100644 (file)
index b0ce8c5..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  linux/drivers/serial/acorn.c
- *
- *  Copyright (C) 1996-2003 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/ecard.h>
-#include <asm/string.h>
-
-#include "8250.h"
-
-#define MAX_PORTS      3
-
-struct serial_card_type {
-       unsigned int    num_ports;
-       unsigned int    uartclk;
-       unsigned int    type;
-       unsigned int    offset[MAX_PORTS];
-};
-
-struct serial_card_info {
-       unsigned int    num_ports;
-       int             ports[MAX_PORTS];
-       void __iomem *vaddr;
-};
-
-static int __devinit
-serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-       struct serial_card_info *info;
-       struct serial_card_type *type = id->data;
-       struct uart_port port;
-       unsigned long bus_addr;
-       unsigned int i;
-
-       info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       info->num_ports = type->num_ports;
-
-       bus_addr = ecard_resource_start(ec, type->type);
-       info->vaddr = ecardm_iomap(ec, type->type, 0, 0);
-       if (!info->vaddr) {
-               kfree(info);
-               return -ENOMEM;
-       }
-
-       ecard_set_drvdata(ec, info);
-
-       memset(&port, 0, sizeof(struct uart_port));
-       port.irq        = ec->irq;
-       port.flags      = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
-       port.uartclk    = type->uartclk;
-       port.iotype     = UPIO_MEM;
-       port.regshift   = 2;
-       port.dev        = &ec->dev;
-
-       for (i = 0; i < info->num_ports; i ++) {
-               port.membase = info->vaddr + type->offset[i];
-               port.mapbase = bus_addr + type->offset[i];
-
-               info->ports[i] = serial8250_register_port(&port);
-       }
-
-       return 0;
-}
-
-static void __devexit serial_card_remove(struct expansion_card *ec)
-{
-       struct serial_card_info *info = ecard_get_drvdata(ec);
-       int i;
-
-       ecard_set_drvdata(ec, NULL);
-
-       for (i = 0; i < info->num_ports; i++)
-               if (info->ports[i] > 0)
-                       serial8250_unregister_port(info->ports[i]);
-
-       kfree(info);
-}
-
-static struct serial_card_type atomwide_type = {
-       .num_ports      = 3,
-       .uartclk        = 7372800,
-       .type           = ECARD_RES_IOCSLOW,
-       .offset         = { 0x2800, 0x2400, 0x2000 },
-};
-
-static struct serial_card_type serport_type = {
-       .num_ports      = 2,
-       .uartclk        = 3686400,
-       .type           = ECARD_RES_IOCSLOW,
-       .offset         = { 0x2000, 0x2020 },
-};
-
-static const struct ecard_id serial_cids[] = {
-       { MANU_ATOMWIDE,        PROD_ATOMWIDE_3PSERIAL, &atomwide_type  },
-       { MANU_SERPORT,         PROD_SERPORT_DSPORT,    &serport_type   },
-       { 0xffff, 0xffff }
-};
-
-static struct ecard_driver serial_card_driver = {
-       .probe          = serial_card_probe,
-       .remove         = __devexit_p(serial_card_remove),
-       .id_table       = serial_cids,
-       .drv = {
-               .name   = "8250_acorn",
-       },
-};
-
-static int __init serial_card_init(void)
-{
-       return ecard_register_driver(&serial_card_driver);
-}
-
-static void __exit serial_card_exit(void)
-{
-       ecard_remove_driver(&serial_card_driver);
-}
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
-MODULE_LICENSE("GPL");
-
-module_init(serial_card_init);
-module_exit(serial_card_exit);
diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250_boca.c
deleted file mode 100644 (file)
index d125dc1..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  Copyright (C) 2005 Russell King.
- *  Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq)                               \
-       {                                               \
-               .iobase         = _base,                \
-               .irq            = _irq,                 \
-               .uartclk        = 1843200,              \
-               .iotype         = UPIO_PORT,            \
-               .flags          = UPF_BOOT_AUTOCONF,    \
-       }
-
-static struct plat_serial8250_port boca_data[] = {
-       PORT(0x100, 12),
-       PORT(0x108, 12),
-       PORT(0x110, 12),
-       PORT(0x118, 12),
-       PORT(0x120, 12),
-       PORT(0x128, 12),
-       PORT(0x130, 12),
-       PORT(0x138, 12),
-       PORT(0x140, 12),
-       PORT(0x148, 12),
-       PORT(0x150, 12),
-       PORT(0x158, 12),
-       PORT(0x160, 12),
-       PORT(0x168, 12),
-       PORT(0x170, 12),
-       PORT(0x178, 12),
-       { },
-};
-
-static struct platform_device boca_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_BOCA,
-       .dev                    = {
-               .platform_data  = boca_data,
-       },
-};
-
-static int __init boca_init(void)
-{
-       return platform_device_register(&boca_device);
-}
-
-module_init(boca_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Boca cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_dw.c b/drivers/tty/serial/8250_dw.c
deleted file mode 100644 (file)
index f574eef..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Synopsys DesignWare 8250 driver.
- *
- * Copyright 2011 Picochip, Jamie Iles.
- *
- * 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.
- *
- * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
- * LCR is written whilst busy.  If it is, then a busy detect interrupt is
- * raised, the LCR needs to be rewritten and the uart status register read.
- */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-struct dw8250_data {
-       int     last_lcr;
-       int     line;
-};
-
-static void dw8250_serial_out(struct uart_port *p, int offset, int value)
-{
-       struct dw8250_data *d = p->private_data;
-
-       if (offset == UART_LCR)
-               d->last_lcr = value;
-
-       offset <<= p->regshift;
-       writeb(value, p->membase + offset);
-}
-
-static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
-{
-       offset <<= p->regshift;
-
-       return readb(p->membase + offset);
-}
-
-static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
-{
-       struct dw8250_data *d = p->private_data;
-
-       if (offset == UART_LCR)
-               d->last_lcr = value;
-
-       offset <<= p->regshift;
-       writel(value, p->membase + offset);
-}
-
-static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
-{
-       offset <<= p->regshift;
-
-       return readl(p->membase + offset);
-}
-
-/* Offset for the DesignWare's UART Status Register. */
-#define UART_USR       0x1f
-
-static int dw8250_handle_irq(struct uart_port *p)
-{
-       struct dw8250_data *d = p->private_data;
-       unsigned int iir = p->serial_in(p, UART_IIR);
-
-       if (serial8250_handle_irq(p, iir)) {
-               return 1;
-       } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
-               /* Clear the USR and write the LCR again. */
-               (void)p->serial_in(p, UART_USR);
-               p->serial_out(p, d->last_lcr, UART_LCR);
-
-               return 1;
-       }
-
-       return 0;
-}
-
-static int __devinit dw8250_probe(struct platform_device *pdev)
-{
-       struct uart_port port = {};
-       struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       struct device_node *np = pdev->dev.of_node;
-       u32 val;
-       struct dw8250_data *data;
-
-       if (!regs || !irq) {
-               dev_err(&pdev->dev, "no registers/irq defined\n");
-               return -EINVAL;
-       }
-
-       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       port.private_data = data;
-
-       spin_lock_init(&port.lock);
-       port.mapbase = regs->start;
-       port.irq = irq->start;
-       port.handle_irq = dw8250_handle_irq;
-       port.type = PORT_8250;
-       port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
-               UPF_FIXED_PORT | UPF_FIXED_TYPE;
-       port.dev = &pdev->dev;
-
-       port.iotype = UPIO_MEM;
-       port.serial_in = dw8250_serial_in;
-       port.serial_out = dw8250_serial_out;
-       if (!of_property_read_u32(np, "reg-io-width", &val)) {
-               switch (val) {
-               case 1:
-                       break;
-               case 4:
-                       port.iotype = UPIO_MEM32;
-                       port.serial_in = dw8250_serial_in32;
-                       port.serial_out = dw8250_serial_out32;
-                       break;
-               default:
-                       dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
-                               val);
-                       return -EINVAL;
-               }
-       }
-
-       if (!of_property_read_u32(np, "reg-shift", &val))
-               port.regshift = val;
-
-       if (of_property_read_u32(np, "clock-frequency", &val)) {
-               dev_err(&pdev->dev, "no clock-frequency property set\n");
-               return -EINVAL;
-       }
-       port.uartclk = val;
-
-       data->line = serial8250_register_port(&port);
-       if (data->line < 0)
-               return data->line;
-
-       platform_set_drvdata(pdev, data);
-
-       return 0;
-}
-
-static int __devexit dw8250_remove(struct platform_device *pdev)
-{
-       struct dw8250_data *data = platform_get_drvdata(pdev);
-
-       serial8250_unregister_port(data->line);
-
-       return 0;
-}
-
-static const struct of_device_id dw8250_match[] = {
-       { .compatible = "snps,dw-apb-uart" },
-       { /* Sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, dw8250_match);
-
-static struct platform_driver dw8250_platform_driver = {
-       .driver = {
-               .name           = "dw-apb-uart",
-               .owner          = THIS_MODULE,
-               .of_match_table = dw8250_match,
-       },
-       .probe                  = dw8250_probe,
-       .remove                 = __devexit_p(dw8250_remove),
-};
-
-module_platform_driver(dw8250_platform_driver);
-
-MODULE_AUTHOR("Jamie Iles");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
diff --git a/drivers/tty/serial/8250_early.c b/drivers/tty/serial/8250_early.c
deleted file mode 100644 (file)
index eaafb98..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Early serial console for 8250/16550 devices
- *
- * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
- *     Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
- * and on early_printk.c by Andi Kleen.
- *
- * This is for use before the serial driver has initialized, in
- * particular, before the UARTs have been discovered and named.
- * Instead of specifying the console device as, e.g., "ttyS0",
- * we locate the device directly by its MMIO or I/O port address.
- *
- * The user can specify the device directly, e.g.,
- *     earlycon=uart8250,io,0x3f8,9600n8
- *     earlycon=uart8250,mmio,0xff5e0000,115200n8
- *     earlycon=uart8250,mmio32,0xff5e0000,115200n8
- * or
- *     console=uart8250,io,0x3f8,9600n8
- *     console=uart8250,mmio,0xff5e0000,115200n8
- *     console=uart8250,mmio32,0xff5e0000,115200n8
- */
-
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <asm/io.h>
-#include <asm/serial.h>
-#ifdef CONFIG_FIX_EARLYCON_MEM
-#include <asm/pgtable.h>
-#include <asm/fixmap.h>
-#endif
-
-struct early_serial8250_device {
-       struct uart_port port;
-       char options[16];               /* e.g., 115200n8 */
-       unsigned int baud;
-};
-
-static struct early_serial8250_device early_device;
-
-static unsigned int __init serial_in(struct uart_port *port, int offset)
-{
-       switch (port->iotype) {
-       case UPIO_MEM:
-               return readb(port->membase + offset);
-       case UPIO_MEM32:
-               return readl(port->membase + (offset << 2));
-       case UPIO_PORT:
-               return inb(port->iobase + offset);
-       default:
-               return 0;
-       }
-}
-
-static void __init serial_out(struct uart_port *port, int offset, int value)
-{
-       switch (port->iotype) {
-       case UPIO_MEM:
-               writeb(value, port->membase + offset);
-               break;
-       case UPIO_MEM32:
-               writel(value, port->membase + (offset << 2));
-               break;
-       case UPIO_PORT:
-               outb(value, port->iobase + offset);
-               break;
-       }
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void __init wait_for_xmitr(struct uart_port *port)
-{
-       unsigned int status;
-
-       for (;;) {
-               status = serial_in(port, UART_LSR);
-               if ((status & BOTH_EMPTY) == BOTH_EMPTY)
-                       return;
-               cpu_relax();
-       }
-}
-
-static void __init serial_putc(struct uart_port *port, int c)
-{
-       wait_for_xmitr(port);
-       serial_out(port, UART_TX, c);
-}
-
-static void __init early_serial8250_write(struct console *console,
-                                       const char *s, unsigned int count)
-{
-       struct uart_port *port = &early_device.port;
-       unsigned int ier;
-
-       /* Save the IER and disable interrupts */
-       ier = serial_in(port, UART_IER);
-       serial_out(port, UART_IER, 0);
-
-       uart_console_write(port, s, count, serial_putc);
-
-       /* Wait for transmitter to become empty and restore the IER */
-       wait_for_xmitr(port);
-       serial_out(port, UART_IER, ier);
-}
-
-static unsigned int __init probe_baud(struct uart_port *port)
-{
-       unsigned char lcr, dll, dlm;
-       unsigned int quot;
-
-       lcr = serial_in(port, UART_LCR);
-       serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
-       dll = serial_in(port, UART_DLL);
-       dlm = serial_in(port, UART_DLM);
-       serial_out(port, UART_LCR, lcr);
-
-       quot = (dlm << 8) | dll;
-       return (port->uartclk / 16) / quot;
-}
-
-static void __init init_port(struct early_serial8250_device *device)
-{
-       struct uart_port *port = &device->port;
-       unsigned int divisor;
-       unsigned char c;
-
-       serial_out(port, UART_LCR, 0x3);        /* 8n1 */
-       serial_out(port, UART_IER, 0);          /* no interrupt */
-       serial_out(port, UART_FCR, 0);          /* no fifo */
-       serial_out(port, UART_MCR, 0x3);        /* DTR + RTS */
-
-       divisor = port->uartclk / (16 * device->baud);
-       c = serial_in(port, UART_LCR);
-       serial_out(port, UART_LCR, c | UART_LCR_DLAB);
-       serial_out(port, UART_DLL, divisor & 0xff);
-       serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
-       serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
-}
-
-static int __init parse_options(struct early_serial8250_device *device,
-                                                               char *options)
-{
-       struct uart_port *port = &device->port;
-       int mmio, mmio32, length;
-
-       if (!options)
-               return -ENODEV;
-
-       port->uartclk = BASE_BAUD * 16;
-
-       mmio = !strncmp(options, "mmio,", 5);
-       mmio32 = !strncmp(options, "mmio32,", 7);
-       if (mmio || mmio32) {
-               port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
-               port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
-                                              &options, 0);
-               if (mmio32)
-                       port->regshift = 2;
-#ifdef CONFIG_FIX_EARLYCON_MEM
-               set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
-                                       port->mapbase & PAGE_MASK);
-               port->membase =
-                       (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
-               port->membase += port->mapbase & ~PAGE_MASK;
-#else
-               port->membase = ioremap_nocache(port->mapbase, 64);
-               if (!port->membase) {
-                       printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
-                               __func__,
-                              (unsigned long long) port->mapbase);
-                       return -ENOMEM;
-               }
-#endif
-       } else if (!strncmp(options, "io,", 3)) {
-               port->iotype = UPIO_PORT;
-               port->iobase = simple_strtoul(options + 3, &options, 0);
-               mmio = 0;
-       } else
-               return -EINVAL;
-
-       options = strchr(options, ',');
-       if (options) {
-               options++;
-               device->baud = simple_strtoul(options, NULL, 0);
-               length = min(strcspn(options, " "), sizeof(device->options));
-               strncpy(device->options, options, length);
-       } else {
-               device->baud = probe_baud(port);
-               snprintf(device->options, sizeof(device->options), "%u",
-                       device->baud);
-       }
-
-       if (mmio || mmio32)
-               printk(KERN_INFO
-                      "Early serial console at MMIO%s 0x%llx (options '%s')\n",
-                       mmio32 ? "32" : "",
-                       (unsigned long long)port->mapbase,
-                       device->options);
-       else
-               printk(KERN_INFO
-                     "Early serial console at I/O port 0x%lx (options '%s')\n",
-                       port->iobase,
-                       device->options);
-
-       return 0;
-}
-
-static struct console early_serial8250_console __initdata = {
-       .name   = "uart",
-       .write  = early_serial8250_write,
-       .flags  = CON_PRINTBUFFER | CON_BOOT,
-       .index  = -1,
-};
-
-static int __init early_serial8250_setup(char *options)
-{
-       struct early_serial8250_device *device = &early_device;
-       int err;
-
-       if (device->port.membase || device->port.iobase)
-               return 0;
-
-       err = parse_options(device, options);
-       if (err < 0)
-               return err;
-
-       init_port(device);
-       return 0;
-}
-
-int __init setup_early_serial8250_console(char *cmdline)
-{
-       char *options;
-       int err;
-
-       options = strstr(cmdline, "uart8250,");
-       if (!options) {
-               options = strstr(cmdline, "uart,");
-               if (!options)
-                       return 0;
-       }
-
-       options = strchr(cmdline, ',') + 1;
-       err = early_serial8250_setup(options);
-       if (err < 0)
-               return err;
-
-       register_console(&early_serial8250_console);
-
-       return 0;
-}
-
-int serial8250_find_port_for_earlycon(void)
-{
-       struct early_serial8250_device *device = &early_device;
-       struct uart_port *port = &device->port;
-       int line;
-       int ret;
-
-       if (!device->port.membase && !device->port.iobase)
-               return -ENODEV;
-
-       line = serial8250_find_port(port);
-       if (line < 0)
-               return -ENODEV;
-
-       ret = update_console_cmdline("uart", 8250,
-                            "ttyS", line, device->options);
-       if (ret < 0)
-               ret = update_console_cmdline("uart", 0,
-                                    "ttyS", line, device->options);
-
-       return ret;
-}
-
-early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250_exar_st16c554.c
deleted file mode 100644 (file)
index bf53aab..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
- *  Based on 8250_boca.
- *
- *  Copyright (C) 2005 Russell King.
- *  Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq)                               \
-       {                                               \
-               .iobase         = _base,                \
-               .irq            = _irq,                 \
-               .uartclk        = 1843200,              \
-               .iotype         = UPIO_PORT,            \
-               .flags          = UPF_BOOT_AUTOCONF,    \
-       }
-
-static struct plat_serial8250_port exar_data[] = {
-       PORT(0x100, 5),
-       PORT(0x108, 5),
-       PORT(0x110, 5),
-       PORT(0x118, 5),
-       { },
-};
-
-static struct platform_device exar_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_EXAR_ST16C554,
-       .dev                    = {
-               .platform_data  = exar_data,
-       },
-};
-
-static int __init exar_init(void)
-{
-       return platform_device_register(&exar_device);
-}
-
-module_init(exar_init);
-
-MODULE_AUTHOR("Paul B Schroeder");
-MODULE_DESCRIPTION("8250 serial probe module for Exar cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250_fourport.c
deleted file mode 100644 (file)
index be15826..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  Copyright (C) 2005 Russell King.
- *  Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define PORT(_base,_irq)                                               \
-       {                                                               \
-               .iobase         = _base,                                \
-               .irq            = _irq,                                 \
-               .uartclk        = 1843200,                              \
-               .iotype         = UPIO_PORT,                            \
-               .flags          = UPF_BOOT_AUTOCONF | UPF_FOURPORT,     \
-       }
-
-static struct plat_serial8250_port fourport_data[] = {
-       PORT(0x1a0, 9),
-       PORT(0x1a8, 9),
-       PORT(0x1b0, 9),
-       PORT(0x1b8, 9),
-       PORT(0x2a0, 5),
-       PORT(0x2a8, 5),
-       PORT(0x2b0, 5),
-       PORT(0x2b8, 5),
-       { },
-};
-
-static struct platform_device fourport_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_FOURPORT,
-       .dev                    = {
-               .platform_data  = fourport_data,
-       },
-};
-
-static int __init fourport_init(void)
-{
-       return platform_device_register(&fourport_device);
-}
-
-module_init(fourport_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for AST Fourport cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_fsl.c b/drivers/tty/serial/8250_fsl.c
deleted file mode 100644 (file)
index f4d3c47..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <linux/serial_reg.h>
-#include <linux/serial_8250.h>
-
-#include "8250.h"
-
-/*
- * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker.
- *
- * 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 isn't a full driver; it just provides an alternate IRQ
- * handler to deal with an errata.  Everything else is just
- * using the bog standard 8250 support.
- *
- * We follow code flow of serial8250_default_handle_irq() but add
- * a check for a break and insert a dummy read on the Rx for the
- * immediately following IRQ event.
- *
- * We re-use the already existing "bug handling" lsr_saved_flags
- * field to carry the "what we just did" information from the one
- * IRQ event to the next one.
- */
-
-int fsl8250_handle_irq(struct uart_port *port)
-{
-       unsigned char lsr, orig_lsr;
-       unsigned long flags;
-       unsigned int iir;
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       iir = port->serial_in(port, UART_IIR);
-       if (iir & UART_IIR_NO_INT) {
-               spin_unlock_irqrestore(&up->port.lock, flags);
-               return 0;
-       }
-
-       /* This is the WAR; if last event was BRK, then read and return */
-       if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
-               up->lsr_saved_flags &= ~UART_LSR_BI;
-               port->serial_in(port, UART_RX);
-               spin_unlock_irqrestore(&up->port.lock, flags);
-               return 1;
-       }
-
-       lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR);
-
-       if (lsr & (UART_LSR_DR | UART_LSR_BI))
-               lsr = serial8250_rx_chars(up, lsr);
-
-       serial8250_modem_status(up);
-
-       if (lsr & UART_LSR_THRE)
-               serial8250_tx_chars(up);
-
-       up->lsr_saved_flags = orig_lsr;
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       return 1;
-}
diff --git a/drivers/tty/serial/8250_gsc.c b/drivers/tty/serial/8250_gsc.c
deleted file mode 100644 (file)
index d8c0ffb..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *     Serial Device Initialisation for Lasi/Asp/Wax/Dino
- *
- *     (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/serial_core.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-
-#include <asm/hardware.h>
-#include <asm/parisc-device.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-static int __init serial_init_chip(struct parisc_device *dev)
-{
-       struct uart_port port;
-       unsigned long address;
-       int err;
-
-       if (!dev->irq) {
-               /* We find some unattached serial ports by walking native
-                * busses.  These should be silently ignored.  Otherwise,
-                * what we have here is a missing parent device, so tell
-                * the user what they're missing.
-                */
-               if (parisc_parent(dev)->id.hw_type != HPHW_IOA)
-                       printk(KERN_INFO
-                               "Serial: device 0x%llx not configured.\n"
-                               "Enable support for Wax, Lasi, Asp or Dino.\n",
-                               (unsigned long long)dev->hpa.start);
-               return -ENODEV;
-       }
-
-       address = dev->hpa.start;
-       if (dev->id.sversion != 0x8d)
-               address += 0x800;
-
-       memset(&port, 0, sizeof(port));
-       port.iotype     = UPIO_MEM;
-       /* 7.272727MHz on Lasi.  Assumed the same for Dino, Wax and Timi. */
-       port.uartclk    = 7272727;
-       port.mapbase    = address;
-       port.membase    = ioremap_nocache(address, 16);
-       port.irq        = dev->irq;
-       port.flags      = UPF_BOOT_AUTOCONF;
-       port.dev        = &dev->dev;
-
-       err = serial8250_register_port(&port);
-       if (err < 0) {
-               printk(KERN_WARNING
-                       "serial8250_register_port returned error %d\n", err);
-               iounmap(port.membase);
-               return err;
-       }
-
-       return 0;
-}
-
-static struct parisc_device_id serial_tbl[] = {
-       { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 },
-       { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c },
-       { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d },
-       { 0 }
-};
-
-/* Hack.  Some machines have SERIAL_0 attached to Lasi and SERIAL_1
- * attached to Dino.  Unfortunately, Dino appears before Lasi in the device
- * tree.  To ensure that ttyS0 == SERIAL_0, we register two drivers; one
- * which only knows about Lasi and then a second which will find all the
- * other serial ports.  HPUX ignores this problem.
- */
-static struct parisc_device_id lasi_tbl[] = {
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */
-       { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */
-       { 0 }
-};
-
-
-MODULE_DEVICE_TABLE(parisc, serial_tbl);
-
-static struct parisc_driver lasi_driver = {
-       .name           = "serial_1",
-       .id_table       = lasi_tbl,
-       .probe          = serial_init_chip,
-};
-
-static struct parisc_driver serial_driver = {
-       .name           = "serial",
-       .id_table       = serial_tbl,
-       .probe          = serial_init_chip,
-};
-
-static int __init probe_serial_gsc(void)
-{
-       register_parisc_driver(&lasi_driver);
-       register_parisc_driver(&serial_driver);
-       return 0;
-}
-
-module_init(probe_serial_gsc);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_hp300.c b/drivers/tty/serial/8250_hp300.c
deleted file mode 100644 (file)
index c13438c..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Driver for the 98626/98644/internal serial interface on hp300/hp400
- * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
- *
- * Ported from 2.2 and modified to use the normal 8250 driver
- * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-#include <linux/dio.h>
-#include <linux/console.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
-#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
-#endif
-
-#ifdef CONFIG_HPAPCI
-struct hp300_port
-{
-       struct hp300_port *next;        /* next port */
-       int line;                       /* line (tty) number */
-};
-
-static struct hp300_port *hp300_ports;
-#endif
-
-#ifdef CONFIG_HPDCA
-
-static int __devinit hpdca_init_one(struct dio_dev *d,
-                                       const struct dio_device_id *ent);
-static void __devexit hpdca_remove_one(struct dio_dev *d);
-
-static struct dio_device_id hpdca_dio_tbl[] = {
-       { DIO_ID_DCA0 },
-       { DIO_ID_DCA0REM },
-       { DIO_ID_DCA1 },
-       { DIO_ID_DCA1REM },
-       { 0 }
-};
-
-static struct dio_driver hpdca_driver = {
-       .name      = "hpdca",
-       .id_table  = hpdca_dio_tbl,
-       .probe     = hpdca_init_one,
-       .remove    = __devexit_p(hpdca_remove_one),
-};
-
-#endif
-
-static unsigned int num_ports;
-
-extern int hp300_uart_scode;
-
-/* Offset to UART registers from base of DCA */
-#define UART_OFFSET    17
-
-#define DCA_ID         0x01    /* ID (read), reset (write) */
-#define DCA_IC         0x03    /* Interrupt control        */
-
-/* Interrupt control */
-#define DCA_IC_IE      0x80    /* Master interrupt enable  */
-
-#define HPDCA_BAUD_BASE 153600
-
-/* Base address of the Frodo part */
-#define FRODO_BASE     (0x41c000)
-
-/*
- * Where we find the 8250-like APCI ports, and how far apart they are.
- */
-#define FRODO_APCIBASE         0x0
-#define FRODO_APCISPACE                0x20
-#define FRODO_APCI_OFFSET(x)   (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
-
-#define HPAPCI_BAUD_BASE 500400
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-/*
- * Parse the bootinfo to find descriptions for headless console and
- * debug serial ports and register them with the 8250 driver.
- * This function should be called before serial_console_init() is called
- * to make sure the serial console will be available for use. IA-64 kernel
- * calls this function from setup_arch() after the EFI and ACPI tables have
- * been parsed.
- */
-int __init hp300_setup_serial_console(void)
-{
-       int scode;
-       struct uart_port port;
-
-       memset(&port, 0, sizeof(port));
-
-       if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
-               return 0;
-
-       if (DIO_SCINHOLE(hp300_uart_scode))
-               return 0;
-
-       scode = hp300_uart_scode;
-
-       /* Memory mapped I/O */
-       port.iotype = UPIO_MEM;
-       port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
-       port.type = PORT_UNKNOWN;
-
-       /* Check for APCI console */
-       if (scode == 256) {
-#ifdef CONFIG_HPAPCI
-               printk(KERN_INFO "Serial console is HP APCI 1\n");
-
-               port.uartclk = HPAPCI_BAUD_BASE * 16;
-               port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
-               port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
-               port.regshift = 2;
-               add_preferred_console("ttyS", port.line, "9600n8");
-#else
-               printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
-               return 0;
-#endif
-       } else {
-#ifdef CONFIG_HPDCA
-               unsigned long pa = dio_scodetophysaddr(scode);
-               if (!pa)
-                       return 0;
-
-               printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
-
-               port.uartclk = HPDCA_BAUD_BASE * 16;
-               port.mapbase = (pa + UART_OFFSET);
-               port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
-               port.regshift = 1;
-               port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
-
-               /* Enable board-interrupts */
-               out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
-
-               if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
-                       add_preferred_console("ttyS", port.line, "9600n8");
-#else
-               printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
-               return 0;
-#endif
-       }
-
-       if (early_serial_setup(&port) < 0)
-               printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
-       return 0;
-}
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
-#ifdef CONFIG_HPDCA
-static int __devinit hpdca_init_one(struct dio_dev *d,
-                               const struct dio_device_id *ent)
-{
-       struct uart_port port;
-       int line;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-       if (hp300_uart_scode == d->scode) {
-               /* Already got it. */
-               return 0;
-       }
-#endif
-       memset(&port, 0, sizeof(struct uart_port));
-
-       /* Memory mapped I/O */
-       port.iotype = UPIO_MEM;
-       port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
-       port.irq = d->ipl;
-       port.uartclk = HPDCA_BAUD_BASE * 16;
-       port.mapbase = (d->resource.start + UART_OFFSET);
-       port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
-       port.regshift = 1;
-       port.dev = &d->dev;
-       line = serial8250_register_port(&port);
-
-       if (line < 0) {
-               printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
-                      " irq %d failed\n", d->scode, port.irq);
-               return -ENOMEM;
-       }
-
-       /* Enable board-interrupts */
-       out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
-       dio_set_drvdata(d, (void *)line);
-
-       /* Reset the DCA */
-       out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
-       udelay(100);
-
-       num_ports++;
-
-       return 0;
-}
-#endif
-
-static int __init hp300_8250_init(void)
-{
-       static int called;
-#ifdef CONFIG_HPAPCI
-       int line;
-       unsigned long base;
-       struct uart_port uport;
-       struct hp300_port *port;
-       int i;
-#endif
-       if (called)
-               return -ENODEV;
-       called = 1;
-
-       if (!MACH_IS_HP300)
-               return -ENODEV;
-
-#ifdef CONFIG_HPDCA
-       dio_register_driver(&hpdca_driver);
-#endif
-#ifdef CONFIG_HPAPCI
-       if (hp300_model < HP_400) {
-               if (!num_ports)
-                       return -ENODEV;
-               return 0;
-       }
-       /* These models have the Frodo chip.
-        * Port 0 is reserved for the Apollo Domain keyboard.
-        * Port 1 is either the console or the DCA.
-        */
-       for (i = 1; i < 4; i++) {
-               /* Port 1 is the console on a 425e, on other machines it's
-                * mapped to DCA.
-                */
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-               if (i == 1)
-                       continue;
-#endif
-
-               /* Create new serial device */
-               port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
-               if (!port)
-                       return -ENOMEM;
-
-               memset(&uport, 0, sizeof(struct uart_port));
-
-               base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
-
-               /* Memory mapped I/O */
-               uport.iotype = UPIO_MEM;
-               uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
-                             | UPF_BOOT_AUTOCONF;
-               /* XXX - no interrupt support yet */
-               uport.irq = 0;
-               uport.uartclk = HPAPCI_BAUD_BASE * 16;
-               uport.mapbase = base;
-               uport.membase = (char *)(base + DIO_VIRADDRBASE);
-               uport.regshift = 2;
-
-               line = serial8250_register_port(&uport);
-
-               if (line < 0) {
-                       printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
-                              " %d irq %d failed\n", i, uport.irq);
-                       kfree(port);
-                       continue;
-               }
-
-               port->line = line;
-               port->next = hp300_ports;
-               hp300_ports = port;
-
-               num_ports++;
-       }
-#endif
-
-       /* Any boards found? */
-       if (!num_ports)
-               return -ENODEV;
-
-       return 0;
-}
-
-#ifdef CONFIG_HPDCA
-static void __devexit hpdca_remove_one(struct dio_dev *d)
-{
-       int line;
-
-       line = (int) dio_get_drvdata(d);
-       if (d->resource.start) {
-               /* Disable board-interrupts */
-               out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
-       }
-       serial8250_unregister_port(line);
-}
-#endif
-
-static void __exit hp300_8250_exit(void)
-{
-#ifdef CONFIG_HPAPCI
-       struct hp300_port *port, *to_free;
-
-       for (port = hp300_ports; port; ) {
-               serial8250_unregister_port(port->line);
-               to_free = port;
-               port = port->next;
-               kfree(to_free);
-       }
-
-       hp300_ports = NULL;
-#endif
-#ifdef CONFIG_HPDCA
-       dio_unregister_driver(&hpdca_driver);
-#endif
-}
-
-module_init(hp300_8250_init);
-module_exit(hp300_8250_exit);
-MODULE_DESCRIPTION("HP DCA/APCI serial driver");
-MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250_hub6.c
deleted file mode 100644 (file)
index a5c778e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright (C) 2005 Russell King.
- *  Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#define HUB6(card,port)                                                        \
-       {                                                               \
-               .iobase         = 0x302,                                \
-               .irq            = 3,                                    \
-               .uartclk        = 1843200,                              \
-               .iotype         = UPIO_HUB6,                            \
-               .flags          = UPF_BOOT_AUTOCONF,                    \
-               .hub6           = (card) << 6 | (port) << 3 | 1,        \
-       }
-
-static struct plat_serial8250_port hub6_data[] = {
-       HUB6(0, 0),
-       HUB6(0, 1),
-       HUB6(0, 2),
-       HUB6(0, 3),
-       HUB6(0, 4),
-       HUB6(0, 5),
-       HUB6(1, 0),
-       HUB6(1, 1),
-       HUB6(1, 2),
-       HUB6(1, 3),
-       HUB6(1, 4),
-       HUB6(1, 5),
-       { },
-};
-
-static struct platform_device hub6_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_HUB6,
-       .dev                    = {
-               .platform_data  = hub6_data,
-       },
-};
-
-static int __init hub6_init(void)
-{
-       return platform_device_register(&hub6_device);
-}
-
-module_init(hub6_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for Hub6 cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250_mca.c
deleted file mode 100644 (file)
index d20abf0..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Copyright (C) 2005 Russell King.
- *  Data taken from include/asm-i386/serial.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mca.h>
-#include <linux/serial_8250.h>
-
-/*
- * FIXME: Should we be doing AUTO_IRQ here?
- */
-#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-#define MCA_FLAGS      UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ
-#else
-#define MCA_FLAGS      UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
-#endif
-
-#define PORT(_base,_irq)                       \
-       {                                       \
-               .iobase         = _base,        \
-               .irq            = _irq,         \
-               .uartclk        = 1843200,      \
-               .iotype         = UPIO_PORT,    \
-               .flags          = MCA_FLAGS,    \
-       }
-
-static struct plat_serial8250_port mca_data[] = {
-       PORT(0x3220, 3),
-       PORT(0x3228, 3),
-       PORT(0x4220, 3),
-       PORT(0x4228, 3),
-       PORT(0x5220, 3),
-       PORT(0x5228, 3),
-       { },
-};
-
-static struct platform_device mca_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_MCA,
-       .dev                    = {
-               .platform_data  = mca_data,
-       },
-};
-
-static int __init mca_init(void)
-{
-       if (!MCA_bus)
-               return -ENODEV;
-       return platform_device_register(&mca_device);
-}
-
-module_init(mca_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("8250 serial probe module for MCA ports");
-MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
deleted file mode 100644 (file)
index da2b0b0..0000000
+++ /dev/null
@@ -1,4223 +0,0 @@
-/*
- *  Probe module for 8250/16550-type PCI serial ports.
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/8250_pci.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "8250.h"
-
-#undef SERIAL_DEBUG_PCI
-
-/*
- * init function returns:
- *  > 0 - number of ports
- *  = 0 - use board->num_ports
- *  < 0 - error
- */
-struct pci_serial_quirk {
-       u32     vendor;
-       u32     device;
-       u32     subvendor;
-       u32     subdevice;
-       int     (*probe)(struct pci_dev *dev);
-       int     (*init)(struct pci_dev *dev);
-       int     (*setup)(struct serial_private *,
-                        const struct pciserial_board *,
-                        struct uart_port *, int);
-       void    (*exit)(struct pci_dev *dev);
-};
-
-#define PCI_NUM_BAR_RESOURCES  6
-
-struct serial_private {
-       struct pci_dev          *dev;
-       unsigned int            nr;
-       void __iomem            *remapped_bar[PCI_NUM_BAR_RESOURCES];
-       struct pci_serial_quirk *quirk;
-       int                     line[0];
-};
-
-static int pci_default_setup(struct serial_private*,
-         const struct pciserial_board*, struct uart_port*, int);
-
-static void moan_device(const char *str, struct pci_dev *dev)
-{
-       printk(KERN_WARNING
-              "%s: %s\n"
-              "Please send the output of lspci -vv, this\n"
-              "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
-              "manufacturer and name of serial board or\n"
-              "modem board to rmk+serial@arm.linux.org.uk.\n",
-              pci_name(dev), str, dev->vendor, dev->device,
-              dev->subsystem_vendor, dev->subsystem_device);
-}
-
-static int
-setup_port(struct serial_private *priv, struct uart_port *port,
-          int bar, int offset, int regshift)
-{
-       struct pci_dev *dev = priv->dev;
-       unsigned long base, len;
-
-       if (bar >= PCI_NUM_BAR_RESOURCES)
-               return -EINVAL;
-
-       base = pci_resource_start(dev, bar);
-
-       if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
-               len =  pci_resource_len(dev, bar);
-
-               if (!priv->remapped_bar[bar])
-                       priv->remapped_bar[bar] = ioremap_nocache(base, len);
-               if (!priv->remapped_bar[bar])
-                       return -ENOMEM;
-
-               port->iotype = UPIO_MEM;
-               port->iobase = 0;
-               port->mapbase = base + offset;
-               port->membase = priv->remapped_bar[bar] + offset;
-               port->regshift = regshift;
-       } else {
-               port->iotype = UPIO_PORT;
-               port->iobase = base + offset;
-               port->mapbase = 0;
-               port->membase = NULL;
-               port->regshift = 0;
-       }
-       return 0;
-}
-
-/*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
-static int addidata_apci7800_setup(struct serial_private *priv,
-                               const struct pciserial_board *board,
-                               struct uart_port *port, int idx)
-{
-       unsigned int bar = 0, offset = board->first_offset;
-       bar = FL_GET_BASE(board->flags);
-
-       if (idx < 2) {
-               offset += idx * board->uart_offset;
-       } else if ((idx >= 2) && (idx < 4)) {
-               bar += 1;
-               offset += ((idx - 2) * board->uart_offset);
-       } else if ((idx >= 4) && (idx < 6)) {
-               bar += 2;
-               offset += ((idx - 4) * board->uart_offset);
-       } else if (idx >= 6) {
-               bar += 3;
-               offset += ((idx - 6) * board->uart_offset);
-       }
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * AFAVLAB uses a different mixture of BARs and offsets
- * Not that ugly ;) -- HW
- */
-static int
-afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
-             struct uart_port *port, int idx)
-{
-       unsigned int bar, offset = board->first_offset;
-
-       bar = FL_GET_BASE(board->flags);
-       if (idx < 4)
-               bar += idx;
-       else {
-               bar = 4;
-               offset += (idx - 4) * board->uart_offset;
-       }
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * HP's Remote Management Console.  The Diva chip came in several
- * different versions.  N-class, L2000 and A500 have two Diva chips, each
- * with 3 UARTs (the third UART on the second chip is unused).  Superdome
- * and Keystone have one Diva chip with 3 UARTs.  Some later machines have
- * one Diva chip, but it has been expanded to 5 UARTs.
- */
-static int pci_hp_diva_init(struct pci_dev *dev)
-{
-       int rc = 0;
-
-       switch (dev->subsystem_device) {
-       case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
-       case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
-       case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
-       case PCI_DEVICE_ID_HP_DIVA_EVEREST:
-               rc = 3;
-               break;
-       case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
-               rc = 2;
-               break;
-       case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
-               rc = 4;
-               break;
-       case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
-       case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
-               rc = 1;
-               break;
-       }
-
-       return rc;
-}
-
-/*
- * HP's Diva chip puts the 4th/5th serial port further out, and
- * some serial ports are supposed to be hidden on certain models.
- */
-static int
-pci_hp_diva_setup(struct serial_private *priv,
-               const struct pciserial_board *board,
-               struct uart_port *port, int idx)
-{
-       unsigned int offset = board->first_offset;
-       unsigned int bar = FL_GET_BASE(board->flags);
-
-       switch (priv->dev->subsystem_device) {
-       case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
-               if (idx == 3)
-                       idx++;
-               break;
-       case PCI_DEVICE_ID_HP_DIVA_EVEREST:
-               if (idx > 0)
-                       idx++;
-               if (idx > 2)
-                       idx++;
-               break;
-       }
-       if (idx > 2)
-               offset = 0x18;
-
-       offset += idx * board->uart_offset;
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * Added for EKF Intel i960 serial boards
- */
-static int pci_inteli960ni_init(struct pci_dev *dev)
-{
-       unsigned long oldval;
-
-       if (!(dev->subsystem_device & 0x1000))
-               return -ENODEV;
-
-       /* is firmware started? */
-       pci_read_config_dword(dev, 0x44, (void *)&oldval);
-       if (oldval == 0x00001000L) { /* RESET value */
-               printk(KERN_DEBUG "Local i960 firmware missing");
-               return -ENODEV;
-       }
-       return 0;
-}
-
-/*
- * Some PCI serial cards using the PLX 9050 PCI interface chip require
- * that the card interrupt be explicitly enabled or disabled.  This
- * seems to be mainly needed on card using the PLX which also use I/O
- * mapped memory.
- */
-static int pci_plx9050_init(struct pci_dev *dev)
-{
-       u8 irq_config;
-       void __iomem *p;
-
-       if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
-               moan_device("no memory in bar 0", dev);
-               return 0;
-       }
-
-       irq_config = 0x41;
-       if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
-           dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS)
-               irq_config = 0x43;
-
-       if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
-           (dev->device == PCI_DEVICE_ID_PLX_ROMULUS))
-               /*
-                * As the megawolf cards have the int pins active
-                * high, and have 2 UART chips, both ints must be
-                * enabled on the 9050. Also, the UARTS are set in
-                * 16450 mode by default, so we have to enable the
-                * 16C950 'enhanced' mode so that we can use the
-                * deep FIFOs
-                */
-               irq_config = 0x5b;
-       /*
-        * enable/disable interrupts
-        */
-       p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
-       if (p == NULL)
-               return -ENOMEM;
-       writel(irq_config, p + 0x4c);
-
-       /*
-        * Read the register back to ensure that it took effect.
-        */
-       readl(p + 0x4c);
-       iounmap(p);
-
-       return 0;
-}
-
-static void __devexit pci_plx9050_exit(struct pci_dev *dev)
-{
-       u8 __iomem *p;
-
-       if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
-               return;
-
-       /*
-        * disable interrupts
-        */
-       p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
-       if (p != NULL) {
-               writel(0, p + 0x4c);
-
-               /*
-                * Read the register back to ensure that it took effect.
-                */
-               readl(p + 0x4c);
-               iounmap(p);
-       }
-}
-
-#define NI8420_INT_ENABLE_REG  0x38
-#define NI8420_INT_ENABLE_BIT  0x2000
-
-static void __devexit pci_ni8420_exit(struct pci_dev *dev)
-{
-       void __iomem *p;
-       unsigned long base, len;
-       unsigned int bar = 0;
-
-       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
-               moan_device("no memory in bar", dev);
-               return;
-       }
-
-       base = pci_resource_start(dev, bar);
-       len =  pci_resource_len(dev, bar);
-       p = ioremap_nocache(base, len);
-       if (p == NULL)
-               return;
-
-       /* Disable the CPU Interrupt */
-       writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT),
-              p + NI8420_INT_ENABLE_REG);
-       iounmap(p);
-}
-
-
-/* MITE registers */
-#define MITE_IOWBSR1   0xc4
-#define MITE_IOWCR1    0xf4
-#define MITE_LCIMR1    0x08
-#define MITE_LCIMR2    0x10
-
-#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
-
-static void __devexit pci_ni8430_exit(struct pci_dev *dev)
-{
-       void __iomem *p;
-       unsigned long base, len;
-       unsigned int bar = 0;
-
-       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
-               moan_device("no memory in bar", dev);
-               return;
-       }
-
-       base = pci_resource_start(dev, bar);
-       len =  pci_resource_len(dev, bar);
-       p = ioremap_nocache(base, len);
-       if (p == NULL)
-               return;
-
-       /* Disable the CPU Interrupt */
-       writel(MITE_LCIMR2_CLR_CPU_IE, p + MITE_LCIMR2);
-       iounmap(p);
-}
-
-/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
-static int
-sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
-               struct uart_port *port, int idx)
-{
-       unsigned int bar, offset = board->first_offset;
-
-       bar = 0;
-
-       if (idx < 4) {
-               /* first four channels map to 0, 0x100, 0x200, 0x300 */
-               offset += idx * board->uart_offset;
-       } else if (idx < 8) {
-               /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
-               offset += idx * board->uart_offset + 0xC00;
-       } else /* we have only 8 ports on PMC-OCTALPRO */
-               return 1;
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
-* This does initialization for PMC OCTALPRO cards:
-* maps the device memory, resets the UARTs (needed, bc
-* if the module is removed and inserted again, the card
-* is in the sleep mode) and enables global interrupt.
-*/
-
-/* global control register offset for SBS PMC-OctalPro */
-#define OCT_REG_CR_OFF         0x500
-
-static int sbs_init(struct pci_dev *dev)
-{
-       u8 __iomem *p;
-
-       p = pci_ioremap_bar(dev, 0);
-
-       if (p == NULL)
-               return -ENOMEM;
-       /* Set bit-4 Control Register (UART RESET) in to reset the uarts */
-       writeb(0x10, p + OCT_REG_CR_OFF);
-       udelay(50);
-       writeb(0x0, p + OCT_REG_CR_OFF);
-
-       /* Set bit-2 (INTENABLE) of Control Register */
-       writeb(0x4, p + OCT_REG_CR_OFF);
-       iounmap(p);
-
-       return 0;
-}
-
-/*
- * Disables the global interrupt of PMC-OctalPro
- */
-
-static void __devexit sbs_exit(struct pci_dev *dev)
-{
-       u8 __iomem *p;
-
-       p = pci_ioremap_bar(dev, 0);
-       /* FIXME: What if resource_len < OCT_REG_CR_OFF */
-       if (p != NULL)
-               writeb(0, p + OCT_REG_CR_OFF);
-       iounmap(p);
-}
-
-/*
- * SIIG serial cards have an PCI interface chip which also controls
- * the UART clocking frequency. Each UART can be clocked independently
- * (except cards equipped with 4 UARTs) and initial clocking settings
- * are stored in the EEPROM chip. It can cause problems because this
- * version of serial driver doesn't support differently clocked UART's
- * on single PCI card. To prevent this, initialization functions set
- * high frequency clocking for all UART's on given card. It is safe (I
- * hope) because it doesn't touch EEPROM settings to prevent conflicts
- * with other OSes (like M$ DOS).
- *
- *  SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
- *
- * There is two family of SIIG serial cards with different PCI
- * interface chip and different configuration methods:
- *     - 10x cards have control registers in IO and/or memory space;
- *     - 20x cards have control registers in standard PCI configuration space.
- *
- * Note: all 10x cards have PCI device ids 0x10..
- *       all 20x cards have PCI device ids 0x20..
- *
- * There are also Quartet Serial cards which use Oxford Semiconductor
- * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
- *
- * Note: some SIIG cards are probed by the parport_serial object.
- */
-
-#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
-#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
-
-static int pci_siig10x_init(struct pci_dev *dev)
-{
-       u16 data;
-       void __iomem *p;
-
-       switch (dev->device & 0xfff8) {
-       case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
-               data = 0xffdf;
-               break;
-       case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
-               data = 0xf7ff;
-               break;
-       default:                        /* 1S1P, 4S */
-               data = 0xfffb;
-               break;
-       }
-
-       p = ioremap_nocache(pci_resource_start(dev, 0), 0x80);
-       if (p == NULL)
-               return -ENOMEM;
-
-       writew(readw(p + 0x28) & data, p + 0x28);
-       readw(p + 0x28);
-       iounmap(p);
-       return 0;
-}
-
-#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
-#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
-
-static int pci_siig20x_init(struct pci_dev *dev)
-{
-       u8 data;
-
-       /* Change clock frequency for the first UART. */
-       pci_read_config_byte(dev, 0x6f, &data);
-       pci_write_config_byte(dev, 0x6f, data & 0xef);
-
-       /* If this card has 2 UART, we have to do the same with second UART. */
-       if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
-           ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
-               pci_read_config_byte(dev, 0x73, &data);
-               pci_write_config_byte(dev, 0x73, data & 0xef);
-       }
-       return 0;
-}
-
-static int pci_siig_init(struct pci_dev *dev)
-{
-       unsigned int type = dev->device & 0xff00;
-
-       if (type == 0x1000)
-               return pci_siig10x_init(dev);
-       else if (type == 0x2000)
-               return pci_siig20x_init(dev);
-
-       moan_device("Unknown SIIG card", dev);
-       return -ENODEV;
-}
-
-static int pci_siig_setup(struct serial_private *priv,
-                         const struct pciserial_board *board,
-                         struct uart_port *port, int idx)
-{
-       unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
-
-       if (idx > 3) {
-               bar = 4;
-               offset = (idx - 4) * 8;
-       }
-
-       return setup_port(priv, port, bar, offset, 0);
-}
-
-/*
- * Timedia has an explosion of boards, and to avoid the PCI table from
- * growing *huge*, we use this function to collapse some 70 entries
- * in the PCI table into one, for sanity's and compactness's sake.
- */
-static const unsigned short timedia_single_port[] = {
-       0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
-};
-
-static const unsigned short timedia_dual_port[] = {
-       0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
-       0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
-       0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
-       0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
-       0xD079, 0
-};
-
-static const unsigned short timedia_quad_port[] = {
-       0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
-       0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
-       0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
-       0xB157, 0
-};
-
-static const unsigned short timedia_eight_port[] = {
-       0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
-       0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
-};
-
-static const struct timedia_struct {
-       int num;
-       const unsigned short *ids;
-} timedia_data[] = {
-       { 1, timedia_single_port },
-       { 2, timedia_dual_port },
-       { 4, timedia_quad_port },
-       { 8, timedia_eight_port }
-};
-
-/*
- * There are nearly 70 different Timedia/SUNIX PCI serial devices.  Instead of
- * listing them individually, this driver merely grabs them all with
- * PCI_ANY_ID.  Some of these devices, however, also feature a parallel port,
- * and should be left free to be claimed by parport_serial instead.
- */
-static int pci_timedia_probe(struct pci_dev *dev)
-{
-       /*
-        * Check the third digit of the subdevice ID
-        * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
-        */
-       if ((dev->subsystem_device & 0x00f0) >= 0x70) {
-               dev_info(&dev->dev,
-                       "ignoring Timedia subdevice %04x for parport_serial\n",
-                       dev->subsystem_device);
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static int pci_timedia_init(struct pci_dev *dev)
-{
-       const unsigned short *ids;
-       int i, j;
-
-       for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
-               ids = timedia_data[i].ids;
-               for (j = 0; ids[j]; j++)
-                       if (dev->subsystem_device == ids[j])
-                               return timedia_data[i].num;
-       }
-       return 0;
-}
-
-/*
- * Timedia/SUNIX uses a mixture of BARs and offsets
- * Ugh, this is ugly as all hell --- TYT
- */
-static int
-pci_timedia_setup(struct serial_private *priv,
-                 const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
-{
-       unsigned int bar = 0, offset = board->first_offset;
-
-       switch (idx) {
-       case 0:
-               bar = 0;
-               break;
-       case 1:
-               offset = board->uart_offset;
-               bar = 0;
-               break;
-       case 2:
-               bar = 1;
-               break;
-       case 3:
-               offset = board->uart_offset;
-               /* FALLTHROUGH */
-       case 4: /* BAR 2 */
-       case 5: /* BAR 3 */
-       case 6: /* BAR 4 */
-       case 7: /* BAR 5 */
-               bar = idx - 2;
-       }
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-/*
- * Some Titan cards are also a little weird
- */
-static int
-titan_400l_800l_setup(struct serial_private *priv,
-                     const struct pciserial_board *board,
-                     struct uart_port *port, int idx)
-{
-       unsigned int bar, offset = board->first_offset;
-
-       switch (idx) {
-       case 0:
-               bar = 1;
-               break;
-       case 1:
-               bar = 2;
-               break;
-       default:
-               bar = 4;
-               offset = (idx - 2) * board->uart_offset;
-       }
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int pci_xircom_init(struct pci_dev *dev)
-{
-       msleep(100);
-       return 0;
-}
-
-static int pci_ni8420_init(struct pci_dev *dev)
-{
-       void __iomem *p;
-       unsigned long base, len;
-       unsigned int bar = 0;
-
-       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
-               moan_device("no memory in bar", dev);
-               return 0;
-       }
-
-       base = pci_resource_start(dev, bar);
-       len =  pci_resource_len(dev, bar);
-       p = ioremap_nocache(base, len);
-       if (p == NULL)
-               return -ENOMEM;
-
-       /* Enable CPU Interrupt */
-       writel(readl(p + NI8420_INT_ENABLE_REG) | NI8420_INT_ENABLE_BIT,
-              p + NI8420_INT_ENABLE_REG);
-
-       iounmap(p);
-       return 0;
-}
-
-#define MITE_IOWBSR1_WSIZE     0xa
-#define MITE_IOWBSR1_WIN_OFFSET        0x800
-#define MITE_IOWBSR1_WENAB     (1 << 7)
-#define MITE_LCIMR1_IO_IE_0    (1 << 24)
-#define MITE_LCIMR2_SET_CPU_IE (1 << 31)
-#define MITE_IOWCR1_RAMSEL_MASK        0xfffffffe
-
-static int pci_ni8430_init(struct pci_dev *dev)
-{
-       void __iomem *p;
-       unsigned long base, len;
-       u32 device_window;
-       unsigned int bar = 0;
-
-       if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
-               moan_device("no memory in bar", dev);
-               return 0;
-       }
-
-       base = pci_resource_start(dev, bar);
-       len =  pci_resource_len(dev, bar);
-       p = ioremap_nocache(base, len);
-       if (p == NULL)
-               return -ENOMEM;
-
-       /* Set device window address and size in BAR0 */
-       device_window = ((base + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00)
-                       | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE;
-       writel(device_window, p + MITE_IOWBSR1);
-
-       /* Set window access to go to RAMSEL IO address space */
-       writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
-              p + MITE_IOWCR1);
-
-       /* Enable IO Bus Interrupt 0 */
-       writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
-
-       /* Enable CPU Interrupt */
-       writel(MITE_LCIMR2_SET_CPU_IE, p + MITE_LCIMR2);
-
-       iounmap(p);
-       return 0;
-}
-
-/* UART Port Control Register */
-#define NI8430_PORTCON 0x0f
-#define NI8430_PORTCON_TXVR_ENABLE     (1 << 3)
-
-static int
-pci_ni8430_setup(struct serial_private *priv,
-                const struct pciserial_board *board,
-                struct uart_port *port, int idx)
-{
-       void __iomem *p;
-       unsigned long base, len;
-       unsigned int bar, offset = board->first_offset;
-
-       if (idx >= board->num_ports)
-               return 1;
-
-       bar = FL_GET_BASE(board->flags);
-       offset += idx * board->uart_offset;
-
-       base = pci_resource_start(priv->dev, bar);
-       len =  pci_resource_len(priv->dev, bar);
-       p = ioremap_nocache(base, len);
-
-       /* enable the transceiver */
-       writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
-              p + offset + NI8430_PORTCON);
-
-       iounmap(p);
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int pci_netmos_9900_setup(struct serial_private *priv,
-                               const struct pciserial_board *board,
-                               struct uart_port *port, int idx)
-{
-       unsigned int bar;
-
-       if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
-               /* netmos apparently orders BARs by datasheet layout, so serial
-                * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
-                */
-               bar = 3 * idx;
-
-               return setup_port(priv, port, bar, 0, board->reg_shift);
-       } else {
-               return pci_default_setup(priv, board, port, idx);
-       }
-}
-
-/* the 99xx series comes with a range of device IDs and a variety
- * of capabilities:
- *
- * 9900 has varying capabilities and can cascade to sub-controllers
- *   (cascading should be purely internal)
- * 9904 is hardwired with 4 serial ports
- * 9912 and 9922 are hardwired with 2 serial ports
- */
-static int pci_netmos_9900_numports(struct pci_dev *dev)
-{
-       unsigned int c = dev->class;
-       unsigned int pi;
-       unsigned short sub_serports;
-
-       pi = (c & 0xff);
-
-       if (pi == 2) {
-               return 1;
-       } else if ((pi == 0) &&
-                          (dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
-               /* two possibilities: 0x30ps encodes number of parallel and
-                * serial ports, or 0x1000 indicates *something*. This is not
-                * immediately obvious, since the 2s1p+4s configuration seems
-                * to offer all functionality on functions 0..2, while still
-                * advertising the same function 3 as the 4s+2s1p config.
-                */
-               sub_serports = dev->subsystem_device & 0xf;
-               if (sub_serports > 0) {
-                       return sub_serports;
-               } else {
-                       printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
-                       return 0;
-               }
-       }
-
-       moan_device("unknown NetMos/Mostech program interface", dev);
-       return 0;
-}
-
-static int pci_netmos_init(struct pci_dev *dev)
-{
-       /* subdevice 0x00PS means <P> parallel, <S> serial */
-       unsigned int num_serial = dev->subsystem_device & 0xf;
-
-       if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
-               (dev->device == PCI_DEVICE_ID_NETMOS_9865))
-               return 0;
-
-       if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
-                       dev->subsystem_device == 0x0299)
-               return 0;
-
-       switch (dev->device) { /* FALLTHROUGH on all */
-               case PCI_DEVICE_ID_NETMOS_9904:
-               case PCI_DEVICE_ID_NETMOS_9912:
-               case PCI_DEVICE_ID_NETMOS_9922:
-               case PCI_DEVICE_ID_NETMOS_9900:
-                       num_serial = pci_netmos_9900_numports(dev);
-                       break;
-
-               default:
-                       if (num_serial == 0 ) {
-                               moan_device("unknown NetMos/Mostech device", dev);
-                       }
-       }
-
-       if (num_serial == 0)
-               return -ENODEV;
-
-       return num_serial;
-}
-
-/*
- * These chips are available with optionally one parallel port and up to
- * two serial ports. Unfortunately they all have the same product id.
- *
- * Basic configuration is done over a region of 32 I/O ports. The base
- * ioport is called INTA or INTC, depending on docs/other drivers.
- *
- * The region of the 32 I/O ports is configured in POSIO0R...
- */
-
-/* registers */
-#define ITE_887x_MISCR         0x9c
-#define ITE_887x_INTCBAR       0x78
-#define ITE_887x_UARTBAR       0x7c
-#define ITE_887x_PS0BAR                0x10
-#define ITE_887x_POSIO0                0x60
-
-/* I/O space size */
-#define ITE_887x_IOSIZE                32
-/* I/O space size (bits 26-24; 8 bytes = 011b) */
-#define ITE_887x_POSIO_IOSIZE_8                (3 << 24)
-/* I/O space size (bits 26-24; 32 bytes = 101b) */
-#define ITE_887x_POSIO_IOSIZE_32       (5 << 24)
-/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */
-#define ITE_887x_POSIO_SPEED           (3 << 29)
-/* enable IO_Space bit */
-#define ITE_887x_POSIO_ENABLE          (1 << 31)
-
-static int pci_ite887x_init(struct pci_dev *dev)
-{
-       /* inta_addr are the configuration addresses of the ITE */
-       static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
-                                                       0x200, 0x280, 0 };
-       int ret, i, type;
-       struct resource *iobase = NULL;
-       u32 miscr, uartbar, ioport;
-
-       /* search for the base-ioport */
-       i = 0;
-       while (inta_addr[i] && iobase == NULL) {
-               iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
-                                                               "ite887x");
-               if (iobase != NULL) {
-                       /* write POSIO0R - speed | size | ioport */
-                       pci_write_config_dword(dev, ITE_887x_POSIO0,
-                               ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
-                               ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]);
-                       /* write INTCBAR - ioport */
-                       pci_write_config_dword(dev, ITE_887x_INTCBAR,
-                                                               inta_addr[i]);
-                       ret = inb(inta_addr[i]);
-                       if (ret != 0xff) {
-                               /* ioport connected */
-                               break;
-                       }
-                       release_region(iobase->start, ITE_887x_IOSIZE);
-                       iobase = NULL;
-               }
-               i++;
-       }
-
-       if (!inta_addr[i]) {
-               printk(KERN_ERR "ite887x: could not find iobase\n");
-               return -ENODEV;
-       }
-
-       /* start of undocumented type checking (see parport_pc.c) */
-       type = inb(iobase->start + 0x18) & 0x0f;
-
-       switch (type) {
-       case 0x2:       /* ITE8871 (1P) */
-       case 0xa:       /* ITE8875 (1P) */
-               ret = 0;
-               break;
-       case 0xe:       /* ITE8872 (2S1P) */
-               ret = 2;
-               break;
-       case 0x6:       /* ITE8873 (1S) */
-               ret = 1;
-               break;
-       case 0x8:       /* ITE8874 (2S) */
-               ret = 2;
-               break;
-       default:
-               moan_device("Unknown ITE887x", dev);
-               ret = -ENODEV;
-       }
-
-       /* configure all serial ports */
-       for (i = 0; i < ret; i++) {
-               /* read the I/O port from the device */
-               pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),
-                                                               &ioport);
-               ioport &= 0x0000FF00;   /* the actual base address */
-               pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),
-                       ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
-                       ITE_887x_POSIO_IOSIZE_8 | ioport);
-
-               /* write the ioport to the UARTBAR */
-               pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);
-               uartbar &= ~(0xffff << (16 * i));       /* clear half the reg */
-               uartbar |= (ioport << (16 * i));        /* set the ioport */
-               pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);
-
-               /* get current config */
-               pci_read_config_dword(dev, ITE_887x_MISCR, &miscr);
-               /* disable interrupts (UARTx_Routing[3:0]) */
-               miscr &= ~(0xf << (12 - 4 * i));
-               /* activate the UART (UARTx_En) */
-               miscr |= 1 << (23 - i);
-               /* write new config with activated UART */
-               pci_write_config_dword(dev, ITE_887x_MISCR, miscr);
-       }
-
-       if (ret <= 0) {
-               /* the device has no UARTs if we get here */
-               release_region(iobase->start, ITE_887x_IOSIZE);
-       }
-
-       return ret;
-}
-
-static void __devexit pci_ite887x_exit(struct pci_dev *dev)
-{
-       u32 ioport;
-       /* the ioport is bit 0-15 in POSIO0R */
-       pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
-       ioport &= 0xffff;
-       release_region(ioport, ITE_887x_IOSIZE);
-}
-
-/*
- * Oxford Semiconductor Inc.
- * Check that device is part of the Tornado range of devices, then determine
- * the number of ports available on the device.
- */
-static int pci_oxsemi_tornado_init(struct pci_dev *dev)
-{
-       u8 __iomem *p;
-       unsigned long deviceID;
-       unsigned int  number_uarts = 0;
-
-       /* OxSemi Tornado devices are all 0xCxxx */
-       if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
-           (dev->device & 0xF000) != 0xC000)
-               return 0;
-
-       p = pci_iomap(dev, 0, 5);
-       if (p == NULL)
-               return -ENOMEM;
-
-       deviceID = ioread32(p);
-       /* Tornado device */
-       if (deviceID == 0x07000200) {
-               number_uarts = ioread8(p + 4);
-               printk(KERN_DEBUG
-                       "%d ports detected on Oxford PCI Express device\n",
-                                                               number_uarts);
-       }
-       pci_iounmap(dev, p);
-       return number_uarts;
-}
-
-static int
-pci_default_setup(struct serial_private *priv,
-                 const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
-{
-       unsigned int bar, offset = board->first_offset, maxnr;
-
-       bar = FL_GET_BASE(board->flags);
-       if (board->flags & FL_BASE_BARS)
-               bar += idx;
-       else
-               offset += idx * board->uart_offset;
-
-       maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
-               (board->reg_shift + 3);
-
-       if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
-               return 1;
-
-       return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int
-ce4100_serial_setup(struct serial_private *priv,
-                 const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
-{
-       int ret;
-
-       ret = setup_port(priv, port, 0, 0, board->reg_shift);
-       port->iotype = UPIO_MEM32;
-       port->type = PORT_XSCALE;
-       port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
-       port->regshift = 2;
-
-       return ret;
-}
-
-static int
-pci_omegapci_setup(struct serial_private *priv,
-                     const struct pciserial_board *board,
-                     struct uart_port *port, int idx)
-{
-       return setup_port(priv, port, 2, idx * 8, 0);
-}
-
-static int skip_tx_en_setup(struct serial_private *priv,
-                       const struct pciserial_board *board,
-                       struct uart_port *port, int idx)
-{
-       port->flags |= UPF_NO_TXEN_TEST;
-       printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
-                         "[%04x:%04x] subsystem [%04x:%04x]\n",
-                         priv->dev->vendor,
-                         priv->dev->device,
-                         priv->dev->subsystem_vendor,
-                         priv->dev->subsystem_device);
-
-       return pci_default_setup(priv, board, port, idx);
-}
-
-static int kt_serial_setup(struct serial_private *priv,
-                          const struct pciserial_board *board,
-                          struct uart_port *port, int idx)
-{
-       port->flags |= UPF_IIR_ONCE;
-       return skip_tx_en_setup(priv, board, port, idx);
-}
-
-static int pci_eg20t_init(struct pci_dev *dev)
-{
-#if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE)
-       return -ENODEV;
-#else
-       return 0;
-#endif
-}
-
-static int
-pci_xr17c154_setup(struct serial_private *priv,
-                 const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
-{
-       port->flags |= UPF_EXAR_EFR;
-       return pci_default_setup(priv, board, port, idx);
-}
-
-static int try_enable_msi(struct pci_dev *dev)
-{
-       /* use msi if available, but fallback to legacy otherwise */
-       pci_enable_msi(dev);
-       return 0;
-}
-
-static void disable_msi(struct pci_dev *dev)
-{
-       pci_disable_msi(dev);
-}
-
-#define PCI_VENDOR_ID_SBSMODULARIO     0x124B
-#define PCI_SUBVENDOR_ID_SBSMODULARIO  0x124B
-#define PCI_DEVICE_ID_OCTPRO           0x0001
-#define PCI_SUBDEVICE_ID_OCTPRO232     0x0108
-#define PCI_SUBDEVICE_ID_OCTPRO422     0x0208
-#define PCI_SUBDEVICE_ID_POCTAL232     0x0308
-#define PCI_SUBDEVICE_ID_POCTAL422     0x0408
-#define PCI_VENDOR_ID_ADVANTECH                0x13fe
-#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
-#define PCI_DEVICE_ID_ADVANTECH_PCI3620        0x3620
-#define PCI_DEVICE_ID_TITAN_200I       0x8028
-#define PCI_DEVICE_ID_TITAN_400I       0x8048
-#define PCI_DEVICE_ID_TITAN_800I       0x8088
-#define PCI_DEVICE_ID_TITAN_800EH      0xA007
-#define PCI_DEVICE_ID_TITAN_800EHB     0xA008
-#define PCI_DEVICE_ID_TITAN_400EH      0xA009
-#define PCI_DEVICE_ID_TITAN_100E       0xA010
-#define PCI_DEVICE_ID_TITAN_200E       0xA012
-#define PCI_DEVICE_ID_TITAN_400E       0xA013
-#define PCI_DEVICE_ID_TITAN_800E       0xA014
-#define PCI_DEVICE_ID_TITAN_200EI      0xA016
-#define PCI_DEVICE_ID_TITAN_200EISI    0xA017
-#define PCI_DEVICE_ID_TITAN_400V3      0xA310
-#define PCI_DEVICE_ID_TITAN_410V3      0xA312
-#define PCI_DEVICE_ID_TITAN_800V3      0xA314
-#define PCI_DEVICE_ID_TITAN_800V3B     0xA315
-#define PCI_DEVICE_ID_OXSEMI_16PCI958  0x9538
-#define PCIE_DEVICE_ID_NEO_2_OX_IBM    0x00F6
-#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
-#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
-
-/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
-#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
-
-/*
- * Master list of serial port init/setup/exit quirks.
- * This does not describe the general nature of the port.
- * (ie, baud base, number and location of ports, etc)
- *
- * This list is ordered alphabetically by vendor then device.
- * Specific entries must come before more generic entries.
- */
-static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
-       /*
-       * ADDI-DATA GmbH communication cards <info@addi-data.com>
-       */
-       {
-               .vendor         = PCI_VENDOR_ID_ADDIDATA_OLD,
-               .device         = PCI_DEVICE_ID_ADDIDATA_APCI7800,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = addidata_apci7800_setup,
-       },
-       /*
-        * AFAVLAB cards - these may be called via parport_serial
-        *  It is not clear whether this applies to all products.
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_AFAVLAB,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = afavlab_setup,
-       },
-       /*
-        * HP Diva
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_HP,
-               .device         = PCI_DEVICE_ID_HP_DIVA,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_hp_diva_init,
-               .setup          = pci_hp_diva_setup,
-       },
-       /*
-        * Intel
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_80960_RP,
-               .subvendor      = 0xe4bf,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_inteli960ni_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_8257X_SOL,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = skip_tx_en_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_82573L_SOL,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = skip_tx_en_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_82573E_SOL,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = skip_tx_en_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_CE4100_UART,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = ce4100_serial_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = try_enable_msi,
-               .setup          = kt_serial_setup,
-               .exit           = disable_msi,
-       },
-       /*
-        * ITE
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_ITE,
-               .device         = PCI_DEVICE_ID_ITE_8872,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ite887x_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ite887x_exit),
-       },
-       /*
-        * National Instruments
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PCI23216,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PCI2328,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PCI2324,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PCI2322,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PCI2324I,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PCI2322I,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PXI8420_23216,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PXI8420_2328,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PXI8420_2324,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PXI8420_2322,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PXI8422_2324,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_DEVICE_ID_NI_PXI8422_2322,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8420_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_ni8420_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_NI,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_ni8430_init,
-               .setup          = pci_ni8430_setup,
-               .exit           = __devexit_p(pci_ni8430_exit),
-       },
-       /*
-        * Panacom
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_PANACOM,
-               .device         = PCI_DEVICE_ID_PANACOM_QUADMODEM,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_plx9050_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_PANACOM,
-               .device         = PCI_DEVICE_ID_PANACOM_DUALMODEM,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_plx9050_exit),
-       },
-       /*
-        * PLX
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9030,
-               .subvendor      = PCI_SUBVENDOR_ID_PERLE,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9050,
-               .subvendor      = PCI_SUBVENDOR_ID_EXSYS,
-               .subdevice      = PCI_SUBDEVICE_ID_EXSYS_4055,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_plx9050_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9050,
-               .subvendor      = PCI_SUBVENDOR_ID_KEYSPAN,
-               .subdevice      = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_plx9050_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9050,
-               .subvendor      = PCI_VENDOR_ID_PLX,
-               .subdevice      = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_plx9050_exit),
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_ROMULUS,
-               .subvendor      = PCI_VENDOR_ID_PLX,
-               .subdevice      = PCI_DEVICE_ID_PLX_ROMULUS,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = __devexit_p(pci_plx9050_exit),
-       },
-       /*
-        * SBS Technologies, Inc., PMC-OCTALPRO 232
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
-               .device         = PCI_DEVICE_ID_OCTPRO,
-               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
-               .subdevice      = PCI_SUBDEVICE_ID_OCTPRO232,
-               .init           = sbs_init,
-               .setup          = sbs_setup,
-               .exit           = __devexit_p(sbs_exit),
-       },
-       /*
-        * SBS Technologies, Inc., PMC-OCTALPRO 422
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
-               .device         = PCI_DEVICE_ID_OCTPRO,
-               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
-               .subdevice      = PCI_SUBDEVICE_ID_OCTPRO422,
-               .init           = sbs_init,
-               .setup          = sbs_setup,
-               .exit           = __devexit_p(sbs_exit),
-       },
-       /*
-        * SBS Technologies, Inc., P-Octal 232
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
-               .device         = PCI_DEVICE_ID_OCTPRO,
-               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
-               .subdevice      = PCI_SUBDEVICE_ID_POCTAL232,
-               .init           = sbs_init,
-               .setup          = sbs_setup,
-               .exit           = __devexit_p(sbs_exit),
-       },
-       /*
-        * SBS Technologies, Inc., P-Octal 422
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_SBSMODULARIO,
-               .device         = PCI_DEVICE_ID_OCTPRO,
-               .subvendor      = PCI_SUBVENDOR_ID_SBSMODULARIO,
-               .subdevice      = PCI_SUBDEVICE_ID_POCTAL422,
-               .init           = sbs_init,
-               .setup          = sbs_setup,
-               .exit           = __devexit_p(sbs_exit),
-       },
-       /*
-        * SIIG cards - these may be called via parport_serial
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig_init,
-               .setup          = pci_siig_setup,
-       },
-       /*
-        * Titan cards
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_TITAN,
-               .device         = PCI_DEVICE_ID_TITAN_400L,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = titan_400l_800l_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_TITAN,
-               .device         = PCI_DEVICE_ID_TITAN_800L,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = titan_400l_800l_setup,
-       },
-       /*
-        * Timedia cards
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_TIMEDIA,
-               .device         = PCI_DEVICE_ID_TIMEDIA_1889,
-               .subvendor      = PCI_VENDOR_ID_TIMEDIA,
-               .subdevice      = PCI_ANY_ID,
-               .probe          = pci_timedia_probe,
-               .init           = pci_timedia_init,
-               .setup          = pci_timedia_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_TIMEDIA,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_timedia_setup,
-       },
-       /*
-        * Exar cards
-        */
-       {
-               .vendor = PCI_VENDOR_ID_EXAR,
-               .device = PCI_DEVICE_ID_EXAR_XR17C152,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_xr17c154_setup,
-       },
-       {
-               .vendor = PCI_VENDOR_ID_EXAR,
-               .device = PCI_DEVICE_ID_EXAR_XR17C154,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_xr17c154_setup,
-       },
-       {
-               .vendor = PCI_VENDOR_ID_EXAR,
-               .device = PCI_DEVICE_ID_EXAR_XR17C158,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_xr17c154_setup,
-       },
-       /*
-        * Xircom cards
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_XIRCOM,
-               .device         = PCI_DEVICE_ID_XIRCOM_X3201_MDM,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_xircom_init,
-               .setup          = pci_default_setup,
-       },
-       /*
-        * Netmos cards - these may be called via parport_serial
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_NETMOS,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_netmos_init,
-               .setup          = pci_netmos_9900_setup,
-       },
-       /*
-        * For Oxford Semiconductor Tornado based devices
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_OXSEMI,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_oxsemi_tornado_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_MAINPINE,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_oxsemi_tornado_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_DIGI,
-               .device         = PCIE_DEVICE_ID_NEO_2_OX_IBM,
-               .subvendor              = PCI_SUBVENDOR_ID_IBM,
-               .subdevice              = PCI_ANY_ID,
-               .init                   = pci_oxsemi_tornado_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = 0x8811,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = 0x8812,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = 0x8813,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = 0x8814,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = 0x10DB,
-               .device         = 0x8027,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = 0x10DB,
-               .device         = 0x8028,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = 0x10DB,
-               .device         = 0x8029,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = 0x10DB,
-               .device         = 0x800C,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = 0x10DB,
-               .device         = 0x800D,
-               .init           = pci_eg20t_init,
-               .setup          = pci_default_setup,
-       },
-       /*
-        * Cronyx Omega PCI (PLX-chip based)
-        */
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_omegapci_setup,
-        },
-       /*
-        * Default "match everything" terminator entry
-        */
-       {
-               .vendor         = PCI_ANY_ID,
-               .device         = PCI_ANY_ID,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_default_setup,
-       }
-};
-
-static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
-{
-       return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
-}
-
-static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
-{
-       struct pci_serial_quirk *quirk;
-
-       for (quirk = pci_serial_quirks; ; quirk++)
-               if (quirk_id_matches(quirk->vendor, dev->vendor) &&
-                   quirk_id_matches(quirk->device, dev->device) &&
-                   quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
-                   quirk_id_matches(quirk->subdevice, dev->subsystem_device))
-                       break;
-       return quirk;
-}
-
-static inline int get_pci_irq(struct pci_dev *dev,
-                               const struct pciserial_board *board)
-{
-       if (board->flags & FL_NOIRQ)
-               return 0;
-       else
-               return dev->irq;
-}
-
-/*
- * This is the configuration table for all of the PCI serial boards
- * which we support.  It is directly indexed by the pci_board_num_t enum
- * value, which is encoded in the pci_device_id PCI probe table's
- * driver_data member.
- *
- * The makeup of these names are:
- *  pbn_bn{_bt}_n_baud{_offsetinhex}
- *
- *  bn         = PCI BAR number
- *  bt         = Index using PCI BARs
- *  n          = number of serial ports
- *  baud       = baud rate
- *  offsetinhex        = offset for each sequential port (in hex)
- *
- * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
- *
- * Please note: in theory if n = 1, _bt infix should make no difference.
- * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
- */
-enum pci_board_num_t {
-       pbn_default = 0,
-
-       pbn_b0_1_115200,
-       pbn_b0_2_115200,
-       pbn_b0_4_115200,
-       pbn_b0_5_115200,
-       pbn_b0_8_115200,
-
-       pbn_b0_1_921600,
-       pbn_b0_2_921600,
-       pbn_b0_4_921600,
-
-       pbn_b0_2_1130000,
-
-       pbn_b0_4_1152000,
-
-       pbn_b0_2_1843200,
-       pbn_b0_4_1843200,
-
-       pbn_b0_2_1843200_200,
-       pbn_b0_4_1843200_200,
-       pbn_b0_8_1843200_200,
-
-       pbn_b0_1_4000000,
-
-       pbn_b0_bt_1_115200,
-       pbn_b0_bt_2_115200,
-       pbn_b0_bt_4_115200,
-       pbn_b0_bt_8_115200,
-
-       pbn_b0_bt_1_460800,
-       pbn_b0_bt_2_460800,
-       pbn_b0_bt_4_460800,
-
-       pbn_b0_bt_1_921600,
-       pbn_b0_bt_2_921600,
-       pbn_b0_bt_4_921600,
-       pbn_b0_bt_8_921600,
-
-       pbn_b1_1_115200,
-       pbn_b1_2_115200,
-       pbn_b1_4_115200,
-       pbn_b1_8_115200,
-       pbn_b1_16_115200,
-
-       pbn_b1_1_921600,
-       pbn_b1_2_921600,
-       pbn_b1_4_921600,
-       pbn_b1_8_921600,
-
-       pbn_b1_2_1250000,
-
-       pbn_b1_bt_1_115200,
-       pbn_b1_bt_2_115200,
-       pbn_b1_bt_4_115200,
-
-       pbn_b1_bt_2_921600,
-
-       pbn_b1_1_1382400,
-       pbn_b1_2_1382400,
-       pbn_b1_4_1382400,
-       pbn_b1_8_1382400,
-
-       pbn_b2_1_115200,
-       pbn_b2_2_115200,
-       pbn_b2_4_115200,
-       pbn_b2_8_115200,
-
-       pbn_b2_1_460800,
-       pbn_b2_4_460800,
-       pbn_b2_8_460800,
-       pbn_b2_16_460800,
-
-       pbn_b2_1_921600,
-       pbn_b2_4_921600,
-       pbn_b2_8_921600,
-
-       pbn_b2_8_1152000,
-
-       pbn_b2_bt_1_115200,
-       pbn_b2_bt_2_115200,
-       pbn_b2_bt_4_115200,
-
-       pbn_b2_bt_2_921600,
-       pbn_b2_bt_4_921600,
-
-       pbn_b3_2_115200,
-       pbn_b3_4_115200,
-       pbn_b3_8_115200,
-
-       pbn_b4_bt_2_921600,
-       pbn_b4_bt_4_921600,
-       pbn_b4_bt_8_921600,
-
-       /*
-        * Board-specific versions.
-        */
-       pbn_panacom,
-       pbn_panacom2,
-       pbn_panacom4,
-       pbn_exsys_4055,
-       pbn_plx_romulus,
-       pbn_oxsemi,
-       pbn_oxsemi_1_4000000,
-       pbn_oxsemi_2_4000000,
-       pbn_oxsemi_4_4000000,
-       pbn_oxsemi_8_4000000,
-       pbn_intel_i960,
-       pbn_sgi_ioc3,
-       pbn_computone_4,
-       pbn_computone_6,
-       pbn_computone_8,
-       pbn_sbsxrsio,
-       pbn_exar_XR17C152,
-       pbn_exar_XR17C154,
-       pbn_exar_XR17C158,
-       pbn_exar_ibm_saturn,
-       pbn_pasemi_1682M,
-       pbn_ni8430_2,
-       pbn_ni8430_4,
-       pbn_ni8430_8,
-       pbn_ni8430_16,
-       pbn_ADDIDATA_PCIe_1_3906250,
-       pbn_ADDIDATA_PCIe_2_3906250,
-       pbn_ADDIDATA_PCIe_4_3906250,
-       pbn_ADDIDATA_PCIe_8_3906250,
-       pbn_ce4100_1_115200,
-       pbn_omegapci,
-       pbn_NETMOS9900_2s_115200,
-};
-
-/*
- * uart_offset - the space between channels
- * reg_shift   - describes how the UART registers are mapped
- *               to PCI memory by the card.
- * For example IER register on SBS, Inc. PMC-OctPro is located at
- * offset 0x10 from the UART base, while UART_IER is defined as 1
- * in include/linux/serial_reg.h,
- * see first lines of serial_in() and serial_out() in 8250.c
-*/
-
-static struct pciserial_board pci_boards[] __devinitdata = {
-       [pbn_default] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_1_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_2_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_4_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_5_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 5,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_8_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_1_921600] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_2_921600] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_4_921600] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_2_1130000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 1130000,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_4_1152000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 1152000,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_2_1843200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 1843200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_4_1843200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 1843200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_2_1843200_200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 1843200,
-               .uart_offset    = 0x200,
-       },
-       [pbn_b0_4_1843200_200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 1843200,
-               .uart_offset    = 0x200,
-       },
-       [pbn_b0_8_1843200_200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 1843200,
-               .uart_offset    = 0x200,
-       },
-       [pbn_b0_1_4000000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 4000000,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_bt_1_115200] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_2_115200] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_4_115200] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_8_115200] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 8,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_bt_1_460800] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 1,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_2_460800] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_4_460800] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b0_bt_1_921600] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 1,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_2_921600] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_4_921600] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b0_bt_8_921600] = {
-               .flags          = FL_BASE0|FL_BASE_BARS,
-               .num_ports      = 8,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b1_1_115200] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_2_115200] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_4_115200] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_8_115200] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 8,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_16_115200] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 16,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b1_1_921600] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 1,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_2_921600] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_4_921600] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_8_921600] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 8,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_2_1250000] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 2,
-               .base_baud      = 1250000,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b1_bt_1_115200] = {
-               .flags          = FL_BASE1|FL_BASE_BARS,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_bt_2_115200] = {
-               .flags          = FL_BASE1|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_bt_4_115200] = {
-               .flags          = FL_BASE1|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b1_bt_2_921600] = {
-               .flags          = FL_BASE1|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b1_1_1382400] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 1,
-               .base_baud      = 1382400,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_2_1382400] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 2,
-               .base_baud      = 1382400,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_4_1382400] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 4,
-               .base_baud      = 1382400,
-               .uart_offset    = 8,
-       },
-       [pbn_b1_8_1382400] = {
-               .flags          = FL_BASE1,
-               .num_ports      = 8,
-               .base_baud      = 1382400,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b2_1_115200] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_2_115200] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_4_115200] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_8_115200] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 8,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b2_1_460800] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 1,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_4_460800] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 4,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_8_460800] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 8,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_16_460800] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 16,
-               .base_baud      = 460800,
-               .uart_offset    = 8,
-        },
-
-       [pbn_b2_1_921600] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 1,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_4_921600] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_8_921600] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 8,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b2_8_1152000] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 8,
-               .base_baud      = 1152000,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b2_bt_1_115200] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 1,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_bt_2_115200] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_bt_4_115200] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b2_bt_2_921600] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b2_bt_4_921600] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b3_2_115200] = {
-               .flags          = FL_BASE3,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b3_4_115200] = {
-               .flags          = FL_BASE3,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_b3_8_115200] = {
-               .flags          = FL_BASE3,
-               .num_ports      = 8,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       [pbn_b4_bt_2_921600] = {
-               .flags          = FL_BASE4,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b4_bt_4_921600] = {
-               .flags          = FL_BASE4,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-       [pbn_b4_bt_8_921600] = {
-               .flags          = FL_BASE4,
-               .num_ports      = 8,
-               .base_baud      = 921600,
-               .uart_offset    = 8,
-       },
-
-       /*
-        * Entries following this are board-specific.
-        */
-
-       /*
-        * Panacom - IOMEM
-        */
-       [pbn_panacom] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 0x400,
-               .reg_shift      = 7,
-       },
-       [pbn_panacom2] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 0x400,
-               .reg_shift      = 7,
-       },
-       [pbn_panacom4] = {
-               .flags          = FL_BASE2|FL_BASE_BARS,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 0x400,
-               .reg_shift      = 7,
-       },
-
-       [pbn_exsys_4055] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
-       /* I think this entry is broken - the first_offset looks wrong --rmk */
-       [pbn_plx_romulus] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 8 << 2,
-               .reg_shift      = 2,
-               .first_offset   = 0x03,
-       },
-
-       /*
-        * This board uses the size of PCI Base region 0 to
-        * signal now many ports are available
-        */
-       [pbn_oxsemi] = {
-               .flags          = FL_BASE0|FL_REGION_SZ_CAP,
-               .num_ports      = 32,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-       [pbn_oxsemi_1_4000000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 4000000,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_oxsemi_2_4000000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 4000000,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_oxsemi_4_4000000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 4000000,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_oxsemi_8_4000000] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 4000000,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-
-
-       /*
-        * EKF addition for i960 Boards form EKF with serial port.
-        * Max 256 ports.
-        */
-       [pbn_intel_i960] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 32,
-               .base_baud      = 921600,
-               .uart_offset    = 8 << 2,
-               .reg_shift      = 2,
-               .first_offset   = 0x10000,
-       },
-       [pbn_sgi_ioc3] = {
-               .flags          = FL_BASE0|FL_NOIRQ,
-               .num_ports      = 1,
-               .base_baud      = 458333,
-               .uart_offset    = 8,
-               .reg_shift      = 0,
-               .first_offset   = 0x20178,
-       },
-
-       /*
-        * Computone - uses IOMEM.
-        */
-       [pbn_computone_4] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 0x40,
-               .reg_shift      = 2,
-               .first_offset   = 0x200,
-       },
-       [pbn_computone_6] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 6,
-               .base_baud      = 921600,
-               .uart_offset    = 0x40,
-               .reg_shift      = 2,
-               .first_offset   = 0x200,
-       },
-       [pbn_computone_8] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 921600,
-               .uart_offset    = 0x40,
-               .reg_shift      = 2,
-               .first_offset   = 0x200,
-       },
-       [pbn_sbsxrsio] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 460800,
-               .uart_offset    = 256,
-               .reg_shift      = 4,
-       },
-       /*
-        * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
-        *  Only basic 16550A support.
-        *  XR17C15[24] are not tested, but they should work.
-        */
-       [pbn_exar_XR17C152] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 921600,
-               .uart_offset    = 0x200,
-       },
-       [pbn_exar_XR17C154] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 921600,
-               .uart_offset    = 0x200,
-       },
-       [pbn_exar_XR17C158] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 921600,
-               .uart_offset    = 0x200,
-       },
-       [pbn_exar_ibm_saturn] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 921600,
-               .uart_offset    = 0x200,
-       },
-
-       /*
-        * PA Semi PWRficient PA6T-1682M on-chip UART
-        */
-       [pbn_pasemi_1682M] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 8333333,
-       },
-       /*
-        * National Instruments 843x
-        */
-       [pbn_ni8430_16] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 16,
-               .base_baud      = 3686400,
-               .uart_offset    = 0x10,
-               .first_offset   = 0x800,
-       },
-       [pbn_ni8430_8] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 3686400,
-               .uart_offset    = 0x10,
-               .first_offset   = 0x800,
-       },
-       [pbn_ni8430_4] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 3686400,
-               .uart_offset    = 0x10,
-               .first_offset   = 0x800,
-       },
-       [pbn_ni8430_2] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 3686400,
-               .uart_offset    = 0x10,
-               .first_offset   = 0x800,
-       },
-       /*
-        * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
-        */
-       [pbn_ADDIDATA_PCIe_1_3906250] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 3906250,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_ADDIDATA_PCIe_2_3906250] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 3906250,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_ADDIDATA_PCIe_4_3906250] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 4,
-               .base_baud      = 3906250,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_ADDIDATA_PCIe_8_3906250] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 3906250,
-               .uart_offset    = 0x200,
-               .first_offset   = 0x1000,
-       },
-       [pbn_ce4100_1_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
-               .base_baud      = 921600,
-               .reg_shift      = 2,
-       },
-       [pbn_omegapci] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 8,
-               .base_baud      = 115200,
-               .uart_offset    = 0x200,
-       },
-       [pbn_NETMOS9900_2s_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 2,
-               .base_baud      = 115200,
-       },
-};
-
-static const struct pci_device_id softmodem_blacklist[] = {
-       { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
-       { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
-       { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
-};
-
-/*
- * Given a complete unknown PCI device, try to use some heuristics to
- * guess what the configuration might be, based on the pitiful PCI
- * serial specs.  Returns 0 on success, 1 on failure.
- */
-static int __devinit
-serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
-{
-       const struct pci_device_id *blacklist;
-       int num_iomem, num_port, first_port = -1, i;
-
-       /*
-        * If it is not a communications device or the programming
-        * interface is greater than 6, give up.
-        *
-        * (Should we try to make guesses for multiport serial devices
-        * later?)
-        */
-       if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
-            ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
-           (dev->class & 0xff) > 6)
-               return -ENODEV;
-
-       /*
-        * Do not access blacklisted devices that are known not to
-        * feature serial ports.
-        */
-       for (blacklist = softmodem_blacklist;
-            blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
-            blacklist++) {
-               if (dev->vendor == blacklist->vendor &&
-                   dev->device == blacklist->device)
-                       return -ENODEV;
-       }
-
-       num_iomem = num_port = 0;
-       for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
-               if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
-                       num_port++;
-                       if (first_port == -1)
-                               first_port = i;
-               }
-               if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
-                       num_iomem++;
-       }
-
-       /*
-        * If there is 1 or 0 iomem regions, and exactly one port,
-        * use it.  We guess the number of ports based on the IO
-        * region size.
-        */
-       if (num_iomem <= 1 && num_port == 1) {
-               board->flags = first_port;
-               board->num_ports = pci_resource_len(dev, first_port) / 8;
-               return 0;
-       }
-
-       /*
-        * Now guess if we've got a board which indexes by BARs.
-        * Each IO BAR should be 8 bytes, and they should follow
-        * consecutively.
-        */
-       first_port = -1;
-       num_port = 0;
-       for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
-               if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
-                   pci_resource_len(dev, i) == 8 &&
-                   (first_port == -1 || (first_port + num_port) == i)) {
-                       num_port++;
-                       if (first_port == -1)
-                               first_port = i;
-               }
-       }
-
-       if (num_port > 1) {
-               board->flags = first_port | FL_BASE_BARS;
-               board->num_ports = num_port;
-               return 0;
-       }
-
-       return -ENODEV;
-}
-
-static inline int
-serial_pci_matches(const struct pciserial_board *board,
-                  const struct pciserial_board *guessed)
-{
-       return
-           board->num_ports == guessed->num_ports &&
-           board->base_baud == guessed->base_baud &&
-           board->uart_offset == guessed->uart_offset &&
-           board->reg_shift == guessed->reg_shift &&
-           board->first_offset == guessed->first_offset;
-}
-
-struct serial_private *
-pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
-{
-       struct uart_port serial_port;
-       struct serial_private *priv;
-       struct pci_serial_quirk *quirk;
-       int rc, nr_ports, i;
-
-       nr_ports = board->num_ports;
-
-       /*
-        * Find an init and setup quirks.
-        */
-       quirk = find_quirk(dev);
-
-       /*
-        * Run the new-style initialization function.
-        * The initialization function returns:
-        *  <0  - error
-        *   0  - use board->num_ports
-        *  >0  - number of ports
-        */
-       if (quirk->init) {
-               rc = quirk->init(dev);
-               if (rc < 0) {
-                       priv = ERR_PTR(rc);
-                       goto err_out;
-               }
-               if (rc)
-                       nr_ports = rc;
-       }
-
-       priv = kzalloc(sizeof(struct serial_private) +
-                      sizeof(unsigned int) * nr_ports,
-                      GFP_KERNEL);
-       if (!priv) {
-               priv = ERR_PTR(-ENOMEM);
-               goto err_deinit;
-       }
-
-       priv->dev = dev;
-       priv->quirk = quirk;
-
-       memset(&serial_port, 0, sizeof(struct uart_port));
-       serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
-       serial_port.uartclk = board->base_baud * 16;
-       serial_port.irq = get_pci_irq(dev, board);
-       serial_port.dev = &dev->dev;
-
-       for (i = 0; i < nr_ports; i++) {
-               if (quirk->setup(priv, board, &serial_port, i))
-                       break;
-
-#ifdef SERIAL_DEBUG_PCI
-               printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
-                      serial_port.iobase, serial_port.irq, serial_port.iotype);
-#endif
-
-               priv->line[i] = serial8250_register_port(&serial_port);
-               if (priv->line[i] < 0) {
-                       printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
-                       break;
-               }
-       }
-       priv->nr = i;
-       return priv;
-
-err_deinit:
-       if (quirk->exit)
-               quirk->exit(dev);
-err_out:
-       return priv;
-}
-EXPORT_SYMBOL_GPL(pciserial_init_ports);
-
-void pciserial_remove_ports(struct serial_private *priv)
-{
-       struct pci_serial_quirk *quirk;
-       int i;
-
-       for (i = 0; i < priv->nr; i++)
-               serial8250_unregister_port(priv->line[i]);
-
-       for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
-               if (priv->remapped_bar[i])
-                       iounmap(priv->remapped_bar[i]);
-               priv->remapped_bar[i] = NULL;
-       }
-
-       /*
-        * Find the exit quirks.
-        */
-       quirk = find_quirk(priv->dev);
-       if (quirk->exit)
-               quirk->exit(priv->dev);
-
-       kfree(priv);
-}
-EXPORT_SYMBOL_GPL(pciserial_remove_ports);
-
-void pciserial_suspend_ports(struct serial_private *priv)
-{
-       int i;
-
-       for (i = 0; i < priv->nr; i++)
-               if (priv->line[i] >= 0)
-                       serial8250_suspend_port(priv->line[i]);
-}
-EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
-
-void pciserial_resume_ports(struct serial_private *priv)
-{
-       int i;
-
-       /*
-        * Ensure that the board is correctly configured.
-        */
-       if (priv->quirk->init)
-               priv->quirk->init(priv->dev);
-
-       for (i = 0; i < priv->nr; i++)
-               if (priv->line[i] >= 0)
-                       serial8250_resume_port(priv->line[i]);
-}
-EXPORT_SYMBOL_GPL(pciserial_resume_ports);
-
-/*
- * Probe one serial board.  Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-       struct pci_serial_quirk *quirk;
-       struct serial_private *priv;
-       const struct pciserial_board *board;
-       struct pciserial_board tmp;
-       int rc;
-
-       quirk = find_quirk(dev);
-       if (quirk->probe) {
-               rc = quirk->probe(dev);
-               if (rc)
-                       return rc;
-       }
-
-       if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
-               printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
-                       ent->driver_data);
-               return -EINVAL;
-       }
-
-       board = &pci_boards[ent->driver_data];
-
-       rc = pci_enable_device(dev);
-       pci_save_state(dev);
-       if (rc)
-               return rc;
-
-       if (ent->driver_data == pbn_default) {
-               /*
-                * Use a copy of the pci_board entry for this;
-                * avoid changing entries in the table.
-                */
-               memcpy(&tmp, board, sizeof(struct pciserial_board));
-               board = &tmp;
-
-               /*
-                * We matched one of our class entries.  Try to
-                * determine the parameters of this board.
-                */
-               rc = serial_pci_guess_board(dev, &tmp);
-               if (rc)
-                       goto disable;
-       } else {
-               /*
-                * We matched an explicit entry.  If we are able to
-                * detect this boards settings with our heuristic,
-                * then we no longer need this entry.
-                */
-               memcpy(&tmp, &pci_boards[pbn_default],
-                      sizeof(struct pciserial_board));
-               rc = serial_pci_guess_board(dev, &tmp);
-               if (rc == 0 && serial_pci_matches(board, &tmp))
-                       moan_device("Redundant entry in serial pci_table.",
-                                   dev);
-       }
-
-       priv = pciserial_init_ports(dev, board);
-       if (!IS_ERR(priv)) {
-               pci_set_drvdata(dev, priv);
-               return 0;
-       }
-
-       rc = PTR_ERR(priv);
-
- disable:
-       pci_disable_device(dev);
-       return rc;
-}
-
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
-{
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       pci_set_drvdata(dev, NULL);
-
-       pciserial_remove_ports(priv);
-
-       pci_disable_device(dev);
-}
-
-#ifdef CONFIG_PM
-static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
-{
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       if (priv)
-               pciserial_suspend_ports(priv);
-
-       pci_save_state(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
-       return 0;
-}
-
-static int pciserial_resume_one(struct pci_dev *dev)
-{
-       int err;
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       pci_set_power_state(dev, PCI_D0);
-       pci_restore_state(dev);
-
-       if (priv) {
-               /*
-                * The device may have been disabled.  Re-enable it.
-                */
-               err = pci_enable_device(dev);
-               /* FIXME: We cannot simply error out here */
-               if (err)
-                       printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
-               pciserial_resume_ports(priv);
-       }
-       return 0;
-}
-#endif
-
-static struct pci_device_id serial_pci_tbl[] = {
-       /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
-       {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
-               PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
-               pbn_b2_8_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
-               pbn_b1_8_1382400 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
-               pbn_b1_4_1382400 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
-               pbn_b1_2_1382400 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
-               pbn_b1_8_1382400 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
-               pbn_b1_4_1382400 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
-               pbn_b1_2_1382400 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
-               pbn_b1_8_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
-               pbn_b1_8_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
-               pbn_b1_4_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
-               pbn_b1_4_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
-               pbn_b1_2_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
-               pbn_b1_8_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
-               pbn_b1_8_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
-               pbn_b1_4_921600 },
-       {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
-               pbn_b1_2_1250000 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
-               pbn_b0_2_1843200 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
-               pbn_b0_4_1843200 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-               PCI_VENDOR_ID_AFAVLAB,
-               PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
-               pbn_b0_4_1152000 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
-               pbn_b0_2_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
-               pbn_b0_4_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
-               pbn_b0_8_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
-               pbn_b0_2_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
-               pbn_b0_4_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
-               pbn_b0_8_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
-               pbn_b0_2_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
-               pbn_b0_4_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
-               pbn_b0_8_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
-               pbn_b0_2_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
-               pbn_b0_4_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-               PCI_SUBVENDOR_ID_CONNECT_TECH,
-               PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
-               pbn_b0_8_1843200_200 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-               PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
-               0, 0, pbn_exar_ibm_saturn },
-
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_1_115200 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_115200 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_4_115200 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_115200 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_4_115200 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_8_115200 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_8_460800 },
-       {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_8_115200 },
-
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_115200 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_921600 },
-       /*
-        * VScom SPCOM800, from sl@s.pl
-        */
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_8_921600 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_4_921600 },
-       /* Unknown card - subdevice 0x1584 */
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_VENDOR_ID_PLX,
-               PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
-               pbn_b0_4_115200 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_KEYSPAN,
-               PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
-               pbn_panacom },
-       {       PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_panacom4 },
-       {       PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_panacom2 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
-               PCI_VENDOR_ID_ESDGMBH,
-               PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0,
-               pbn_b2_4_115200 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-               PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
-               pbn_b2_4_460800 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-               PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
-               pbn_b2_8_460800 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-               PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
-               pbn_b2_16_460800 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-               PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
-               pbn_b2_16_460800 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_CHASE_PCIRAS,
-               PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
-               pbn_b2_4_460800 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_CHASE_PCIRAS,
-               PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
-               pbn_b2_8_460800 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-               PCI_SUBVENDOR_ID_EXSYS,
-               PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
-               pbn_exsys_4055 },
-       /*
-        * Megawolf Romulus PCI Serial Card, from Mike Hudson
-        * (Exoray@isys.ca)
-        */
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
-               0x10b5, 0x106a, 0, 0,
-               pbn_plx_romulus },
-       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_4_115200 },
-       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_2_115200 },
-       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_8_115200 },
-       {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_8_115200 },
-       {       PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
-               PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
-               0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL,
-               0, 0,
-               pbn_b0_4_1152000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0x9505,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_921600 },
-
-               /*
-                * The below card is a little controversial since it is the
-                * subject of a PCI vendor/device ID clash.  (See
-                * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html).
-                * For now just used the hex ID 0x950a.
-                */
-       {       PCI_VENDOR_ID_OXSEMI, 0x950a,
-               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
-               pbn_b0_2_115200 },
-       {       PCI_VENDOR_ID_OXSEMI, 0x950a,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_2_1130000 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950,
-               PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0,
-               pbn_b0_1_921600 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_115200 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_921600 },
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
-               PCI_ANY_ID , PCI_ANY_ID, 0, 0,
-               pbn_b2_8_1152000 },
-
-       /*
-        * Oxford Semiconductor Inc. Tornado PCI express device range.
-        */
-       {       PCI_VENDOR_ID_OXSEMI, 0xc101,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc105,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc11b,    /* OXPCIe952 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc11f,    /* OXPCIe952 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc120,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc124,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc138,    /* OXPCIe952 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc13d,    /* OXPCIe952 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc140,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc141,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc144,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc145,    /* OXPCIe952 1 Legacy UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc158,    /* OXPCIe952 2 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_2_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc15d,    /* OXPCIe952 2 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_2_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc208,    /* OXPCIe954 4 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_4_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc20d,    /* OXPCIe954 4 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_4_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc308,    /* OXPCIe958 8 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_8_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc30d,    /* OXPCIe958 8 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_8_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc40b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc40f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc41b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc41f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc42b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc42f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc43b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc43f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc44b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc44f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc45b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc45f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc46b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc46f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc47b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc47f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc48b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc48f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc49b,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc49f,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc4ab,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc4af,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc4bb,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc4bf,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc4cb,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_OXSEMI, 0xc4cf,    /* OXPCIe200 1 Native UART */
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       /*
-        * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
-        */
-       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
-               PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
-               PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
-               pbn_oxsemi_2_4000000 },
-       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
-               PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
-               pbn_oxsemi_4_4000000 },
-       {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
-               PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
-               pbn_oxsemi_8_4000000 },
-
-       /*
-        * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
-        */
-       {       PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
-               PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_2_4000000 },
-
-       /*
-        * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
-        * from skokodyn@yahoo.com
-        */
-       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
-               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0,
-               pbn_sbsxrsio },
-       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
-               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0,
-               pbn_sbsxrsio },
-       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
-               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0,
-               pbn_sbsxrsio },
-       {       PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
-               PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0,
-               pbn_sbsxrsio },
-
-       /*
-        * Digitan DS560-558, from jimd@esoft.com
-        */
-       {       PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_1_115200 },
-
-       /*
-        * Titan Electronic cards
-        *  The 400L and 800L have a custom setup quirk.
-        */
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_2_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_1_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_2_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_8_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b4_bt_2_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b4_bt_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b4_bt_8_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_1_4000000 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_2_4000000 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_4_4000000 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_8_4000000 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_2_4000000 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi_2_4000000 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_410V3,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_4_921600 },
-
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_1_460800 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_1_460800 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_1_460800 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_4_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_4_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_4_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_4_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_4_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_4_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_8_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_8_921600 },
-       {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_8_921600 },
-
-       /*
-        * Computone devices submitted by Doug McNash dmcnash@computone.com
-        */
-       {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-               PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
-               0, 0, pbn_computone_4 },
-       {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-               PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
-               0, 0, pbn_computone_8 },
-       {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-               PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
-               0, 0, pbn_computone_6 },
-
-       {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_oxsemi },
-       {       PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
-               PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_1_921600 },
-
-       /*
-        * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
-        */
-       {       PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_8_115200 },
-       {       PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_8_115200 },
-
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_4_460800 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_4_460800 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_460800 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_460800 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_460800 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_1_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_1_460800 },
-
-       /*
-        * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
-        * Cards are identified by their subsystem vendor IDs, which
-        * (in hex) match the model number.
-        *
-        * Note that JC140x are RS422/485 cards which require ox950
-        * ACR = 0x10, and as such are not currently fully supported.
-        */
-       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
-               0x1204, 0x0004, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
-               0x1208, 0x0004, 0, 0,
-               pbn_b0_4_921600 },
-/*     {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
-               0x1402, 0x0002, 0, 0,
-               pbn_b0_2_921600 }, */
-/*     {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
-               0x1404, 0x0004, 0, 0,
-               pbn_b0_4_921600 }, */
-       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
-               0x1208, 0x0004, 0, 0,
-               pbn_b0_4_921600 },
-
-       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
-               0x1204, 0x0004, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
-               0x1208, 0x0004, 0, 0,
-               pbn_b0_4_921600 },
-       {       PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
-               0x1208, 0x0004, 0, 0,
-               pbn_b0_4_921600 },
-       /*
-        * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
-        */
-       {       PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_1_1382400 },
-
-       /*
-        * Dell Remote Access Card III - Tim_T_Murphy@Dell.com
-        */
-       {       PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_1_1382400 },
-
-       /*
-        * RAStel 2 port modem, gerg@moreton.com.au
-        */
-       {       PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_bt_2_115200 },
-
-       /*
-        * EKF addition for i960 Boards form EKF with serial port
-        */
-       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
-               0xE4BF, PCI_ANY_ID, 0, 0,
-               pbn_intel_i960 },
-
-       /*
-        * Xircom Cardbus/Ethernet combos
-        */
-       {       PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_115200 },
-       /*
-        * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
-        */
-       {       PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_115200 },
-
-       /*
-        * Untested PCI modems, sent in from various folks...
-        */
-
-       /*
-        * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
-        */
-       {       PCI_VENDOR_ID_ROCKWELL, 0x1004,
-               0x1048, 0x1500, 0, 0,
-               pbn_b1_1_115200 },
-
-       {       PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
-               0xFF00, 0, 0, 0,
-               pbn_sgi_ioc3 },
-
-       /*
-        * HP Diva card
-        */
-       {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
-               PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0,
-               pbn_b1_1_115200 },
-       {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_5_115200 },
-       {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b2_1_115200 },
-
-       {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b3_2_115200 },
-       {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b3_4_115200 },
-       {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b3_8_115200 },
-
-       /*
-        * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
-        */
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
-               PCI_ANY_ID, PCI_ANY_ID,
-               0,
-               0, pbn_exar_XR17C152 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
-               PCI_ANY_ID, PCI_ANY_ID,
-               0,
-               0, pbn_exar_XR17C154 },
-       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
-               PCI_ANY_ID, PCI_ANY_ID,
-               0,
-               0, pbn_exar_XR17C158 },
-
-       /*
-        * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
-        */
-       {       PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_1_115200 },
-       /*
-        * ITE
-        */
-       {       PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
-               PCI_ANY_ID, PCI_ANY_ID,
-               0, 0,
-               pbn_b1_bt_1_115200 },
-
-       /*
-        * IntaShield IS-200
-        */
-       {       PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,   /* 135a.0811 */
-               pbn_b2_2_115200 },
-       /*
-        * IntaShield IS-400
-        */
-       {       PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,    /* 135a.0dc0 */
-               pbn_b2_4_115200 },
-       /*
-        * Perle PCI-RAS cards
-        */
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
-               PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
-               0, 0, pbn_b2_4_921600 },
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
-               PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
-               0, 0, pbn_b2_8_921600 },
-
-       /*
-        * Mainpine series cards: Fairly standard layout but fools
-        * parts of the autodetect in some cases and uses otherwise
-        * unmatched communications subclasses in the PCI Express case
-        */
-
-       {       /* RockForceDUO */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0200,
-               0, 0, pbn_b0_2_115200 },
-       {       /* RockForceQUATRO */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0300,
-               0, 0, pbn_b0_4_115200 },
-       {       /* RockForceDUO+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0400,
-               0, 0, pbn_b0_2_115200 },
-       {       /* RockForceQUATRO+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0500,
-               0, 0, pbn_b0_4_115200 },
-       {       /* RockForce+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0600,
-               0, 0, pbn_b0_2_115200 },
-       {       /* RockForce+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0700,
-               0, 0, pbn_b0_4_115200 },
-       {       /* RockForceOCTO+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0800,
-               0, 0, pbn_b0_8_115200 },
-       {       /* RockForceDUO+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0C00,
-               0, 0, pbn_b0_2_115200 },
-       {       /* RockForceQUARTRO+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x0D00,
-               0, 0, pbn_b0_4_115200 },
-       {       /* RockForceOCTO+ */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x1D00,
-               0, 0, pbn_b0_8_115200 },
-       {       /* RockForceD1 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2000,
-               0, 0, pbn_b0_1_115200 },
-       {       /* RockForceF1 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2100,
-               0, 0, pbn_b0_1_115200 },
-       {       /* RockForceD2 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2200,
-               0, 0, pbn_b0_2_115200 },
-       {       /* RockForceF2 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2300,
-               0, 0, pbn_b0_2_115200 },
-       {       /* RockForceD4 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2400,
-               0, 0, pbn_b0_4_115200 },
-       {       /* RockForceF4 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2500,
-               0, 0, pbn_b0_4_115200 },
-       {       /* RockForceD8 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2600,
-               0, 0, pbn_b0_8_115200 },
-       {       /* RockForceF8 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x2700,
-               0, 0, pbn_b0_8_115200 },
-       {       /* IQ Express D1 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3000,
-               0, 0, pbn_b0_1_115200 },
-       {       /* IQ Express F1 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3100,
-               0, 0, pbn_b0_1_115200 },
-       {       /* IQ Express D2 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3200,
-               0, 0, pbn_b0_2_115200 },
-       {       /* IQ Express F2 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3300,
-               0, 0, pbn_b0_2_115200 },
-       {       /* IQ Express D4 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3400,
-               0, 0, pbn_b0_4_115200 },
-       {       /* IQ Express F4 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3500,
-               0, 0, pbn_b0_4_115200 },
-       {       /* IQ Express D8 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3C00,
-               0, 0, pbn_b0_8_115200 },
-       {       /* IQ Express F8 */
-               PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
-               PCI_VENDOR_ID_MAINPINE, 0x3D00,
-               0, 0, pbn_b0_8_115200 },
-
-
-       /*
-        * PA Semi PA6T-1682M on-chip UART
-        */
-       {       PCI_VENDOR_ID_PASEMI, 0xa004,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_pasemi_1682M },
-
-       /*
-        * National Instruments
-        */
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI23216,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_16_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2328,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_8_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_4_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_2_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324I,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_4_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322I,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_2_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_23216,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_16_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2328,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_8_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_4_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_2_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_4_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b1_bt_2_115200 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_2 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_2 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_4 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_4 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2328,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_8 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2328,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_8 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_23216,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_16 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_23216,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_16 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_2 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2322,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_2 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_4 },
-       {       PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_ni8430_4 },
-
-       /*
-       * ADDI-DATA GmbH communication cards <info@addi-data.com>
-       */
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7500,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_4_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7420,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_2_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7300,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA_OLD,
-               PCI_DEVICE_ID_ADDIDATA_APCI7800,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b1_8_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7500_2,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_4_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7420_2,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_2_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7300_2,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7500_3,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_4_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7420_3,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_2_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7300_3,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCI7800_3,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_b0_8_115200 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCIe7500,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_ADDIDATA_PCIe_4_3906250 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCIe7420,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_ADDIDATA_PCIe_2_3906250 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCIe7300,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_ADDIDATA_PCIe_1_3906250 },
-
-       {       PCI_VENDOR_ID_ADDIDATA,
-               PCI_DEVICE_ID_ADDIDATA_APCIe7800,
-               PCI_ANY_ID,
-               PCI_ANY_ID,
-               0,
-               0,
-               pbn_ADDIDATA_PCIe_8_3906250 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
-               PCI_VENDOR_ID_IBM, 0x0299,
-               0, 0, pbn_b0_bt_2_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
-               0xA000, 0x1000,
-               0, 0, pbn_b0_1_115200 },
-
-       /* the 9901 is a rebranded 9912 */
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
-               0xA000, 0x1000,
-               0, 0, pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
-               0xA000, 0x1000,
-               0, 0, pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
-               0xA000, 0x1000,
-               0, 0, pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
-               0xA000, 0x1000,
-               0, 0, pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
-               0xA000, 0x3002,
-               0, 0, pbn_NETMOS9900_2s_115200 },
-
-       /*
-        * Best Connectivity and Rosewill PCI Multi I/O cards
-        */
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
-               0xA000, 0x1000,
-               0, 0, pbn_b0_1_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
-               0xA000, 0x3002,
-               0, 0, pbn_b0_bt_2_115200 },
-
-       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
-               0xA000, 0x3004,
-               0, 0, pbn_b0_bt_4_115200 },
-       /* Intel CE4100 */
-       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
-               PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
-               pbn_ce4100_1_115200 },
-
-       /*
-        * Cronyx Omega PCI
-        */
-       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_omegapci },
-
-       /*
-        * These entries match devices with class COMMUNICATION_SERIAL,
-        * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
-        */
-       {       PCI_ANY_ID, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_COMMUNICATION_SERIAL << 8,
-               0xffff00, pbn_default },
-       {       PCI_ANY_ID, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_COMMUNICATION_MODEM << 8,
-               0xffff00, pbn_default },
-       {       PCI_ANY_ID, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_COMMUNICATION_MULTISERIAL << 8,
-               0xffff00, pbn_default },
-       { 0, }
-};
-
-static pci_ers_result_t serial8250_io_error_detected(struct pci_dev *dev,
-                                               pci_channel_state_t state)
-{
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       if (state == pci_channel_io_perm_failure)
-               return PCI_ERS_RESULT_DISCONNECT;
-
-       if (priv)
-               pciserial_suspend_ports(priv);
-
-       pci_disable_device(dev);
-
-       return PCI_ERS_RESULT_NEED_RESET;
-}
-
-static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
-{
-       int rc;
-
-       rc = pci_enable_device(dev);
-
-       if (rc)
-               return PCI_ERS_RESULT_DISCONNECT;
-
-       pci_restore_state(dev);
-       pci_save_state(dev);
-
-       return PCI_ERS_RESULT_RECOVERED;
-}
-
-static void serial8250_io_resume(struct pci_dev *dev)
-{
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       if (priv)
-               pciserial_resume_ports(priv);
-}
-
-static struct pci_error_handlers serial8250_err_handler = {
-       .error_detected = serial8250_io_error_detected,
-       .slot_reset = serial8250_io_slot_reset,
-       .resume = serial8250_io_resume,
-};
-
-static struct pci_driver serial_pci_driver = {
-       .name           = "serial",
-       .probe          = pciserial_init_one,
-       .remove         = __devexit_p(pciserial_remove_one),
-#ifdef CONFIG_PM
-       .suspend        = pciserial_suspend_one,
-       .resume         = pciserial_resume_one,
-#endif
-       .id_table       = serial_pci_tbl,
-       .err_handler    = &serial8250_err_handler,
-};
-
-static int __init serial8250_pci_init(void)
-{
-       return pci_register_driver(&serial_pci_driver);
-}
-
-static void __exit serial8250_pci_exit(void)
-{
-       pci_unregister_driver(&serial_pci_driver);
-}
-
-module_init(serial8250_pci_init);
-module_exit(serial8250_pci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250_pnp.c
deleted file mode 100644 (file)
index a2f2365..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- *  Probe module for 8250/16550-type ISAPNP serial ports.
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- *  Ported to the Linux PnP Layer - (C) Adam Belay.
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pnp.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/serial_core.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-
-#include "8250.h"
-
-#define UNKNOWN_DEV 0x3000
-
-
-static const struct pnp_device_id pnp_dev_table[] = {
-       /* Archtek America Corp. */
-       /* Archtek SmartLink Modem 3334BT Plug & Play */
-       {       "AAC000F",              0       },
-       /* Anchor Datacomm BV */
-       /* SXPro 144 External Data Fax Modem Plug & Play */
-       {       "ADC0001",              0       },
-       /* SXPro 288 External Data Fax Modem Plug & Play */
-       {       "ADC0002",              0       },
-       /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
-       {       "AEI0250",              0       },
-       /* Actiontec ISA PNP 56K X2 Fax Modem */
-       {       "AEI1240",              0       },
-       /* Rockwell 56K ACF II Fax+Data+Voice Modem */
-       {       "AKY1021",              0 /*SPCI_FL_NO_SHIRQ*/  },
-       /* AZT3005 PnP SOUND DEVICE */
-       {       "AZT4001",              0       },
-       /* Best Data Products Inc. Smart One 336F PnP Modem */
-       {       "BDP3336",              0       },
-       /*  Boca Research */
-       /* Boca Complete Ofc Communicator 14.4 Data-FAX */
-       {       "BRI0A49",              0       },
-       /* Boca Research 33,600 ACF Modem */
-       {       "BRI1400",              0       },
-       /* Boca 33.6 Kbps Internal FD34FSVD */
-       {       "BRI3400",              0       },
-       /* Boca 33.6 Kbps Internal FD34FSVD */
-       {       "BRI0A49",              0       },
-       /* Best Data Products Inc. Smart One 336F PnP Modem */
-       {       "BDP3336",              0       },
-       /* Computer Peripherals Inc */
-       /* EuroViVa CommCenter-33.6 SP PnP */
-       {       "CPI4050",              0       },
-       /* Creative Labs */
-       /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
-       {       "CTL3001",              0       },
-       /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
-       {       "CTL3011",              0       },
-       /* Davicom ISA 33.6K Modem */
-       {       "DAV0336",              0       },
-       /* Creative */
-       /* Creative Modem Blaster Flash56 DI5601-1 */
-       {       "DMB1032",              0       },
-       /* Creative Modem Blaster V.90 DI5660 */
-       {       "DMB2001",              0       },
-       /* E-Tech */
-       /* E-Tech CyberBULLET PC56RVP */
-       {       "ETT0002",              0       },
-       /* FUJITSU */
-       /* Fujitsu 33600 PnP-I2 R Plug & Play */
-       {       "FUJ0202",              0       },
-       /* Fujitsu FMV-FX431 Plug & Play */
-       {       "FUJ0205",              0       },
-       /* Fujitsu 33600 PnP-I4 R Plug & Play */
-       {       "FUJ0206",              0       },
-       /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
-       {       "FUJ0209",              0       },
-       /* Archtek America Corp. */
-       /* Archtek SmartLink Modem 3334BT Plug & Play */
-       {       "GVC000F",              0       },
-       /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
-       {       "GVC0303",              0       },
-       /* Hayes */
-       /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
-       {       "HAY0001",              0       },
-       /* Hayes Optima 336 V.34 + FAX + Voice PnP */
-       {       "HAY000C",              0       },
-       /* Hayes Optima 336B V.34 + FAX + Voice PnP */
-       {       "HAY000D",              0       },
-       /* Hayes Accura 56K Ext Fax Modem PnP */
-       {       "HAY5670",              0       },
-       /* Hayes Accura 56K Ext Fax Modem PnP */
-       {       "HAY5674",              0       },
-       /* Hayes Accura 56K Fax Modem PnP */
-       {       "HAY5675",              0       },
-       /* Hayes 288, V.34 + FAX */
-       {       "HAYF000",              0       },
-       /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
-       {       "HAYF001",              0       },
-       /* IBM */
-       /* IBM Thinkpad 701 Internal Modem Voice */
-       {       "IBM0033",              0       },
-       /* Intermec */
-       /* Intermec CV60 touchscreen port */
-       {       "PNP4972",              0       },
-       /* Intertex */
-       /* Intertex 28k8 33k6 Voice EXT PnP */
-       {       "IXDC801",              0       },
-       /* Intertex 33k6 56k Voice EXT PnP */
-       {       "IXDC901",              0       },
-       /* Intertex 28k8 33k6 Voice SP EXT PnP */
-       {       "IXDD801",              0       },
-       /* Intertex 33k6 56k Voice SP EXT PnP */
-       {       "IXDD901",              0       },
-       /* Intertex 28k8 33k6 Voice SP INT PnP */
-       {       "IXDF401",              0       },
-       /* Intertex 28k8 33k6 Voice SP EXT PnP */
-       {       "IXDF801",              0       },
-       /* Intertex 33k6 56k Voice SP EXT PnP */
-       {       "IXDF901",              0       },
-       /* Kortex International */
-       /* KORTEX 28800 Externe PnP */
-       {       "KOR4522",              0       },
-       /* KXPro 33.6 Vocal ASVD PnP */
-       {       "KORF661",              0       },
-       /* Lasat */
-       /* LASAT Internet 33600 PnP */
-       {       "LAS4040",              0       },
-       /* Lasat Safire 560 PnP */
-       {       "LAS4540",              0       },
-       /* Lasat Safire 336  PnP */
-       {       "LAS5440",              0       },
-       /* Microcom, Inc. */
-       /* Microcom TravelPorte FAST V.34 Plug & Play */
-       {       "MNP0281",              0       },
-       /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
-       {       "MNP0336",              0       },
-       /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
-       {       "MNP0339",              0       },
-       /* Microcom DeskPorte 28.8P Plug & Play */
-       {       "MNP0342",              0       },
-       /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
-       {       "MNP0500",              0       },
-       /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
-       {       "MNP0501",              0       },
-       /* Microcom DeskPorte 28.8S Internal Plug & Play */
-       {       "MNP0502",              0       },
-       /* Motorola */
-       /* Motorola BitSURFR Plug & Play */
-       {       "MOT1105",              0       },
-       /* Motorola TA210 Plug & Play */
-       {       "MOT1111",              0       },
-       /* Motorola HMTA 200 (ISDN) Plug & Play */
-       {       "MOT1114",              0       },
-       /* Motorola BitSURFR Plug & Play */
-       {       "MOT1115",              0       },
-       /* Motorola Lifestyle 28.8 Internal */
-       {       "MOT1190",              0       },
-       /* Motorola V.3400 Plug & Play */
-       {       "MOT1501",              0       },
-       /* Motorola Lifestyle 28.8 V.34 Plug & Play */
-       {       "MOT1502",              0       },
-       /* Motorola Power 28.8 V.34 Plug & Play */
-       {       "MOT1505",              0       },
-       /* Motorola ModemSURFR External 28.8 Plug & Play */
-       {       "MOT1509",              0       },
-       /* Motorola Premier 33.6 Desktop Plug & Play */
-       {       "MOT150A",              0       },
-       /* Motorola VoiceSURFR 56K External PnP */
-       {       "MOT150F",              0       },
-       /* Motorola ModemSURFR 56K External PnP */
-       {       "MOT1510",              0       },
-       /* Motorola ModemSURFR 56K Internal PnP */
-       {       "MOT1550",              0       },
-       /* Motorola ModemSURFR Internal 28.8 Plug & Play */
-       {       "MOT1560",              0       },
-       /* Motorola Premier 33.6 Internal Plug & Play */
-       {       "MOT1580",              0       },
-       /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
-       {       "MOT15B0",              0       },
-       /* Motorola VoiceSURFR 56K Internal PnP */
-       {       "MOT15F0",              0       },
-       /* Com 1 */
-       /*  Deskline K56 Phone System PnP */
-       {       "MVX00A1",              0       },
-       /* PC Rider K56 Phone System PnP */
-       {       "MVX00F2",              0       },
-       /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
-       {       "nEC8241",              0       },
-       /* Pace 56 Voice Internal Plug & Play Modem */
-       {       "PMC2430",              0       },
-       /* Generic */
-       /* Generic standard PC COM port  */
-       {       "PNP0500",              0       },
-       /* Generic 16550A-compatible COM port */
-       {       "PNP0501",              0       },
-       /* Compaq 14400 Modem */
-       {       "PNPC000",              0       },
-       /* Compaq 2400/9600 Modem */
-       {       "PNPC001",              0       },
-       /* Dial-Up Networking Serial Cable between 2 PCs */
-       {       "PNPC031",              0       },
-       /* Dial-Up Networking Parallel Cable between 2 PCs */
-       {       "PNPC032",              0       },
-       /* Standard 9600 bps Modem */
-       {       "PNPC100",              0       },
-       /* Standard 14400 bps Modem */
-       {       "PNPC101",              0       },
-       /*  Standard 28800 bps Modem*/
-       {       "PNPC102",              0       },
-       /*  Standard Modem*/
-       {       "PNPC103",              0       },
-       /*  Standard 9600 bps Modem*/
-       {       "PNPC104",              0       },
-       /*  Standard 14400 bps Modem*/
-       {       "PNPC105",              0       },
-       /*  Standard 28800 bps Modem*/
-       {       "PNPC106",              0       },
-       /*  Standard Modem */
-       {       "PNPC107",              0       },
-       /* Standard 9600 bps Modem */
-       {       "PNPC108",              0       },
-       /* Standard 14400 bps Modem */
-       {       "PNPC109",              0       },
-       /* Standard 28800 bps Modem */
-       {       "PNPC10A",              0       },
-       /* Standard Modem */
-       {       "PNPC10B",              0       },
-       /* Standard 9600 bps Modem */
-       {       "PNPC10C",              0       },
-       /* Standard 14400 bps Modem */
-       {       "PNPC10D",              0       },
-       /* Standard 28800 bps Modem */
-       {       "PNPC10E",              0       },
-       /* Standard Modem */
-       {       "PNPC10F",              0       },
-       /* Standard PCMCIA Card Modem */
-       {       "PNP2000",              0       },
-       /* Rockwell */
-       /* Modular Technology */
-       /* Rockwell 33.6 DPF Internal PnP */
-       /* Modular Technology 33.6 Internal PnP */
-       {       "ROK0030",              0       },
-       /* Kortex International */
-       /* KORTEX 14400 Externe PnP */
-       {       "ROK0100",              0       },
-       /* Rockwell 28.8 */
-       {       "ROK4120",              0       },
-       /* Viking Components, Inc */
-       /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
-       {       "ROK4920",              0       },
-       /* Rockwell */
-       /* British Telecom */
-       /* Modular Technology */
-       /* Rockwell 33.6 DPF External PnP */
-       /* BT Prologue 33.6 External PnP */
-       /* Modular Technology 33.6 External PnP */
-       {       "RSS00A0",              0       },
-       /* Viking 56K FAX INT */
-       {       "RSS0262",              0       },
-       /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
-       {       "RSS0250",              0       },
-       /* SupraExpress 28.8 Data/Fax PnP modem */
-       {       "SUP1310",              0       },
-       /* SupraExpress 336i PnP Voice Modem */
-       {       "SUP1381",              0       },
-       /* SupraExpress 33.6 Data/Fax PnP modem */
-       {       "SUP1421",              0       },
-       /* SupraExpress 33.6 Data/Fax PnP modem */
-       {       "SUP1590",              0       },
-       /* SupraExpress 336i Sp ASVD */
-       {       "SUP1620",              0       },
-       /* SupraExpress 33.6 Data/Fax PnP modem */
-       {       "SUP1760",              0       },
-       /* SupraExpress 56i Sp Intl */
-       {       "SUP2171",              0       },
-       /* Phoebe Micro */
-       /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
-       {       "TEX0011",              0       },
-       /* Archtek America Corp. */
-       /* Archtek SmartLink Modem 3334BT Plug & Play */
-       {       "UAC000F",              0       },
-       /* 3Com Corp. */
-       /* Gateway Telepath IIvi 33.6 */
-       {       "USR0000",              0       },
-       /* U.S. Robotics Sporster 33.6K Fax INT PnP */
-       {       "USR0002",              0       },
-       /*  Sportster Vi 14.4 PnP FAX Voicemail */
-       {       "USR0004",              0       },
-       /* U.S. Robotics 33.6K Voice INT PnP */
-       {       "USR0006",              0       },
-       /* U.S. Robotics 33.6K Voice EXT PnP */
-       {       "USR0007",              0       },
-       /* U.S. Robotics Courier V.Everything INT PnP */
-       {       "USR0009",              0       },
-       /* U.S. Robotics 33.6K Voice INT PnP */
-       {       "USR2002",              0       },
-       /* U.S. Robotics 56K Voice INT PnP */
-       {       "USR2070",              0       },
-       /* U.S. Robotics 56K Voice EXT PnP */
-       {       "USR2080",              0       },
-       /* U.S. Robotics 56K FAX INT */
-       {       "USR3031",              0       },
-       /* U.S. Robotics 56K FAX INT */
-       {       "USR3050",              0       },
-       /* U.S. Robotics 56K Voice INT PnP */
-       {       "USR3070",              0       },
-       /* U.S. Robotics 56K Voice EXT PnP */
-       {       "USR3080",              0       },
-       /* U.S. Robotics 56K Voice INT PnP */
-       {       "USR3090",              0       },
-       /* U.S. Robotics 56K Message  */
-       {       "USR9100",              0       },
-       /* U.S. Robotics 56K FAX EXT PnP*/
-       {       "USR9160",              0       },
-       /* U.S. Robotics 56K FAX INT PnP*/
-       {       "USR9170",              0       },
-       /* U.S. Robotics 56K Voice EXT PnP*/
-       {       "USR9180",              0       },
-       /* U.S. Robotics 56K Voice INT PnP*/
-       {       "USR9190",              0       },
-       /* Wacom tablets */
-       {       "WACFXXX",              0       },
-       /* Compaq touchscreen */
-       {       "FPI2002",              0 },
-       /* Fujitsu Stylistic touchscreens */
-       {       "FUJ02B2",              0 },
-       {       "FUJ02B3",              0 },
-       /* Fujitsu Stylistic LT touchscreens */
-       {       "FUJ02B4",              0 },
-       /* Passive Fujitsu Stylistic touchscreens */
-       {       "FUJ02B6",              0 },
-       {       "FUJ02B7",              0 },
-       {       "FUJ02B8",              0 },
-       {       "FUJ02B9",              0 },
-       {       "FUJ02BC",              0 },
-       /* Fujitsu Wacom Tablet PC device */
-       {       "FUJ02E5",              0       },
-       /* Fujitsu P-series tablet PC device */
-       {       "FUJ02E6",              0       },
-       /* Fujitsu Wacom 2FGT Tablet PC device */
-       {       "FUJ02E7",              0       },
-       /* Fujitsu Wacom 1FGT Tablet PC device */
-       {       "FUJ02E9",              0       },
-       /*
-        * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
-        * disguise)
-        */
-       {       "LTS0001",              0       },
-       /* Rockwell's (PORALiNK) 33600 INT PNP */
-       {       "WCI0003",              0       },
-       /* Unknown PnP modems */
-       {       "PNPCXXX",              UNKNOWN_DEV     },
-       /* More unknown PnP modems */
-       {       "PNPDXXX",              UNKNOWN_DEV     },
-       {       "",                     0       }
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static char *modem_names[] __devinitdata = {
-       "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
-       "56K", "56k", "K56", "33.6", "28.8", "14.4",
-       "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
-       "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
-};
-
-static int __devinit check_name(char *name)
-{
-       char **tmp;
-
-       for (tmp = modem_names; *tmp; tmp++)
-               if (strstr(name, *tmp))
-                       return 1;
-
-       return 0;
-}
-
-static int __devinit check_resources(struct pnp_dev *dev)
-{
-       resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(base); i++) {
-               if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
-                       return 1;
-       }
-
-       return 0;
-}
-
-/*
- * Given a complete unknown PnP device, try to use some heuristics to
- * detect modems. Currently use such heuristic set:
- *     - dev->name or dev->bus->name must contain "modem" substring;
- *     - device must have only one IO region (8 byte long) with base address
- *       0x2e8, 0x3e8, 0x2f8 or 0x3f8.
- *
- * Such detection looks very ugly, but can detect at least some of numerous
- * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
- * table.
- */
-static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
-{
-       if (!(check_name(pnp_dev_name(dev)) ||
-               (dev->card && check_name(dev->card->name))))
-                       return -ENODEV;
-
-       if (check_resources(dev))
-               return 0;
-
-       return -ENODEV;
-}
-
-static int __devinit
-serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
-       struct uart_port port;
-       int ret, line, flags = dev_id->driver_data;
-
-       if (flags & UNKNOWN_DEV) {
-               ret = serial_pnp_guess_board(dev, &flags);
-               if (ret < 0)
-                       return ret;
-       }
-
-       memset(&port, 0, sizeof(struct uart_port));
-       if (pnp_irq_valid(dev, 0))
-               port.irq = pnp_irq(dev, 0);
-       if (pnp_port_valid(dev, 0)) {
-               port.iobase = pnp_port_start(dev, 0);
-               port.iotype = UPIO_PORT;
-       } else if (pnp_mem_valid(dev, 0)) {
-               port.mapbase = pnp_mem_start(dev, 0);
-               port.iotype = UPIO_MEM;
-               port.flags = UPF_IOREMAP;
-       } else
-               return -ENODEV;
-
-#ifdef SERIAL_DEBUG_PNP
-       printk(KERN_DEBUG
-               "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
-                      port.iobase, port.mapbase, port.irq, port.iotype);
-#endif
-
-       port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
-       if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
-               port.flags |= UPF_SHARE_IRQ;
-       port.uartclk = 1843200;
-       port.dev = &dev->dev;
-
-       line = serial8250_register_port(&port);
-       if (line < 0)
-               return -ENODEV;
-
-       pnp_set_drvdata(dev, (void *)((long)line + 1));
-       return 0;
-}
-
-static void __devexit serial_pnp_remove(struct pnp_dev *dev)
-{
-       long line = (long)pnp_get_drvdata(dev);
-       if (line)
-               serial8250_unregister_port(line - 1);
-}
-
-#ifdef CONFIG_PM
-static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
-{
-       long line = (long)pnp_get_drvdata(dev);
-
-       if (!line)
-               return -ENODEV;
-       serial8250_suspend_port(line - 1);
-       return 0;
-}
-
-static int serial_pnp_resume(struct pnp_dev *dev)
-{
-       long line = (long)pnp_get_drvdata(dev);
-
-       if (!line)
-               return -ENODEV;
-       serial8250_resume_port(line - 1);
-       return 0;
-}
-#else
-#define serial_pnp_suspend NULL
-#define serial_pnp_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pnp_driver serial_pnp_driver = {
-       .name           = "serial",
-       .probe          = serial_pnp_probe,
-       .remove         = __devexit_p(serial_pnp_remove),
-       .suspend        = serial_pnp_suspend,
-       .resume         = serial_pnp_resume,
-       .id_table       = pnp_dev_table,
-};
-
-static int __init serial8250_pnp_init(void)
-{
-       return pnp_register_driver(&serial_pnp_driver);
-}
-
-static void __exit serial8250_pnp_exit(void)
-{
-       pnp_unregister_driver(&serial_pnp_driver);
-}
-
-module_init(serial8250_pnp_init);
-module_exit(serial8250_pnp_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
index aca2386c5ef10261e74bfb66b2461546c8206150..2de99248dfaee06329f8a4f49505c9db66f7adf1 100644 (file)
@@ -5,279 +5,7 @@
 menu "Serial drivers"
        depends on HAS_IOMEM
 
-#
-# The new 8250/16550 serial drivers
-config SERIAL_8250
-       tristate "8250/16550 and compatible serial support"
-       select SERIAL_CORE
-       ---help---
-         This selects whether you want to include the driver for the standard
-         serial ports.  The standard answer is Y.  People who might say N
-         here are those that are setting up dedicated Ethernet WWW/FTP
-         servers, or users that have one of the various bus mice instead of a
-         serial mouse and don't intend to use their machine's standard serial
-         port for anything.  (Note that the Cyclades and Stallion multi
-         serial port drivers do not need this driver built in for them to
-         work.)
-
-         To compile this driver as a module, choose M here: the
-         module will be called 8250.
-         [WARNING: Do not compile this driver as a module if you are using
-         non-standard serial ports, since the configuration information will
-         be lost when the driver is unloaded.  This limitation may be lifted
-         in the future.]
-
-         BTW1: If you have a mouseman serial mouse which is not recognized by
-         the X window system, try running gpm first.
-
-         BTW2: If you intend to use a software modem (also called Winmodem)
-         under Linux, forget it.  These modems are crippled and require
-         proprietary drivers which are only available under Windows.
-
-         Most people will say Y or M here, so that they can use serial mice,
-         modems and similar devices connecting to the standard serial ports.
-
-config SERIAL_8250_CONSOLE
-       bool "Console on 8250/16550 and compatible serial port"
-       depends on SERIAL_8250=y
-       select SERIAL_CORE_CONSOLE
-       ---help---
-         If you say Y here, it will be possible to use a serial port as the
-         system console (the system console is the device which receives all
-         kernel messages and warnings and which allows logins in single user
-         mode). This could be useful if some terminal or printer is connected
-         to that serial port.
-
-         Even if you say Y here, the currently visible virtual console
-         (/dev/tty0) will still be used as the system console by default, but
-         you can alter that using a kernel command line option such as
-         "console=ttyS1". (Try "man bootparam" or see the documentation of
-         your boot loader (grub or lilo or loadlin) about how to pass options
-         to the kernel at boot time.)
-
-         If you don't have a VGA card installed and you say Y here, the
-         kernel will automatically use the first serial line, /dev/ttyS0, as
-         system console.
-
-         You can set that using a kernel command line option such as
-         "console=uart8250,io,0x3f8,9600n8"
-         "console=uart8250,mmio,0xff5e0000,115200n8".
-         and it will switch to normal serial console when the corresponding 
-         port is ready.
-         "earlycon=uart8250,io,0x3f8,9600n8"
-         "earlycon=uart8250,mmio,0xff5e0000,115200n8".
-         it will not only setup early console.
-
-         If unsure, say N.
-
-config FIX_EARLYCON_MEM
-       bool
-       depends on X86
-       default y
-
-config SERIAL_8250_GSC
-       tristate
-       depends on SERIAL_8250 && GSC
-       default SERIAL_8250
-
-config SERIAL_8250_PCI
-       tristate "8250/16550 PCI device support" if EXPERT
-       depends on SERIAL_8250 && PCI
-       default SERIAL_8250
-       help
-         This builds standard PCI serial support. You may be able to
-         disable this feature if you only need legacy serial support.
-         Saves about 9K.
-
-config SERIAL_8250_PNP
-       tristate "8250/16550 PNP device support" if EXPERT
-       depends on SERIAL_8250 && PNP
-       default SERIAL_8250
-       help
-         This builds standard PNP serial support. You may be able to
-         disable this feature if you only need legacy serial support.
-
-config SERIAL_8250_FSL
-       bool
-       depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
-       default PPC
-
-config SERIAL_8250_HP300
-       tristate
-       depends on SERIAL_8250 && HP300
-       default SERIAL_8250
-
-config SERIAL_8250_CS
-       tristate "8250/16550 PCMCIA device support"
-       depends on PCMCIA && SERIAL_8250
-       ---help---
-         Say Y here to enable support for 16-bit PCMCIA serial devices,
-         including serial port cards, modems, and the modem functions of
-         multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
-         credit-card size devices often used with laptops.)
-
-         To compile this driver as a module, choose M here: the
-         module will be called serial_cs.
-
-         If unsure, say N.
-
-config SERIAL_8250_NR_UARTS
-       int "Maximum number of 8250/16550 serial ports"
-       depends on SERIAL_8250
-       default "4"
-       help
-         Set this to the number of serial ports you want the driver
-         to support.  This includes any ports discovered via ACPI or
-         PCI enumeration and any ports that may be added at run-time
-         via hot-plug, or any ISA multi-port serial cards.
-
-config SERIAL_8250_RUNTIME_UARTS
-       int "Number of 8250/16550 serial ports to register at runtime"
-       depends on SERIAL_8250
-       range 0 SERIAL_8250_NR_UARTS
-       default "4"
-       help
-         Set this to the maximum number of serial ports you want
-         the kernel to register at boot time.  This can be overridden
-         with the module parameter "nr_uarts", or boot-time parameter
-         8250.nr_uarts
-
-config SERIAL_8250_EXTENDED
-       bool "Extended 8250/16550 serial driver options"
-       depends on SERIAL_8250
-       help
-         If you wish to use any non-standard features of the standard "dumb"
-         driver, say Y here. This includes HUB6 support, shared serial
-         interrupts, special multiport support, support for more than the
-         four COM 1/2/3/4 boards, etc.
-
-         Note that the answer to this question won't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about serial driver options. If unsure, say N.
-
-config SERIAL_8250_MANY_PORTS
-       bool "Support more than 4 legacy serial ports"
-       depends on SERIAL_8250_EXTENDED && !IA64
-       help
-         Say Y here if you have dumb serial boards other than the four
-         standard COM 1/2/3/4 ports. This may happen if you have an AST
-         FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
-         from <http://www.tldp.org/docs.html#howto>), or other custom
-         serial port hardware which acts similar to standard serial port
-         hardware. If you only use the standard COM 1/2/3/4 ports, you can
-         say N here to save some memory. You can also say Y if you have an
-         "intelligent" multiport card such as Cyclades, Digiboards, etc.
-
-#
-# Multi-port serial cards
-#
-
-config SERIAL_8250_FOURPORT
-       tristate "Support Fourport cards"
-       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
-       help
-         Say Y here if you have an AST FourPort serial board.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8250_fourport.
-
-config SERIAL_8250_ACCENT
-       tristate "Support Accent cards"
-       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
-       help
-         Say Y here if you have an Accent Async serial board.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8250_accent.
-
-config SERIAL_8250_BOCA
-       tristate "Support Boca cards"
-       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
-       help
-         Say Y here if you have a Boca serial board.  Please read the Boca
-         mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8250_boca.
-
-config SERIAL_8250_EXAR_ST16C554
-       tristate "Support Exar ST16C554/554D Quad UART"
-       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
-       help
-         The Uplogix Envoy TU301 uses this Exar Quad UART.  If you are
-         tinkering with your Envoy TU301, or have a machine with this UART,
-         say Y here.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8250_exar_st16c554.
-
-config SERIAL_8250_HUB6
-       tristate "Support Hub6 cards"
-       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
-       help
-         Say Y here if you have a HUB6 serial board.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8250_hub6.
-
-config SERIAL_8250_SHARE_IRQ
-       bool "Support for sharing serial interrupts"
-       depends on SERIAL_8250_EXTENDED
-       help
-         Some serial boards have hardware support which allows multiple dumb
-         serial ports on the same board to share a single IRQ. To enable
-         support for this in the serial driver, say Y here.
-
-config SERIAL_8250_DETECT_IRQ
-       bool "Autodetect IRQ on standard ports (unsafe)"
-       depends on SERIAL_8250_EXTENDED
-       help
-         Say Y here if you want the kernel to try to guess which IRQ
-         to use for your serial port.
-
-         This is considered unsafe; it is far better to configure the IRQ in
-         a boot script using the setserial command.
-
-         If unsure, say N.
-
-config SERIAL_8250_RSA
-       bool "Support RSA serial ports"
-       depends on SERIAL_8250_EXTENDED
-       help
-         ::: To be written :::
-
-config SERIAL_8250_MCA
-       tristate "Support 8250-type ports on MCA buses"
-       depends on SERIAL_8250 != n && MCA
-       help
-         Say Y here if you have a MCA serial ports.
-
-         To compile this driver as a module, choose M here: the module
-         will be called 8250_mca.
-
-config SERIAL_8250_ACORN
-       tristate "Acorn expansion card serial port support"
-       depends on ARCH_ACORN && SERIAL_8250
-       help
-         If you have an Atomwide Serial card or Serial Port card for an Acorn
-         system, say Y to this option.  The driver can handle 1, 2, or 3 port
-         cards.  If unsure, say N.
-
-config SERIAL_8250_RM9K
-       bool "Support for MIPS RM9xxx integrated serial port"
-       depends on SERIAL_8250 != n && SERIAL_RM9000
-       select SERIAL_8250_SHARE_IRQ
-       help
-         Selecting this option will add support for the integrated serial
-         port hardware found on MIPS RM9122 and similar processors.
-         If unsure, say N.
-
-config SERIAL_8250_DW
-       tristate "Support for Synopsys DesignWare 8250 quirks"
-       depends on SERIAL_8250 && OF
-       help
-         Selecting this option will enable handling of the extra features
-         present in the Synopsys DesignWare APB UART.
+source "drivers/tty/serial/8250/Kconfig"
 
 comment "Non-8250 serial port support"
 
@@ -536,15 +264,6 @@ config SERIAL_MAX3107
        help
          MAX3107 chip support
 
-config SERIAL_MAX3107_AAVA
-       tristate "MAX3107 AAVA platform support"
-       depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB
-       select SERIAL_CORE
-       help
-         Support for the MAX3107 chip configuration found on the AAVA
-         platform. Includes the extra initialisation and GPIO support
-         neded for this device.
-
 config SERIAL_DZ
        bool "DECstation DZ serial driver"
        depends on MACH_DECSTATION && 32BIT
index f5b01f2ce525da8df92d1972529fefb70c98ae23..fef32e10c8515a9de39ceab267f6647882c64197 100644 (file)
@@ -14,22 +14,9 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
 obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
 obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
 
-obj-$(CONFIG_SERIAL_8250) += 8250.o
-obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
-obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
-obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
-obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
-obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
-obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
-obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
-obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
-obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
-obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
-obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
-obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
-obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
-obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
-obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
+# Now bring in any enabled 8250/16450/16550 type drivers.
+obj-$(CONFIG_SERIAL_8250) += 8250/
+
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
@@ -42,7 +29,6 @@ obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
 obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
 obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
-obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
index 6958594f2fc09a4c35eb65ce6037f937b323251e..6800f5f26241430789a92efea30d58920dca9453 100644 (file)
@@ -159,6 +159,7 @@ struct uart_amba_port {
        unsigned int            fifosize;       /* vendor-specific */
        unsigned int            lcrh_tx;        /* vendor-specific */
        unsigned int            lcrh_rx;        /* vendor-specific */
+       unsigned int            old_cr;         /* state during shutdown */
        bool                    autorts;
        char                    type[12];
        bool                    interrupt_may_hang; /* vendor-specific */
@@ -268,7 +269,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
        struct dma_slave_config tx_conf = {
                .dst_addr = uap->port.mapbase + UART01x_DR,
                .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
-               .direction = DMA_TO_DEVICE,
+               .direction = DMA_MEM_TO_DEV,
                .dst_maxburst = uap->fifosize >> 1,
        };
        struct dma_chan *chan;
@@ -301,7 +302,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
                struct dma_slave_config rx_conf = {
                        .src_addr = uap->port.mapbase + UART01x_DR,
                        .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
-                       .direction = DMA_FROM_DEVICE,
+                       .direction = DMA_DEV_TO_MEM,
                        .src_maxburst = uap->fifosize >> 1,
                };
 
@@ -480,7 +481,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
                return -EBUSY;
        }
 
-       desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE,
+       desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV,
                                             DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
@@ -676,7 +677,7 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
                &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
        dma_dev = rxchan->device;
        desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1,
-                                       DMA_FROM_DEVICE,
+                                       DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        /*
         * If the DMA engine is busy and cannot prepare a
@@ -1411,7 +1412,9 @@ static int pl011_startup(struct uart_port *port)
        while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
                barrier();
 
-       cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
+       /* restore RTS and DTR */
+       cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
+       cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
        writew(cr, uap->port.membase + UART011_CR);
 
        /* Clear pending error interrupts */
@@ -1469,6 +1472,7 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
 static void pl011_shutdown(struct uart_port *port)
 {
        struct uart_amba_port *uap = (struct uart_amba_port *)port;
+       unsigned int cr;
 
        /*
         * disable all interrupts
@@ -1488,9 +1492,16 @@ static void pl011_shutdown(struct uart_port *port)
 
        /*
         * disable the port
+        * disable the port. It should not disable RTS and DTR.
+        * Also RTS and DTR state should be preserved to restore
+        * it during startup().
         */
        uap->autorts = false;
-       writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);
+       cr = readw(uap->port.membase + UART011_CR);
+       uap->old_cr = cr;
+       cr &= UART011_CR_RTS | UART011_CR_DTR;
+       cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
+       writew(cr, uap->port.membase + UART011_CR);
 
        /*
         * disable break condition and fifos
@@ -1740,9 +1751,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_amba_port *uap = amba_ports[co->index];
        unsigned int status, old_cr, new_cr;
+       unsigned long flags;
+       int locked = 1;
 
        clk_enable(uap->clk);
 
+       local_irq_save(flags);
+       if (uap->port.sysrq)
+               locked = 0;
+       else if (oops_in_progress)
+               locked = spin_trylock(&uap->port.lock);
+       else
+               spin_lock(&uap->port.lock);
+
        /*
         *      First save the CR then disable the interrupts
         */
@@ -1762,6 +1783,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
        } while (status & UART01x_FR_BUSY);
        writew(old_cr, uap->port.membase + UART011_CR);
 
+       if (locked)
+               spin_unlock(&uap->port.lock);
+       local_irq_restore(flags);
+
        clk_disable(uap->clk);
 }
 
@@ -1905,6 +1930,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        uap->vendor = vendor;
        uap->lcrh_rx = vendor->lcrh_rx;
        uap->lcrh_tx = vendor->lcrh_tx;
+       uap->old_cr = 0;
        uap->fifosize = vendor->fifosize;
        uap->interrupt_may_hang = vendor->interrupt_may_hang;
        uap->port.dev = &dev->dev;
index 7c867a046c9752214773ba5f2a1237893ed2ebfd..7545fe1b99257dad128f3ddd57356939ce8f8399 100644 (file)
@@ -251,6 +251,7 @@ static void jsm_io_resume(struct pci_dev *pdev)
        struct jsm_board *brd = pci_get_drvdata(pdev);
 
        pci_restore_state(pdev);
+       pci_save_state(pdev);
 
        jsm_uart_port_init(brd);
 }
diff --git a/drivers/tty/serial/max3107-aava.c b/drivers/tty/serial/max3107-aava.c
deleted file mode 100644 (file)
index aae772a..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *  max3107.c - spi uart protocol driver for Maxim 3107
- *  Based on max3100.c
- *     by Christian Pellegrin <chripell@evolware.org>
- *  and        max3110.c
- *     by Feng Tang <feng.tang@intel.com>
- *
- *  Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  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/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/sfi.h>
-#include <linux/module.h>
-#include <asm/mrst.h>
-#include "max3107.h"
-
-/* GPIO direction to input function */
-static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-       struct max3107_port *s = container_of(chip, struct max3107_port, chip);
-       u16 buf[1];             /* Buffer for SPI transfer */
-
-       if (offset >= MAX3107_GPIO_COUNT) {
-               dev_err(&s->spi->dev, "Invalid GPIO\n");
-               return -EINVAL;
-       }
-
-       /* Read current GPIO configuration register */
-       buf[0] = MAX3107_GPIOCFG_REG;
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
-               dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
-               return -EIO;
-       }
-       buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
-       /* Set GPIO to input */
-       buf[0] &= ~(0x0001 << offset);
-
-       /* Write new GPIO configuration register value */
-       buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
-               dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
-               return -EIO;
-       }
-       return 0;
-}
-
-/* GPIO direction to output function */
-static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
-                                       int value)
-{
-       struct max3107_port *s = container_of(chip, struct max3107_port, chip);
-       u16 buf[2];     /* Buffer for SPI transfers */
-
-       if (offset >= MAX3107_GPIO_COUNT) {
-               dev_err(&s->spi->dev, "Invalid GPIO\n");
-               return -EINVAL;
-       }
-
-       /* Read current GPIO configuration and data registers */
-       buf[0] = MAX3107_GPIOCFG_REG;
-       buf[1] = MAX3107_GPIODATA_REG;
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
-               dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
-               return -EIO;
-       }
-       buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-       buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
-       /* Set GPIO to output */
-       buf[0] |= (0x0001 << offset);
-       /* Set value */
-       if (value)
-               buf[1] |= (0x0001 << offset);
-       else
-               buf[1] &= ~(0x0001 << offset);
-
-       /* Write new GPIO configuration and data register values */
-       buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
-       buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
-               dev_err(&s->spi->dev,
-                       "SPI transfer for GPIO conf data w failed\n");
-               return -EIO;
-       }
-       return 0;
-}
-
-/* GPIO value query function */
-static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct max3107_port *s = container_of(chip, struct max3107_port, chip);
-       u16 buf[1];     /* Buffer for SPI transfer */
-
-       if (offset >= MAX3107_GPIO_COUNT) {
-               dev_err(&s->spi->dev, "Invalid GPIO\n");
-               return -EINVAL;
-       }
-
-       /* Read current GPIO data register */
-       buf[0] = MAX3107_GPIODATA_REG;
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
-               dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
-               return -EIO;
-       }
-       buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
-       /* Return value */
-       return buf[0] & (0x0001 << offset);
-}
-
-/* GPIO value set function */
-static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct max3107_port *s = container_of(chip, struct max3107_port, chip);
-       u16 buf[2];     /* Buffer for SPI transfers */
-
-       if (offset >= MAX3107_GPIO_COUNT) {
-               dev_err(&s->spi->dev, "Invalid GPIO\n");
-               return;
-       }
-
-       /* Read current GPIO configuration registers*/
-       buf[0] = MAX3107_GPIODATA_REG;
-       buf[1] = MAX3107_GPIOCFG_REG;
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
-               dev_err(&s->spi->dev,
-                       "SPI transfer for GPIO data and config read failed\n");
-               return;
-       }
-       buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-       buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
-       if (!(buf[1] & (0x0001 << offset))) {
-               /* Configured as input, can't set value */
-               dev_warn(&s->spi->dev,
-                               "Trying to set value for input GPIO\n");
-               return;
-       }
-
-       /* Set value */
-       if (value)
-               buf[0] |= (0x0001 << offset);
-       else
-               buf[0] &= ~(0x0001 << offset);
-
-       /* Write new GPIO data register value */
-       buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
-       /* Perform SPI transfer */
-       if (max3107_rw(s, (u8 *)buf, NULL, 2))
-               dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
-}
-
-/* GPIO chip data */
-static struct gpio_chip max3107_gpio_chip = {
-       .owner                  = THIS_MODULE,
-       .direction_input        = max3107_gpio_direction_in,
-       .direction_output       = max3107_gpio_direction_out,
-       .get                    = max3107_gpio_get,
-       .set                    = max3107_gpio_set,
-       .can_sleep              = 1,
-       .base                   = MAX3107_GPIO_BASE,
-       .ngpio                  = MAX3107_GPIO_COUNT,
-};
-
-/**
- *     max3107_aava_reset      -       reset on AAVA systems
- *     @spi: The SPI device we are probing
- *
- *     Reset the device ready for probing.
- */
-
-static int max3107_aava_reset(struct spi_device *spi)
-{
-       /* Reset the chip */
-       if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
-               pr_err("Requesting RESET GPIO failed\n");
-               return -EIO;
-       }
-       if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
-               pr_err("Setting RESET GPIO to 0 failed\n");
-               gpio_free(MAX3107_RESET_GPIO);
-               return -EIO;
-       }
-       msleep(MAX3107_RESET_DELAY);
-       if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
-               pr_err("Setting RESET GPIO to 1 failed\n");
-               gpio_free(MAX3107_RESET_GPIO);
-               return -EIO;
-       }
-       gpio_free(MAX3107_RESET_GPIO);
-       msleep(MAX3107_WAKEUP_DELAY);
-       return 0;
-}
-
-static int max3107_aava_configure(struct max3107_port *s)
-{
-       int retval;
-
-       /* Initialize GPIO chip data */
-       s->chip = max3107_gpio_chip;
-       s->chip.label = s->spi->modalias;
-       s->chip.dev = &s->spi->dev;
-
-       /* Add GPIO chip */
-       retval = gpiochip_add(&s->chip);
-       if (retval) {
-               dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
-               return retval;
-       }
-
-       /* Temporary fix for EV2 boot problems, set modem reset to 0 */
-       max3107_gpio_direction_out(&s->chip, 3, 0);
-       return 0;
-}
-
-#if 0
-/* This will get enabled once we have the board stuff merged for this
-   specific case */
-
-static const struct baud_table brg13_ext[] = {
-       { 300,    MAX3107_BRG13_B300 },
-       { 600,    MAX3107_BRG13_B600 },
-       { 1200,   MAX3107_BRG13_B1200 },
-       { 2400,   MAX3107_BRG13_B2400 },
-       { 4800,   MAX3107_BRG13_B4800 },
-       { 9600,   MAX3107_BRG13_B9600 },
-       { 19200,  MAX3107_BRG13_B19200 },
-       { 57600,  MAX3107_BRG13_B57600 },
-       { 115200, MAX3107_BRG13_B115200 },
-       { 230400, MAX3107_BRG13_B230400 },
-       { 460800, MAX3107_BRG13_B460800 },
-       { 921600, MAX3107_BRG13_B921600 },
-       { 0, 0 }
-};
-
-static void max3107_aava_init(struct max3107_port *s)
-{
-       /*override for AAVA SC specific*/
-       if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
-               if (get_koski_build_id() <= KOSKI_EV2)
-                       if (s->ext_clk) {
-                               s->brg_cfg = MAX3107_BRG13_B9600;
-                               s->baud_tbl = (struct baud_table *)brg13_ext;
-                       }
-       }
-}
-#endif
-
-static int __devexit max3107_aava_remove(struct spi_device *spi)
-{
-       struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
-       /* Remove GPIO chip */
-       if (gpiochip_remove(&s->chip))
-               dev_warn(&spi->dev, "Removing GPIO chip failed\n");
-
-       /* Then do the default remove */
-       return max3107_remove(spi);
-}
-
-/* Platform data */
-static struct max3107_plat aava_plat_data = {
-       .loopback               = 0,
-       .ext_clk                = 1,
-/*     .init                   = max3107_aava_init, */
-       .configure              = max3107_aava_configure,
-       .hw_suspend             = max3107_hw_susp,
-       .polled_mode            = 0,
-       .poll_time              = 0,
-};
-
-
-static int __devinit max3107_probe_aava(struct spi_device *spi)
-{
-       int err = max3107_aava_reset(spi);
-       if (err < 0)
-               return err;
-       return max3107_probe(spi, &aava_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
-       .driver = {
-               .name           = "aava-max3107",
-               .owner          = THIS_MODULE,
-       },
-       .probe          = max3107_probe_aava,
-       .remove         = __devexit_p(max3107_aava_remove),
-       .suspend        = max3107_suspend,
-       .resume         = max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
-       return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
-       spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("spi:aava-max3107");
-MODULE_LICENSE("GPL v2");
index d192dcbb82f5e464f9ab6beb8805a2dcd1c6733b..f80904145fd4e3f5faeaa6a8440f7f5596115fde 100644 (file)
 
 #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
 
+/* SCR register bitmasks */
+#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK              (1 << 7)
+
+/* FCR register bitmasks */
+#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT               6
+#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK                        (0x3 << 6)
+
 static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 
 /* Forward declaration of functions */
@@ -129,6 +136,7 @@ static void serial_omap_enable_ms(struct uart_port *port)
 static void serial_omap_stop_tx(struct uart_port *port)
 {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
+       struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
 
        if (up->use_dma &&
                up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
@@ -151,6 +159,9 @@ static void serial_omap_stop_tx(struct uart_port *port)
                serial_out(up, UART_IER, up->ier);
        }
 
+       if (!up->use_dma && pdata->set_forceidle)
+               pdata->set_forceidle(up->pdev);
+
        pm_runtime_mark_last_busy(&up->pdev->dev);
        pm_runtime_put_autosuspend(&up->pdev->dev);
 }
@@ -279,6 +290,7 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
 static void serial_omap_start_tx(struct uart_port *port)
 {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
+       struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
        struct circ_buf *xmit;
        unsigned int start;
        int ret = 0;
@@ -286,6 +298,8 @@ static void serial_omap_start_tx(struct uart_port *port)
        if (!up->use_dma) {
                pm_runtime_get_sync(&up->pdev->dev);
                serial_omap_enable_ier_thri(up);
+               if (pdata->set_noidle)
+                       pdata->set_noidle(up->pdev);
                pm_runtime_mark_last_busy(&up->pdev->dev);
                pm_runtime_put_autosuspend(&up->pdev->dev);
                return;
@@ -726,8 +740,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
        quot = serial_omap_get_divisor(port, baud);
 
        /* calculate wakeup latency constraint */
-       up->calc_latency = (1000000 * up->port.fifosize) /
-                               (1000 * baud / 8);
+       up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8);
        up->latency = up->calc_latency;
        schedule_work(&up->qos_work);
 
@@ -811,14 +824,21 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
        up->mcr = serial_in(up, UART_MCR);
        serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
        /* FIFO ENABLE, DMA MODE */
-       serial_out(up, UART_FCR, up->fcr);
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+       up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
 
        if (up->use_dma) {
                serial_out(up, UART_TI752_TLR, 0);
-               up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8);
+               up->scr |= UART_FCR_TRIGGER_4;
+       } else {
+               /* Set receive FIFO threshold to 1 byte */
+               up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
+               up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
        }
 
+       serial_out(up, UART_FCR, up->fcr);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
        serial_out(up, UART_OMAP_SCR, up->scr);
 
        serial_out(up, UART_EFR, up->efr);
@@ -1160,7 +1180,7 @@ static struct uart_driver serial_omap_reg = {
        .cons           = OMAP_CONSOLE,
 };
 
-#ifdef CONFIG_SUSPEND
+#ifdef CONFIG_PM_SLEEP
 static int serial_omap_suspend(struct device *dev)
 {
        struct uart_omap_port *up = dev_get_drvdata(dev);
@@ -1521,6 +1541,7 @@ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
        }
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static void serial_omap_restore_context(struct uart_omap_port *up)
 {
        if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
@@ -1550,7 +1571,6 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
                serial_out(up, UART_OMAP_MDR1, up->mdr1);
 }
 
-#ifdef CONFIG_PM_RUNTIME
 static int serial_omap_runtime_suspend(struct device *dev)
 {
        struct uart_omap_port *up = dev_get_drvdata(dev);
index de0f613ed6f56051df309abc3ad25ea804081006..17ae65762d1a465f83ae92d9e64128419c2e077c 100644 (file)
@@ -764,7 +764,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
        sg_dma_address(sg) = priv->rx_buf_dma;
 
        desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
-                       sg, 1, DMA_FROM_DEVICE,
+                       sg, 1, DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
        if (!desc)
@@ -923,7 +923,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
        }
 
        desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
-                                       priv->sg_tx_p, nent, DMA_TO_DEVICE,
+                                       priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
index f96f37b5fec624566a9fef34754140189c84964d..c55e5fb16fa326930fe75a3a16a23a0a0cd2eccf 100644 (file)
@@ -1593,7 +1593,8 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
 #define S5PV210_SERIAL_DRV_DATA        (kernel_ulong_t)NULL
 #endif
 
-#ifdef CONFIG_CPU_EXYNOS4210
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) || \
+       defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
 static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
        .info = &(struct s3c24xx_uart_info) {
                .name           = "Samsung Exynos4 UART",
index c7bf31a6a7e75f711b711cad125a1b874db2fa04..13056180adf5eff85b9af7a81d2cb12a93c5dae0 100644 (file)
@@ -2348,11 +2348,11 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
         */
        tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
        if (likely(!IS_ERR(tty_dev))) {
-               device_init_wakeup(tty_dev, 1);
-               device_set_wakeup_enable(tty_dev, 0);
-       } else
+               device_set_wakeup_capable(tty_dev, 1);
+       } else {
                printk(KERN_ERR "Cannot register tty device on line %d\n",
                       uport->line);
+       }
 
        /*
         * Ensure UPF_DEAD is not set.
diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/serial_cs.c
deleted file mode 100644 (file)
index 8609060..0000000
+++ /dev/null
@@ -1,870 +0,0 @@
-/*======================================================================
-
-    A driver for PCMCIA serial devices
-
-    serial_cs.c 1.134 2002/05/04 05:48:53
-
-    The contents of this file are subject to the Mozilla Public
-    License Version 1.1 (the "License"); you may not use this file
-    except in compliance with the License. You may obtain a copy of
-    the License at http://www.mozilla.org/MPL/
-
-    Software distributed under the License is distributed on an "AS
-    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-    implied. See the License for the specific language governing
-    rights and limitations under the License.
-
-    The initial developer of the original code is David A. Hinds
-    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
-    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
-
-    Alternatively, the contents of this file may be used under the
-    terms of the GNU General Public License version 2 (the "GPL"), in which
-    case the provisions of the GPL are applicable instead of the
-    above.  If you wish to allow the use of your version of this file
-    only under the terms of the GPL and not to allow others to use
-    your version of this file under the MPL, indicate your decision
-    by deleting the provisions above and replace them with the notice
-    and other provisions required by the GPL.  If you do not delete
-    the provisions above, a recipient may use your version of this
-    file under either the MPL or the GPL.
-    
-======================================================================*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include "8250.h"
-
-
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-/* Enable the speaker? */
-static int do_sound = 1;
-/* Skip strict UART tests? */
-static int buggy_uart;
-
-module_param(do_sound, int, 0444);
-module_param(buggy_uart, int, 0444);
-
-/*====================================================================*/
-
-/* Table of multi-port card ID's */
-
-struct serial_quirk {
-       unsigned int manfid;
-       unsigned int prodid;
-       int multi;              /* 1 = multifunction, > 1 = # ports */
-       void (*config)(struct pcmcia_device *);
-       void (*setup)(struct pcmcia_device *, struct uart_port *);
-       void (*wakeup)(struct pcmcia_device *);
-       int (*post)(struct pcmcia_device *);
-};
-
-struct serial_info {
-       struct pcmcia_device    *p_dev;
-       int                     ndev;
-       int                     multi;
-       int                     slave;
-       int                     manfid;
-       int                     prodid;
-       int                     c950ctrl;
-       int                     line[4];
-       const struct serial_quirk *quirk;
-};
-
-struct serial_cfg_mem {
-       tuple_t tuple;
-       cisparse_t parse;
-       u_char buf[256];
-};
-
-/*
- * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6"
- * manfid 0x0160, 0x0104
- * This card appears to have a 14.7456MHz clock.
- */
-/* Generic Modem: MD55x (GPRS/EDGE) have
- * Elan VPU16551 UART with 14.7456MHz oscillator
- * manfid 0x015D, 0x4C45
- */
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
-{
-       port->uartclk = 14745600;
-}
-
-static int quirk_post_ibm(struct pcmcia_device *link)
-{
-       u8 val;
-       int ret;
-
-       ret = pcmcia_read_config_byte(link, 0x800, &val);
-       if (ret)
-               goto failed;
-
-       ret = pcmcia_write_config_byte(link, 0x800, val | 1);
-       if (ret)
-               goto failed;
-       return 0;
-
- failed:
-       return -ENODEV;
-}
-
-/*
- * Nokia cards are not really multiport cards.  Shouldn't this
- * be handled by setting the quirk entry .multi = 0 | 1 ?
- */
-static void quirk_config_nokia(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-
-       if (info->multi > 1)
-               info->multi = 1;
-}
-
-static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-
-       if (info->c950ctrl)
-               outb(12, info->c950ctrl + 1);
-}
-
-/* request_region? oxsemi branch does no request_region too... */
-/*
- * This sequence is needed to properly initialize MC45 attached to OXCF950.
- * I tried decreasing these msleep()s, but it worked properly (survived
- * 1000 stop/start operations) with these timeouts (or bigger).
- */
-static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-       unsigned int ctrl = info->c950ctrl;
-
-       outb(0xA, ctrl + 1);
-       msleep(100);
-       outb(0xE, ctrl + 1);
-       msleep(300);
-       outb(0xC, ctrl + 1);
-       msleep(100);
-       outb(0xE, ctrl + 1);
-       msleep(200);
-       outb(0xF, ctrl + 1);
-       msleep(100);
-       outb(0xE, ctrl + 1);
-       msleep(100);
-       outb(0xC, ctrl + 1);
-}
-
-/*
- * Socket Dual IO: this enables irq's for second port
- */
-static void quirk_config_socket(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-
-       if (info->multi)
-               link->config_flags |= CONF_ENABLE_ESR;
-}
-
-static const struct serial_quirk quirks[] = {
-       {
-               .manfid = 0x0160,
-               .prodid = 0x0104,
-               .multi  = -1,
-               .setup  = quirk_setup_brainboxes_0104,
-       }, {
-               .manfid = 0x015D,
-               .prodid = 0x4C45,
-               .multi  = -1,
-               .setup  = quirk_setup_brainboxes_0104,
-       }, {
-               .manfid = MANFID_IBM,
-               .prodid = ~0,
-               .multi  = -1,
-               .post   = quirk_post_ibm,
-       }, {
-               .manfid = MANFID_INTEL,
-               .prodid = PRODID_INTEL_DUAL_RS232,
-               .multi  = 2,
-       }, {
-               .manfid = MANFID_NATINST,
-               .prodid = PRODID_NATINST_QUAD_RS232,
-               .multi  = 4,
-       }, {
-               .manfid = MANFID_NOKIA,
-               .prodid = ~0,
-               .multi  = -1,
-               .config = quirk_config_nokia,
-       }, {
-               .manfid = MANFID_OMEGA,
-               .prodid = PRODID_OMEGA_QSP_100,
-               .multi  = 4,
-       }, {
-               .manfid = MANFID_OXSEMI,
-               .prodid = ~0,
-               .multi  = -1,
-               .wakeup = quirk_wakeup_oxsemi,
-       }, {
-               .manfid = MANFID_POSSIO,
-               .prodid = PRODID_POSSIO_GCC,
-               .multi  = -1,
-               .wakeup = quirk_wakeup_possio_gcc,
-       }, {
-               .manfid = MANFID_QUATECH,
-               .prodid = PRODID_QUATECH_DUAL_RS232,
-               .multi  = 2,
-       }, {
-               .manfid = MANFID_QUATECH,
-               .prodid = PRODID_QUATECH_DUAL_RS232_D1,
-               .multi  = 2,
-       }, {
-               .manfid = MANFID_QUATECH,
-               .prodid = PRODID_QUATECH_DUAL_RS232_G,
-               .multi  = 2,
-       }, {
-               .manfid = MANFID_QUATECH,
-               .prodid = PRODID_QUATECH_QUAD_RS232,
-               .multi  = 4,
-       }, {
-               .manfid = MANFID_SOCKET,
-               .prodid = PRODID_SOCKET_DUAL_RS232,
-               .multi  = 2,
-               .config = quirk_config_socket,
-       }, {
-               .manfid = MANFID_SOCKET,
-               .prodid = ~0,
-               .multi  = -1,
-               .config = quirk_config_socket,
-       }
-};
-
-
-static int serial_config(struct pcmcia_device * link);
-
-
-static void serial_remove(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-       int i;
-
-       dev_dbg(&link->dev, "serial_release\n");
-
-       /*
-        * Recheck to see if the device is still configured.
-        */
-       for (i = 0; i < info->ndev; i++)
-               serial8250_unregister_port(info->line[i]);
-
-       if (!info->slave)
-               pcmcia_disable_device(link);
-}
-
-static int serial_suspend(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-       int i;
-
-       for (i = 0; i < info->ndev; i++)
-               serial8250_suspend_port(info->line[i]);
-
-       return 0;
-}
-
-static int serial_resume(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-       int i;
-
-       for (i = 0; i < info->ndev; i++)
-               serial8250_resume_port(info->line[i]);
-
-       if (info->quirk && info->quirk->wakeup)
-               info->quirk->wakeup(link);
-
-       return 0;
-}
-
-static int serial_probe(struct pcmcia_device *link)
-{
-       struct serial_info *info;
-
-       dev_dbg(&link->dev, "serial_attach()\n");
-
-       /* Create new serial device */
-       info = kzalloc(sizeof (*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-       info->p_dev = link;
-       link->priv = info;
-
-       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-       if (do_sound)
-               link->config_flags |= CONF_ENABLE_SPKR;
-
-       return serial_config(link);
-}
-
-static void serial_detach(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-
-       dev_dbg(&link->dev, "serial_detach\n");
-
-       /*
-        * Ensure that the ports have been released.
-        */
-       serial_remove(link);
-
-       /* free bits */
-       kfree(info);
-}
-
-/*====================================================================*/
-
-static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
-                       unsigned int iobase, int irq)
-{
-       struct uart_port port;
-       int line;
-
-       memset(&port, 0, sizeof (struct uart_port));
-       port.iobase = iobase;
-       port.irq = irq;
-       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
-       port.uartclk = 1843200;
-       port.dev = &handle->dev;
-       if (buggy_uart)
-               port.flags |= UPF_BUGGY_UART;
-
-       if (info->quirk && info->quirk->setup)
-               info->quirk->setup(handle, &port);
-
-       line = serial8250_register_port(&port);
-       if (line < 0) {
-               printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
-                      "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
-               return -EINVAL;
-       }
-
-       info->line[info->ndev] = line;
-       info->ndev++;
-
-       return 0;
-}
-
-/*====================================================================*/
-
-static int pfc_config(struct pcmcia_device *p_dev)
-{
-       unsigned int port = 0;
-       struct serial_info *info = p_dev->priv;
-
-       if ((p_dev->resource[1]->end != 0) &&
-               (resource_size(p_dev->resource[1]) == 8)) {
-               port = p_dev->resource[1]->start;
-               info->slave = 1;
-       } else if ((info->manfid == MANFID_OSITECH) &&
-               (resource_size(p_dev->resource[0]) == 0x40)) {
-               port = p_dev->resource[0]->start + 0x28;
-               info->slave = 1;
-       }
-       if (info->slave)
-               return setup_serial(p_dev, info, port, p_dev->irq);
-
-       dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
-       return -ENODEV;
-}
-
-static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
-       static const int size_table[2] = { 8, 16 };
-       int *try = priv_data;
-
-       if (p_dev->resource[0]->start == 0)
-               return -ENODEV;
-
-       if ((*try & 0x1) == 0)
-               p_dev->io_lines = 16;
-
-       if (p_dev->resource[0]->end != size_table[(*try >> 1)])
-               return -ENODEV;
-
-       p_dev->resource[0]->end = 8;
-       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
-       return pcmcia_request_io(p_dev);
-}
-
-static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
-                                       void *priv_data)
-{
-       static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-       int j;
-
-       if (p_dev->io_lines > 3)
-               return -ENODEV;
-
-       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       p_dev->resource[0]->end = 8;
-
-       for (j = 0; j < 5; j++) {
-               p_dev->resource[0]->start = base[j];
-               p_dev->io_lines = base[j] ? 16 : 3;
-               if (!pcmcia_request_io(p_dev))
-                       return 0;
-       }
-       return -ENODEV;
-}
-
-static int simple_config(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-       int i = -ENODEV, try;
-
-       /* First pass: look for a config entry that looks normal.
-        * Two tries: without IO aliases, then with aliases */
-       link->config_flags |= CONF_AUTO_SET_VPP;
-       for (try = 0; try < 4; try++)
-               if (!pcmcia_loop_config(link, simple_config_check, &try))
-                       goto found_port;
-
-       /* Second pass: try to find an entry that isn't picky about
-          its base address, then try to grab any standard serial port
-          address, and finally try to get any free port. */
-       if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
-               goto found_port;
-
-       dev_warn(&link->dev, "no usable port range found, giving up\n");
-       return -1;
-
-found_port:
-       if (info->multi && (info->manfid == MANFID_3COM))
-               link->config_index &= ~(0x08);
-
-       /*
-        * Apply any configuration quirks.
-        */
-       if (info->quirk && info->quirk->config)
-               info->quirk->config(link);
-
-       i = pcmcia_enable_device(link);
-       if (i != 0)
-               return -1;
-       return setup_serial(link, info, link->resource[0]->start, link->irq);
-}
-
-static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
-       int *multi = priv_data;
-
-       if (p_dev->resource[1]->end)
-               return -EINVAL;
-
-       /* The quad port cards have bad CIS's, so just look for a
-          window larger than 8 ports and assume it will be right */
-       if (p_dev->resource[0]->end <= 8)
-               return -EINVAL;
-
-       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       p_dev->resource[0]->end = *multi * 8;
-
-       if (pcmcia_request_io(p_dev))
-               return -ENODEV;
-       return 0;
-}
-
-static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
-                                      void *priv_data)
-{
-       int *base2 = priv_data;
-
-       if (!p_dev->resource[0]->end || !p_dev->resource[1]->end ||
-               p_dev->resource[0]->start + 8 != p_dev->resource[1]->start)
-               return -ENODEV;
-
-       p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
-       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
-       if (pcmcia_request_io(p_dev))
-               return -ENODEV;
-
-       *base2 = p_dev->resource[0]->start + 8;
-       return 0;
-}
-
-static int multi_config(struct pcmcia_device *link)
-{
-       struct serial_info *info = link->priv;
-       int i, base2 = 0;
-
-       /* First, look for a generic full-sized window */
-       if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
-               base2 = link->resource[0]->start + 8;
-       else {
-               /* If that didn't work, look for two windows */
-               info->multi = 2;
-               if (pcmcia_loop_config(link, multi_config_check_notpicky,
-                                      &base2)) {
-                       dev_warn(&link->dev, "no usable port range "
-                              "found, giving up\n");
-                       return -ENODEV;
-               }
-       }
-
-       if (!link->irq)
-               dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
-
-       /*
-        * Apply any configuration quirks.
-        */
-       if (info->quirk && info->quirk->config)
-               info->quirk->config(link);
-
-       i = pcmcia_enable_device(link);
-       if (i != 0)
-               return -ENODEV;
-
-       /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
-        * 8 registers are for the UART, the others are extra registers.
-        * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
-        */
-       if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
-                               info->prodid == PRODID_POSSIO_GCC)) {
-               int err;
-
-               if (link->config_index == 1 ||
-                   link->config_index == 3) {
-                       err = setup_serial(link, info, base2,
-                                       link->irq);
-                       base2 = link->resource[0]->start;
-               } else {
-                       err = setup_serial(link, info, link->resource[0]->start,
-                                       link->irq);
-               }
-               info->c950ctrl = base2;
-
-               /*
-                * FIXME: We really should wake up the port prior to
-                * handing it over to the serial layer.
-                */
-               if (info->quirk && info->quirk->wakeup)
-                       info->quirk->wakeup(link);
-
-               return 0;
-       }
-
-       setup_serial(link, info, link->resource[0]->start, link->irq);
-       for (i = 0; i < info->multi - 1; i++)
-               setup_serial(link, info, base2 + (8 * i),
-                               link->irq);
-       return 0;
-}
-
-static int serial_check_for_multi(struct pcmcia_device *p_dev,  void *priv_data)
-{
-       struct serial_info *info = p_dev->priv;
-
-       if (!p_dev->resource[0]->end)
-               return -EINVAL;
-
-       if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
-               info->multi = p_dev->resource[0]->end >> 3;
-
-       if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
-               && (p_dev->resource[1]->end == 8))
-               info->multi = 2;
-
-       return 0; /* break */
-}
-
-
-static int serial_config(struct pcmcia_device * link)
-{
-       struct serial_info *info = link->priv;
-       int i;
-
-       dev_dbg(&link->dev, "serial_config\n");
-
-       /* Is this a compliant multifunction card? */
-       info->multi = (link->socket->functions > 1);
-
-       /* Is this a multiport card? */
-       info->manfid = link->manf_id;
-       info->prodid = link->card_id;
-
-       for (i = 0; i < ARRAY_SIZE(quirks); i++)
-               if ((quirks[i].manfid == ~0 ||
-                    quirks[i].manfid == info->manfid) &&
-                   (quirks[i].prodid == ~0 ||
-                    quirks[i].prodid == info->prodid)) {
-                       info->quirk = &quirks[i];
-                       break;
-               }
-
-       /* Another check for dual-serial cards: look for either serial or
-          multifunction cards that ask for appropriate IO port ranges */
-       if ((info->multi == 0) &&
-           (link->has_func_id) &&
-           (link->socket->pcmcia_pfc == 0) &&
-           ((link->func_id == CISTPL_FUNCID_MULTI) ||
-            (link->func_id == CISTPL_FUNCID_SERIAL)))
-               pcmcia_loop_config(link, serial_check_for_multi, info);
-
-       /*
-        * Apply any multi-port quirk.
-        */
-       if (info->quirk && info->quirk->multi != -1)
-               info->multi = info->quirk->multi;
-
-       dev_info(&link->dev,
-               "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
-               link->manf_id, link->card_id,
-               link->socket->pcmcia_pfc, info->multi, info->quirk);
-       if (link->socket->pcmcia_pfc)
-               i = pfc_config(link);
-       else if (info->multi > 1)
-               i = multi_config(link);
-       else
-               i = simple_config(link);
-
-       if (i || info->ndev == 0)
-               goto failed;
-
-       /*
-        * Apply any post-init quirk.  FIXME: This should really happen
-        * before we register the port, since it might already be in use.
-        */
-       if (info->quirk && info->quirk->post)
-               if (info->quirk->post(link))
-                       goto failed;
-
-       return 0;
-
-failed:
-       dev_warn(&link->dev, "failed to initialize\n");
-       serial_remove(link);
-       return -ENODEV;
-}
-
-static const struct pcmcia_device_id serial_ids[] = {
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
-       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
-       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
-       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
-       PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
-       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
-       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
-       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
-       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
-       PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
-       PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0b05),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
-       PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
-       PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
-       PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
-       PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
-       PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
-       PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
-       PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
-       PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
-       PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
-       PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
-       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
-       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
-       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
-       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
-       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
-       PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
-       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
-       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
-       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
-       PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
-       PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
-       PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
-       PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
-       PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
-       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
-       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
-       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
-       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
-       PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
-       PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
-       PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
-       PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
-       PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
-       PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
-       PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
-       PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
-       PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
-       PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
-       PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
-       PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
-       PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
-       PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
-       PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
-       PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
-       PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
-       PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
-       PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
-       PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
-       PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
-       PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
-       PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
-       PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
-       PCMCIA_DEVICE_PROD_ID12("OEM      ", "C288MX     ", 0xb572d360, 0xd2385b7a),
-       PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA   ", "C336MX     ", 0x99bcafe9, 0xaa25bcab),
-       PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
-       PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
-       PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
-       PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
-       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC860", 0xd85f6206, 0x698f93db, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC860 3G Network Adapter R1 */
-       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"),  /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
-       PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
-       PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
-       PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
-       PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
-       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100  1.00.",0x19ca78af,0xf964f42b),
-       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
-       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232  1.00.",0x19ca78af,0x69fb7490),
-       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235),
-       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3),
-       PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676),
-       PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
-       PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
-       PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
-       PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
-       /* too generic */
-       /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
-       /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
-       PCMCIA_DEVICE_FUNC_ID(2),
-       PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, serial_ids);
-
-MODULE_FIRMWARE("cis/PCMLM28.cis");
-MODULE_FIRMWARE("cis/DP83903.cis");
-MODULE_FIRMWARE("cis/3CCFEM556.cis");
-MODULE_FIRMWARE("cis/3CXEM556.cis");
-MODULE_FIRMWARE("cis/SW_8xx_SER.cis");
-MODULE_FIRMWARE("cis/SW_7xx_SER.cis");
-MODULE_FIRMWARE("cis/SW_555_SER.cis");
-MODULE_FIRMWARE("cis/MT5634ZLX.cis");
-MODULE_FIRMWARE("cis/COMpad2.cis");
-MODULE_FIRMWARE("cis/COMpad4.cis");
-MODULE_FIRMWARE("cis/RS-COM-2P.cis");
-
-static struct pcmcia_driver serial_cs_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "serial_cs",
-       .probe          = serial_probe,
-       .remove         = serial_detach,
-       .id_table       = serial_ids,
-       .suspend        = serial_suspend,
-       .resume         = serial_resume,
-};
-
-static int __init init_serial_cs(void)
-{
-       return pcmcia_register_driver(&serial_cs_driver);
-}
-
-static void __exit exit_serial_cs(void)
-{
-       pcmcia_unregister_driver(&serial_cs_driver);
-}
-
-module_init(init_serial_cs);
-module_exit(exit_serial_cs);
-
-MODULE_LICENSE("GPL");
index 9e62349b3d9f22cfeb59d2fcea49da4b068aac34..75085795528edd172568dedd2a82f5b160246029 100644 (file)
@@ -1339,7 +1339,7 @@ static void sci_submit_rx(struct sci_port *s)
                struct dma_async_tx_descriptor *desc;
 
                desc = chan->device->device_prep_slave_sg(chan,
-                       sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT);
+                       sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
 
                if (desc) {
                        s->desc_rx[i] = desc;
@@ -1454,7 +1454,7 @@ static void work_fn_tx(struct work_struct *work)
        BUG_ON(!sg_dma_len(sg));
 
        desc = chan->device->device_prep_slave_sg(chan,
-                       sg, s->sg_len_tx, DMA_TO_DEVICE,
+                       sg, s->sg_len_tx, DMA_MEM_TO_DEV,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                /* switch to PIO */
index ef9dd628ba0b9f00859a301a67e581f1bd60039c..bf6e238146ae40acd4ac8ea2f517574870366590 100644 (file)
@@ -227,7 +227,6 @@ int tty_port_block_til_ready(struct tty_port *port,
        int do_clocal = 0, retval;
        unsigned long flags;
        DEFINE_WAIT(wait);
-       int cd;
 
        /* block if port is in the process of being closed */
        if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
@@ -284,11 +283,14 @@ int tty_port_block_til_ready(struct tty_port *port,
                                retval = -ERESTARTSYS;
                        break;
                }
-               /* Probe the carrier. For devices with no carrier detect this
-                  will always return true */
-               cd = tty_port_carrier_raised(port);
+               /*
+                * Probe the carrier. For devices with no carrier detect
+                * tty_port_carrier_raised will always return true.
+                * Never ask drivers if CLOCAL is set, this causes troubles
+                * on some hardware.
+                */
                if (!(port->flags & ASYNC_CLOSING) &&
-                               (do_clocal || cd))
+                               (do_clocal || tty_port_carrier_raised(port)))
                        break;
                if (signal_pending(current)) {
                        retval = -ERESTARTSYS;
index 5e096f43bceaceb056098d69227d937501ef27bf..65447c5f91d7e0c1108d5f4db5d6eaf69af53234 100644 (file)
@@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
        if (!perm && op->op != KD_FONT_OP_GET)
                return -EPERM;
        op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
-       op->flags |= KD_FONT_FLAG_OLD;
        i = con_font_op(vc, op);
        if (i)
                return i;
index 1c50baff7725ec2d8e368b3c34f50925a76f3804..d2b3cffca3f786c9eb21c658604419e710a14985 100644 (file)
@@ -57,6 +57,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
 
 #define WDM_MAX                        16
 
+/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
+#define WDM_DEFAULT_BUFSIZE    256
 
 static DEFINE_MUTEX(wdm_mutex);
 
@@ -88,7 +90,8 @@ struct wdm_device {
        int                     count;
        dma_addr_t              shandle;
        dma_addr_t              ihandle;
-       struct mutex            lock;
+       struct mutex            wlock;
+       struct mutex            rlock;
        wait_queue_head_t       wait;
        struct work_struct      rxwork;
        int                     werr;
@@ -323,7 +326,7 @@ static ssize_t wdm_write
        }
 
        /* concurrent writes and disconnect */
-       r = mutex_lock_interruptible(&desc->lock);
+       r = mutex_lock_interruptible(&desc->wlock);
        rv = -ERESTARTSYS;
        if (r) {
                kfree(buf);
@@ -386,7 +389,7 @@ static ssize_t wdm_write
 out:
        usb_autopm_put_interface(desc->intf);
 outnp:
-       mutex_unlock(&desc->lock);
+       mutex_unlock(&desc->wlock);
 outnl:
        return rv < 0 ? rv : count;
 }
@@ -399,7 +402,7 @@ static ssize_t wdm_read
        struct wdm_device *desc = file->private_data;
 
 
-       rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
+       rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
        if (rv < 0)
                return -ERESTARTSYS;
 
@@ -467,14 +470,16 @@ retry:
        for (i = 0; i < desc->length - cntr; i++)
                desc->ubuf[i] = desc->ubuf[i + cntr];
 
+       spin_lock_irq(&desc->iuspin);
        desc->length -= cntr;
+       spin_unlock_irq(&desc->iuspin);
        /* in case we had outstanding data */
        if (!desc->length)
                clear_bit(WDM_READ, &desc->flags);
        rv = cntr;
 
 err:
-       mutex_unlock(&desc->lock);
+       mutex_unlock(&desc->rlock);
        return rv;
 }
 
@@ -540,7 +545,8 @@ static int wdm_open(struct inode *inode, struct file *file)
        }
        intf->needs_remote_wakeup = 1;
 
-       mutex_lock(&desc->lock);
+       /* using write lock to protect desc->count */
+       mutex_lock(&desc->wlock);
        if (!desc->count++) {
                desc->werr = 0;
                desc->rerr = 0;
@@ -553,7 +559,7 @@ static int wdm_open(struct inode *inode, struct file *file)
        } else {
                rv = 0;
        }
-       mutex_unlock(&desc->lock);
+       mutex_unlock(&desc->wlock);
        usb_autopm_put_interface(desc->intf);
 out:
        mutex_unlock(&wdm_mutex);
@@ -565,9 +571,11 @@ static int wdm_release(struct inode *inode, struct file *file)
        struct wdm_device *desc = file->private_data;
 
        mutex_lock(&wdm_mutex);
-       mutex_lock(&desc->lock);
+
+       /* using write lock to protect desc->count */
+       mutex_lock(&desc->wlock);
        desc->count--;
-       mutex_unlock(&desc->lock);
+       mutex_unlock(&desc->wlock);
 
        if (!desc->count) {
                dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
@@ -630,7 +638,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
        struct usb_cdc_dmm_desc *dmhd;
        u8 *buffer = intf->altsetting->extra;
        int buflen = intf->altsetting->extralen;
-       u16 maxcom = 0;
+       u16 maxcom = WDM_DEFAULT_BUFSIZE;
 
        if (!buffer)
                goto out;
@@ -665,7 +673,8 @@ next_desc:
        desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
        if (!desc)
                goto out;
-       mutex_init(&desc->lock);
+       mutex_init(&desc->rlock);
+       mutex_init(&desc->wlock);
        spin_lock_init(&desc->iuspin);
        init_waitqueue_head(&desc->wait);
        desc->wMaxCommand = maxcom;
@@ -716,7 +725,7 @@ next_desc:
                goto err;
 
        desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
-                                        desc->bMaxPacketSize0,
+                                        desc->wMaxCommand,
                                         GFP_KERNEL,
                                         &desc->response->transfer_dma);
        if (!desc->inbuf)
@@ -779,11 +788,13 @@ static void wdm_disconnect(struct usb_interface *intf)
        /* to terminate pending flushes */
        clear_bit(WDM_IN_USE, &desc->flags);
        spin_unlock_irqrestore(&desc->iuspin, flags);
-       mutex_lock(&desc->lock);
+       wake_up_all(&desc->wait);
+       mutex_lock(&desc->rlock);
+       mutex_lock(&desc->wlock);
        kill_urbs(desc);
        cancel_work_sync(&desc->rxwork);
-       mutex_unlock(&desc->lock);
-       wake_up_all(&desc->wait);
+       mutex_unlock(&desc->wlock);
+       mutex_unlock(&desc->rlock);
        if (!desc->count)
                cleanup(desc);
        mutex_unlock(&wdm_mutex);
@@ -798,8 +809,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
        dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
 
        /* if this is an autosuspend the caller does the locking */
-       if (!PMSG_IS_AUTO(message))
-               mutex_lock(&desc->lock);
+       if (!PMSG_IS_AUTO(message)) {
+               mutex_lock(&desc->rlock);
+               mutex_lock(&desc->wlock);
+       }
        spin_lock_irq(&desc->iuspin);
 
        if (PMSG_IS_AUTO(message) &&
@@ -815,8 +828,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
                kill_urbs(desc);
                cancel_work_sync(&desc->rxwork);
        }
-       if (!PMSG_IS_AUTO(message))
-               mutex_unlock(&desc->lock);
+       if (!PMSG_IS_AUTO(message)) {
+               mutex_unlock(&desc->wlock);
+               mutex_unlock(&desc->rlock);
+       }
 
        return rv;
 }
@@ -854,7 +869,8 @@ static int wdm_pre_reset(struct usb_interface *intf)
 {
        struct wdm_device *desc = usb_get_intfdata(intf);
 
-       mutex_lock(&desc->lock);
+       mutex_lock(&desc->rlock);
+       mutex_lock(&desc->wlock);
        kill_urbs(desc);
 
        /*
@@ -876,7 +892,8 @@ static int wdm_post_reset(struct usb_interface *intf)
        int rv;
 
        rv = recover_from_urb_loss(desc);
-       mutex_unlock(&desc->lock);
+       mutex_unlock(&desc->wlock);
+       mutex_unlock(&desc->rlock);
        return 0;
 }
 
index d136b8f4c8a7635f42b5d580930418d1c938355c..81e2c0d9c17de1a54720ef0b0432208c706a966b 100644 (file)
@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        dev->current_state = PCI_D0;
 
-       if (!dev->irq) {
+       /* The xHCI driver supports MSI and MSI-X,
+        * so don't fail if the BIOS doesn't provide a legacy IRQ.
+        */
+       if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
                dev_err(&dev->dev,
                        "Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
                        pci_name(dev));
index eb19cba34ac9ee0d2c2b078a3c3c3ef7dc42bc49..e1282328fc27f1ef17228ff4ad57747c79e2c927 100644 (file)
@@ -2447,8 +2447,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
                        && device_can_wakeup(&hcd->self.root_hub->dev))
                dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 
-       /* enable irqs just before we start the controller */
-       if (usb_hcd_is_primary_hcd(hcd)) {
+       /* enable irqs just before we start the controller,
+        * if the BIOS provides legacy PCI irqs.
+        */
+       if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
                retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
                if (retval)
                        goto err_request_irq;
index a0613d8f9be785bf0a52827acf2522b109bce1b2..265c2f675d04295e031513fc32506752e7720a99 100644 (file)
@@ -705,10 +705,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
        if (type == HUB_INIT3)
                goto init3;
 
-       /* After a resume, port power should still be on.
+       /* The superspeed hub except for root hub has to use Hub Depth
+        * value as an offset into the route string to locate the bits
+        * it uses to determine the downstream port number. So hub driver
+        * should send a set hub depth request to superspeed hub after
+        * the superspeed hub is set configuration in initialization or
+        * reset procedure.
+        *
+        * After a resume, port power should still be on.
         * For any other type of activation, turn it on.
         */
        if (type != HUB_RESUME) {
+               if (hdev->parent && hub_is_superspeed(hdev)) {
+                       ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+                                       HUB_SET_DEPTH, USB_RT_HUB,
+                                       hdev->level - 1, 0, NULL, 0,
+                                       USB_CTRL_SET_TIMEOUT);
+                       if (ret < 0)
+                               dev_err(hub->intfdev,
+                                               "set hub depth failed\n");
+               }
 
                /* Speed up system boot by using a delayed_work for the
                 * hub's initial power-up delays.  This is pretty awkward
@@ -987,18 +1003,6 @@ static int hub_configure(struct usb_hub *hub,
                goto fail;
        }
 
-       if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) {
-               ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
-                               HUB_SET_DEPTH, USB_RT_HUB,
-                               hdev->level - 1, 0, NULL, 0,
-                               USB_CTRL_SET_TIMEOUT);
-
-               if (ret < 0) {
-                       message = "can't set hub depth";
-                       goto fail;
-               }
-       }
-
        /* Request the entire hub descriptor.
         * hub->descriptor can handle USB_MAXCHILDREN ports,
         * but the hub can/will return fewer bytes here.
index 2f51de57593a11ebc617085707d22e67735165de..c8df1dd967efe3e5160fbe8507a8b2bbff972aa5 100644 (file)
@@ -126,7 +126,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
                struct dwc3_request *req)
 {
        struct dwc3             *dwc = dep->dwc;
-       u32                     type;
        int                     ret = 0;
 
        req->request.actual     = 0;
@@ -149,20 +148,14 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 
                direction = !!(dep->flags & DWC3_EP0_DIR_IN);
 
-               if (dwc->ep0state == EP0_STATUS_PHASE) {
-                       type = dwc->three_stage_setup
-                               ? DWC3_TRBCTL_CONTROL_STATUS3
-                               : DWC3_TRBCTL_CONTROL_STATUS2;
-               } else if (dwc->ep0state == EP0_DATA_PHASE) {
-                       type = DWC3_TRBCTL_CONTROL_DATA;
-               } else {
-                       /* should never happen */
-                       WARN_ON(1);
+               if (dwc->ep0state != EP0_DATA_PHASE) {
+                       dev_WARN(dwc->dev, "Unexpected pending request\n");
                        return 0;
                }
 
                ret = dwc3_ep0_start_trans(dwc, direction,
-                               req->request.dma, req->request.length, type);
+                               req->request.dma, req->request.length,
+                               DWC3_TRBCTL_CONTROL_DATA);
                dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
                                DWC3_EP0_DIR_IN);
        } else if (dwc->delayed_status) {
index a696bde5322268013819ac43d9059da653d9c045..064b6e2cd4118635508a1dcc4eddfd63e3d08189 100644 (file)
@@ -101,7 +101,7 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
        if (req->request.num_mapped_sgs) {
                req->request.dma = DMA_ADDR_INVALID;
                dma_unmap_sg(dwc->dev, req->request.sg,
-                               req->request.num_sgs,
+                               req->request.num_mapped_sgs,
                                req->direction ? DMA_TO_DEVICE
                                : DMA_FROM_DEVICE);
 
index a95de6a4a13447d3217d7495bcd94079bca04903..baaebf2830fce882022801f7a492a01c4b9f4c79 100644 (file)
@@ -175,13 +175,12 @@ ep_found:
        _ep->comp_desc = comp_desc;
        if (g->speed == USB_SPEED_SUPER) {
                switch (usb_endpoint_type(_ep->desc)) {
-               case USB_ENDPOINT_XFER_BULK:
-               case USB_ENDPOINT_XFER_INT:
-                       _ep->maxburst = comp_desc->bMaxBurst;
-                       break;
                case USB_ENDPOINT_XFER_ISOC:
                        /* mult: bits 1:0 of bmAttributes */
                        _ep->mult = comp_desc->bmAttributes & 0x3;
+               case USB_ENDPOINT_XFER_BULK:
+               case USB_ENDPOINT_XFER_INT:
+                       _ep->maxburst = comp_desc->bMaxBurst;
                        break;
                default:
                        /* Do nothing for control endpoints */
index 753aa0683ac12c483ed34e23543063182bc15536..e0e6375ef5dd7693cb89ff24397223e94f26aa7a 100644 (file)
@@ -126,7 +126,7 @@ ep_matches (
         * descriptor and see if the EP matches it
         */
        if (usb_endpoint_xfer_bulk(desc)) {
-               if (ep_comp) {
+               if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
                        num_req_streams = ep_comp->bmAttributes & 0x1f;
                        if (num_req_streams > ep->max_streams)
                                return 0;
index 6d87f288df4eca0625dc6dccf28c151f2f268991..2c0cd824c667488bb1c0e5b9fb5375f9086eae38 100644 (file)
@@ -418,7 +418,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
 
        /* support autoresume for remote wakeup testing */
        if (autoresume)
-               sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+               loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 
        /* support OTG systems */
        if (gadget_is_otg(cdev->gadget)) {
index 6353eca1e852e5fa260d7e38562816ec6fd1338d..ee8ceec01560e5391a4f115c130002bd98917e41 100644 (file)
@@ -3123,15 +3123,15 @@ fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c,
 
 struct fsg_module_parameters {
        char            *file[FSG_MAX_LUNS];
-       int             ro[FSG_MAX_LUNS];
-       int             removable[FSG_MAX_LUNS];
-       int             cdrom[FSG_MAX_LUNS];
-       int             nofua[FSG_MAX_LUNS];
+       bool            ro[FSG_MAX_LUNS];
+       bool            removable[FSG_MAX_LUNS];
+       bool            cdrom[FSG_MAX_LUNS];
+       bool            nofua[FSG_MAX_LUNS];
 
        unsigned int    file_count, ro_count, removable_count, cdrom_count;
        unsigned int    nofua_count;
        unsigned int    luns;   /* nluns */
-       int             stall;  /* can_stall */
+       bool            stall;  /* can_stall */
 };
 
 #define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc)      \
index d7ea6c076ce98e185ee43b557c524d2b29c67270..b04712f19f1efa613261c2216b08b31958ec4973 100644 (file)
@@ -1430,7 +1430,7 @@ static void setup_received_irq(struct fsl_udc *udc,
                        int pipe = get_pipe_by_windex(wIndex);
                        struct fsl_ep *ep;
 
-                       if (wValue != 0 || wLength != 0 || pipe > udc->max_ep)
+                       if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep)
                                break;
                        ep = get_ep_by_pipe(udc, pipe);
 
@@ -1673,7 +1673,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
        if (!bit_pos)
                return;
 
-       for (i = 0; i < udc->max_ep * 2; i++) {
+       for (i = 0; i < udc->max_ep; i++) {
                ep_num = i >> 1;
                direction = i % 2;
 
index fa0fcc11263fb8b6a73d21bcdbe7ba3f168e19dc..e2293c1588eed80a2e0ba031677f918f774305f0 100644 (file)
 /* #undef      DEBUG */
 /* #undef      VERBOSE_DEBUG */
 
-#if defined(CONFIG_USB_LANGWELL_OTG)
-#define        OTG_TRANSCEIVER
-#endif
-
-
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -1522,8 +1517,7 @@ static void langwell_udc_stop(struct langwell_udc *dev)
 
 
 /* stop all USB activities */
-static void stop_activity(struct langwell_udc *dev,
-               struct usb_gadget_driver *driver)
+static void stop_activity(struct langwell_udc *dev)
 {
        struct langwell_ep      *ep;
        dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
@@ -1535,9 +1529,9 @@ static void stop_activity(struct langwell_udc *dev,
        }
 
        /* report disconnect; the driver is already quiesced */
-       if (driver) {
+       if (dev->driver) {
                spin_unlock(&dev->lock);
-               driver->disconnect(&dev->gadget);
+               dev->driver->disconnect(&dev->gadget);
                spin_lock(&dev->lock);
        }
 
@@ -1925,11 +1919,10 @@ static int langwell_stop(struct usb_gadget *g,
 
        /* stop all usb activities */
        dev->gadget.speed = USB_SPEED_UNKNOWN;
-       stop_activity(dev, driver);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
        dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
+       stop_activity(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
 
        device_remove_file(&dev->pdev->dev, &dev_attr_function);
 
@@ -2315,13 +2308,9 @@ static void handle_setup_packet(struct langwell_udc *dev,
 
                        if (!gadget_is_otg(&dev->gadget))
                                break;
-                       else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
+                       else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
                                dev->gadget.b_hnp_enable = 1;
-#ifdef OTG_TRANSCEIVER
-                               if (!dev->lotg->otg.default_a)
-                                       dev->lotg->hsm.b_hnp_enable = 1;
-#endif
-                       } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
+                       else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
                                dev->gadget.a_hnp_support = 1;
                        else if (setup->bRequest ==
                                        USB_DEVICE_A_ALT_HNP_SUPPORT)
@@ -2733,7 +2722,7 @@ static void handle_usb_reset(struct langwell_udc *dev)
                dev->bus_reset = 1;
 
                /* reset all the queues, stop all USB activities */
-               stop_activity(dev, dev->driver);
+               stop_activity(dev);
                dev->usb_state = USB_STATE_DEFAULT;
        } else {
                dev_vdbg(&dev->pdev->dev, "device controller reset\n");
@@ -2741,7 +2730,7 @@ static void handle_usb_reset(struct langwell_udc *dev)
                langwell_udc_reset(dev);
 
                /* reset all the queues, stop all USB activities */
-               stop_activity(dev, dev->driver);
+               stop_activity(dev);
 
                /* reset ep0 dQH and endptctrl */
                ep0_reset(dev);
@@ -2752,12 +2741,6 @@ static void handle_usb_reset(struct langwell_udc *dev)
                dev->usb_state = USB_STATE_ATTACHED;
        }
 
-#ifdef OTG_TRANSCEIVER
-       /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */
-       if (!dev->lotg->otg.default_a)
-               dev->lotg->hsm.b_hnp_enable = 0;
-#endif
-
        dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
@@ -2770,29 +2753,6 @@ static void handle_bus_suspend(struct langwell_udc *dev)
        dev->resume_state = dev->usb_state;
        dev->usb_state = USB_STATE_SUSPENDED;
 
-#ifdef OTG_TRANSCEIVER
-       if (dev->lotg->otg.default_a) {
-               if (dev->lotg->hsm.b_bus_suspend_vld == 1) {
-                       dev->lotg->hsm.b_bus_suspend = 1;
-                       /* notify transceiver the state changes */
-                       if (spin_trylock(&dev->lotg->wq_lock)) {
-                               langwell_update_transceiver();
-                               spin_unlock(&dev->lotg->wq_lock);
-                       }
-               }
-               dev->lotg->hsm.b_bus_suspend_vld++;
-       } else {
-               if (!dev->lotg->hsm.a_bus_suspend) {
-                       dev->lotg->hsm.a_bus_suspend = 1;
-                       /* notify transceiver the state changes */
-                       if (spin_trylock(&dev->lotg->wq_lock)) {
-                               langwell_update_transceiver();
-                               spin_unlock(&dev->lotg->wq_lock);
-                       }
-               }
-       }
-#endif
-
        /* report suspend to the driver */
        if (dev->driver) {
                if (dev->driver->suspend) {
@@ -2823,11 +2783,6 @@ static void handle_bus_resume(struct langwell_udc *dev)
        if (dev->pdev->device != 0x0829)
                langwell_phy_low_power(dev, 0);
 
-#ifdef OTG_TRANSCEIVER
-       if (dev->lotg->otg.default_a == 0)
-               dev->lotg->hsm.a_bus_suspend = 0;
-#endif
-
        /* report resume to the driver */
        if (dev->driver) {
                if (dev->driver->resume) {
@@ -3020,7 +2975,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
 
        dev->done = &done;
 
-#ifndef        OTG_TRANSCEIVER
        /* free dTD dma_pool and dQH */
        if (dev->dtd_pool)
                dma_pool_destroy(dev->dtd_pool);
@@ -3032,7 +2986,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
        /* release SRAM caching */
        if (dev->has_sram && dev->got_sram)
                sram_deinit(dev);
-#endif
 
        if (dev->status_req) {
                kfree(dev->status_req->req.buf);
@@ -3045,7 +2998,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
        if (dev->got_irq)
                free_irq(pdev->irq, dev);
 
-#ifndef        OTG_TRANSCEIVER
        if (dev->cap_regs)
                iounmap(dev->cap_regs);
 
@@ -3055,13 +3007,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
 
        if (dev->enabled)
                pci_disable_device(pdev);
-#else
-       if (dev->transceiver) {
-               otg_put_transceiver(dev->transceiver);
-               dev->transceiver = NULL;
-               dev->lotg = NULL;
-       }
-#endif
 
        dev->cap_regs = NULL;
 
@@ -3072,9 +3017,7 @@ static void langwell_udc_remove(struct pci_dev *pdev)
        device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
        device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
 
-#ifndef        OTG_TRANSCEIVER
        pci_set_drvdata(pdev, NULL);
-#endif
 
        /* free dev, wait for the release() finished */
        wait_for_completion(&done);
@@ -3089,9 +3032,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
                const struct pci_device_id *id)
 {
        struct langwell_udc     *dev;
-#ifndef        OTG_TRANSCEIVER
        unsigned long           resource, len;
-#endif
        void                    __iomem *base = NULL;
        size_t                  size;
        int                     retval;
@@ -3109,16 +3050,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
        dev->pdev = pdev;
        dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-#ifdef OTG_TRANSCEIVER
-       /* PCI device is already enabled by otg_transceiver driver */
-       dev->enabled = 1;
-
-       /* mem region and register base */
-       dev->region = 1;
-       dev->transceiver = otg_get_transceiver();
-       dev->lotg = otg_to_langwell(dev->transceiver);
-       base = dev->lotg->regs;
-#else
        pci_set_drvdata(pdev, dev);
 
        /* now all the pci goodies ... */
@@ -3139,7 +3070,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
        dev->region = 1;
 
        base = ioremap_nocache(resource, len);
-#endif
        if (base == NULL) {
                dev_err(&dev->pdev->dev, "can't map memory\n");
                retval = -EFAULT;
@@ -3163,7 +3093,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
        dev->got_sram = 0;
        dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
 
-#ifndef        OTG_TRANSCEIVER
        /* enable SRAM caching if detected */
        if (dev->has_sram && !dev->got_sram)
                sram_init(dev);
@@ -3182,7 +3111,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
                goto error;
        }
        dev->got_irq = 1;
-#endif
 
        /* set stopped bit */
        dev->stopped = 1;
@@ -3257,10 +3185,8 @@ static int langwell_udc_probe(struct pci_dev *pdev,
        dev->remote_wakeup = 0;
        dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
 
-#ifndef        OTG_TRANSCEIVER
        /* reset device controller */
        langwell_udc_reset(dev);
-#endif
 
        /* initialize gadget structure */
        dev->gadget.ops = &langwell_ops;        /* usb_gadget_ops */
@@ -3268,9 +3194,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
        INIT_LIST_HEAD(&dev->gadget.ep_list);   /* ep_list */
        dev->gadget.speed = USB_SPEED_UNKNOWN;  /* speed */
        dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
-#ifdef OTG_TRANSCEIVER
-       dev->gadget.is_otg = 1;                 /* support otg mode */
-#endif
 
        /* the "gadget" abstracts/virtualizes the controller */
        dev_set_name(&dev->gadget.dev, "gadget");
@@ -3282,10 +3205,8 @@ static int langwell_udc_probe(struct pci_dev *pdev,
        /* controller endpoints reinit */
        eps_reinit(dev);
 
-#ifndef        OTG_TRANSCEIVER
        /* reset ep0 dQH and endptctrl */
        ep0_reset(dev);
-#endif
 
        /* create dTD dma_pool resource */
        dev->dtd_pool = dma_pool_create("langwell_dtd",
@@ -3367,7 +3288,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
 
        spin_lock_irq(&dev->lock);
        /* stop all usb activities */
-       stop_activity(dev, dev->driver);
+       stop_activity(dev);
        spin_unlock_irq(&dev->lock);
 
        /* free dTD dma_pool and dQH */
@@ -3525,22 +3446,14 @@ static struct pci_driver langwell_pci_driver = {
 
 static int __init init(void)
 {
-#ifdef OTG_TRANSCEIVER
-       return langwell_register_peripheral(&langwell_pci_driver);
-#else
        return pci_register_driver(&langwell_pci_driver);
-#endif
 }
 module_init(init);
 
 
 static void __exit cleanup(void)
 {
-#ifdef OTG_TRANSCEIVER
-       return langwell_unregister_peripheral(&langwell_pci_driver);
-#else
        pci_unregister_driver(&langwell_pci_driver);
-#endif
 }
 module_exit(cleanup);
 
index ef79e242b7b0debf6b9bbb169dd2b5cedf13c733..d6e78accaffee7d8fc68d26291c404e5846d5ac2 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/usb/langwell_udc.h>
-#include <linux/usb/langwell_otg.h>
 
 /*-------------------------------------------------------------------------*/
 
index c7f291a331dfc4454a4879b8e5361f6a3b95278c..85ea14e2545e8fa29d777ddbd945ed8df8476807 100644 (file)
@@ -598,16 +598,16 @@ static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = {
                | USB_5GBPS_OPERATION),
        .bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
        .bU1devExitLat =        USB_DEFAULT_U1_DEV_EXIT_LAT,
-       .bU2DevExitLat =        USB_DEFAULT_U2_DEV_EXIT_LAT,
+       .bU2DevExitLat =        cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
 };
 
 static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
        .bLength =              USB_DT_BOS_SIZE,
        .bDescriptorType =      USB_DT_BOS,
 
-       .wTotalLength =         USB_DT_BOS_SIZE
+       .wTotalLength =         cpu_to_le16(USB_DT_BOS_SIZE
                                + USB_DT_USB_EXT_CAP_SIZE
-                               + USB_DT_USB_SS_CAP_SIZE,
+                               + USB_DT_USB_SS_CAP_SIZE),
 
        .bNumDeviceCaps =       2,
 };
index 91413cac97beec3d17c20aff307c4236f2a5a192..353cdd488b93933f61d25d6f916439d882a5afe8 100644 (file)
@@ -130,7 +130,7 @@ config USB_FSL_MPH_DR_OF
        tristate
 
 config USB_EHCI_FSL
-       bool "Support for Freescale on-chip EHCI USB controller"
+       bool "Support for Freescale PPC on-chip EHCI USB controller"
        depends on USB_EHCI_HCD && FSL_SOC
        select USB_EHCI_ROOT_HUB_TT
        select USB_FSL_MPH_DR_OF if OF
@@ -138,7 +138,7 @@ config USB_EHCI_FSL
          Variation of ARC USB block used in some Freescale chips.
 
 config USB_EHCI_MXC
-       bool "Support for Freescale on-chip EHCI USB controller"
+       bool "Support for Freescale i.MX on-chip EHCI USB controller"
        depends on USB_EHCI_HCD && ARCH_MXC
        select USB_EHCI_ROOT_HUB_TT
        ---help---
@@ -546,7 +546,7 @@ config USB_RENESAS_USBHS_HCD
 config USB_WHCI_HCD
        tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       depends on PCI && USB
+       depends on PCI && USB && UWB
        select USB_WUSB
        select UWB_WHCI
        help
@@ -559,7 +559,7 @@ config USB_WHCI_HCD
 config USB_HWA_HCD
        tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       depends on USB
+       depends on USB && UWB
        select USB_WUSB
        select UWB_HWA
        help
index e90344a1763173e4c49c9099ecf65a7609aad358..c26a82e83f6e6d11b78f002dc3982df9a3b0a27b 100644 (file)
@@ -125,7 +125,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
         */
        if (pdata->init && pdata->init(pdev)) {
                retval = -ENODEV;
-               goto err3;
+               goto err4;
        }
 
        /* Enable USB controller, 83xx or 8536 */
@@ -239,7 +239,7 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
        ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 }
 
-static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
+static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 {
        struct usb_hcd *hcd = ehci_to_hcd(ehci);
        struct fsl_usb2_platform_data *pdata;
@@ -299,12 +299,19 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 #endif
                out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
        }
+
+       if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) {
+               printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
+               return -ENODEV;
+       }
+       return 0;
 }
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
-       ehci_fsl_usb_setup(ehci);
+       if (ehci_fsl_usb_setup(ehci))
+               return -ENODEV;
        ehci_port_power(ehci, 0);
 
        return 0;
index 4918062211656c276f5904cc50d45605076ed026..bdf43e2adc51a4fdb4f12ca4e70b1e5c42c62f2c 100644 (file)
@@ -45,5 +45,6 @@
 #define FSL_SOC_USB_PRICTRL    0x40c   /* NOTE: big-endian */
 #define FSL_SOC_USB_SICTRL     0x410   /* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL       0x500   /* NOTE: big-endian */
+#define CTRL_PHY_CLK_VALID     (1 << 17)
 #define SNOOP_SIZE_2GB         0x1e
 #endif                         /* _EHCI_FSL_H */
index f4b627d343acdf39d1f33d20cea8da7dc6c0f27d..01bb7241d6efd53f3769d47e86d59a28c5cf9ce2 100644 (file)
@@ -276,6 +276,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 
        /* Serial Bus Release Number is at PCI 0x60 offset */
        pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+       if (pdev->vendor == PCI_VENDOR_ID_STMICRO
+           && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
+               ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
 
        /* Keep this around for a while just in case some EHCI
         * implementation uses legacy PCI PM support.  This test
@@ -526,6 +529,9 @@ static const struct pci_device_id pci_ids [] = { {
        /* handle any USB 2.0 EHCI controller */
        PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
        .driver_data =  (unsigned long) &ehci_pci_hc_driver,
+       }, {
+       PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST),
+       .driver_data = (unsigned long) &ehci_pci_hc_driver,
        },
        { /* end: all zeroes */ }
 };
index 32793ce3d9e9dd4a32588204d5a59680046374e6..9c2cc4633894b152047ed587b2cf9494d5fdc684 100644 (file)
@@ -183,7 +183,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
        }
 
        irq = irq_of_parse_and_map(dn, 0);
-       if (irq == NO_IRQ) {
+       if (!irq) {
                printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
                rv = -EBUSY;
                goto err_irq;
index 5df0b0e3392bed244a414bcc58f4da104822b49c..77afabc77f9be8d71fd4502bd5f315d9c8bd2c40 100644 (file)
@@ -139,8 +139,23 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        }
 
        iclk = clk_get(&pdev->dev, "ohci_clk");
+       if (IS_ERR(iclk)) {
+               dev_err(&pdev->dev, "failed to get ohci_clk\n");
+               retval = PTR_ERR(iclk);
+               goto err3;
+       }
        fclk = clk_get(&pdev->dev, "uhpck");
+       if (IS_ERR(fclk)) {
+               dev_err(&pdev->dev, "failed to get uhpck\n");
+               retval = PTR_ERR(fclk);
+               goto err4;
+       }
        hclk = clk_get(&pdev->dev, "hclk");
+       if (IS_ERR(hclk)) {
+               dev_err(&pdev->dev, "failed to get hclk\n");
+               retval = PTR_ERR(hclk);
+               goto err5;
+       }
 
        at91_start_hc(pdev);
        ohci_hcd_init(hcd_to_ohci(hcd));
@@ -153,9 +168,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        at91_stop_hc(pdev);
 
        clk_put(hclk);
+ err5:
        clk_put(fclk);
+ err4:
        clk_put(iclk);
 
+ err3:
        iounmap(hcd->regs);
 
  err2:
@@ -226,7 +244,8 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int
        if (!gpio_is_valid(pdata->vbus_pin[port]))
                return;
 
-       gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
+       gpio_set_value(pdata->vbus_pin[port],
+                      !pdata->vbus_pin_active_low[port] ^ enable);
 }
 
 static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
@@ -237,7 +256,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
        if (!gpio_is_valid(pdata->vbus_pin[port]))
                return -EINVAL;
 
-       return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
+       return gpio_get_value(pdata->vbus_pin[port]) ^
+               !pdata->vbus_pin_active_low[port];
 }
 
 /*
index 5179fcd73d8a391b165abaf1327dd944916dce1a..e4bcb62b930a9ef9e790044255b0d587c890e6c1 100644 (file)
@@ -82,6 +82,14 @@ urb_print(struct urb * urb, char * str, int small, int status)
                ohci_dbg(ohci,format, ## arg ); \
        } while (0);
 
+/* Version for use where "next" is the address of a local variable */
+#define ohci_dbg_nosw(ohci, next, size, format, arg...) \
+       do { \
+               unsigned s_len; \
+               s_len = scnprintf(*next, *size, format, ## arg); \
+               *size -= s_len; *next += s_len; \
+       } while (0);
+
 
 static void ohci_dump_intr_mask (
        struct ohci_hcd *ohci,
@@ -653,7 +661,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 
        /* dump driver info, then registers in spec order */
 
-       ohci_dbg_sw (ohci, &next, &size,
+       ohci_dbg_nosw(ohci, &next, &size,
                "bus %s, device %s\n"
                "%s\n"
                "%s\n",
@@ -672,7 +680,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 
        /* hcca */
        if (ohci->hcca)
-               ohci_dbg_sw (ohci, &next, &size,
+               ohci_dbg_nosw(ohci, &next, &size,
                        "hcca frame 0x%04x\n", ohci_frame_no(ohci));
 
        /* other registers mostly affect frame timings */
index 6109810cc2d3eba72c8eeb6ebb38eff17b93a399..1843bb68ac7ceefc73afcc2ed9f3a2f7fa8de1db 100644 (file)
@@ -397,6 +397,10 @@ static const struct pci_device_id pci_ids [] = { {
        /* handle any USB OHCI controller */
        PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
        .driver_data =  (unsigned long) &ohci_pci_hc_driver,
+       }, {
+       /* The device in the ConneXT I/O hub has no class reg */
+       PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI),
+       .driver_data =  (unsigned long) &ohci_pci_hc_driver,
        }, { /* end: all zeroes */ }
 };
 MODULE_DEVICE_TABLE (pci, pci_ids);
index caf87428ca43c3f38985d9469b566645ea3d3bf9..7732d69e49e012cca439ef21ea6b911cf2942c91 100644 (file)
@@ -867,6 +867,22 @@ hc_init:
 
 static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
 {
+       /* Skip Netlogic mips SoC's internal PCI USB controller.
+        * This device does not need/support EHCI/OHCI handoff
+        */
+       if (pdev->vendor == 0x184e)     /* vendor Netlogic */
+               return;
+       if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI &&
+                       pdev->class != PCI_CLASS_SERIAL_USB_OHCI &&
+                       pdev->class != PCI_CLASS_SERIAL_USB_EHCI &&
+                       pdev->class != PCI_CLASS_SERIAL_USB_XHCI)
+               return;
+
+       if (pci_enable_device(pdev) < 0) {
+               dev_warn(&pdev->dev, "Can't enable PCI device, "
+                               "BIOS handoff failed.\n");
+               return;
+       }
        if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
                quirk_usb_handoff_uhci(pdev);
        else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
@@ -875,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
                quirk_usb_disable_ehci(pdev);
        else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
                quirk_usb_handoff_xhci(pdev);
+       pci_disable_device(pdev);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
index 35e257f79c7b0c7d8565a753e5e5dfb90b128301..557b6f32db86730af004eec3b2ad889bf9457f65 100644 (file)
@@ -93,7 +93,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
         */
        memset(port_removable, 0, sizeof(port_removable));
        for (i = 0; i < ports; i++) {
-               portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+               portsc = xhci_readl(xhci, xhci->usb2_ports[i]);
                /* If a device is removable, PORTSC reports a 0, same as in the
                 * hub descriptor DeviceRemovable bits.
                 */
index 36cbe2226a44e46b3acd6c8269ede7ab57fc03ad..383fc857491c677fbaf6d0ab56b8cdff9cc415d2 100644 (file)
@@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
 }
 
 /*
- * Convert bInterval expressed in frames (in 1-255 range) to exponent of
+ * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
  * microframes, rounded down to nearest power of 2.
  */
-static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
-               struct usb_host_endpoint *ep)
+static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
+               struct usb_host_endpoint *ep, unsigned int desc_interval,
+               unsigned int min_exponent, unsigned int max_exponent)
 {
        unsigned int interval;
 
-       interval = fls(8 * ep->desc.bInterval) - 1;
-       interval = clamp_val(interval, 3, 10);
-       if ((1 << interval) != 8 * ep->desc.bInterval)
+       interval = fls(desc_interval) - 1;
+       interval = clamp_val(interval, min_exponent, max_exponent);
+       if ((1 << interval) != desc_interval)
                dev_warn(&udev->dev,
                         "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
                         ep->desc.bEndpointAddress,
                         1 << interval,
-                        8 * ep->desc.bInterval);
+                        desc_interval);
 
        return interval;
 }
 
+static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+{
+       return xhci_microframes_to_exponent(udev, ep,
+                       ep->desc.bInterval, 0, 15);
+}
+
+
+static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+{
+       return xhci_microframes_to_exponent(udev, ep,
+                       ep->desc.bInterval * 8, 3, 10);
+}
+
 /* Return the polling or NAK interval.
  *
  * The polling interval is expressed in "microframes".  If xHCI's Interval field
@@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
                /* Max NAK rate */
                if (usb_endpoint_xfer_control(&ep->desc) ||
                    usb_endpoint_xfer_bulk(&ep->desc)) {
-                       interval = ep->desc.bInterval;
+                       interval = xhci_parse_microframe_interval(udev, ep);
                        break;
                }
                /* Fall through - SS and HS isoc/int have same decoding */
index b90e1386418b429f05eada3487117d4fbba50186..b62037bff688c07c38f0ad06e22ab8cb964bf62f 100644 (file)
@@ -1204,6 +1204,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci,
  *
  * Returns a zero-based port number, which is suitable for indexing into each of
  * the split roothubs' port arrays and bus state arrays.
+ * Add one to it in order to call xhci_find_slot_id_by_port.
  */
 static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
                struct xhci_hcd *xhci, u32 port_id)
@@ -1324,7 +1325,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                        xhci_set_link_state(xhci, port_array, faked_port_index,
                                                XDEV_U0);
                        slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                       faked_port_index);
+                                       faked_port_index + 1);
                        if (!slot_id) {
                                xhci_dbg(xhci, "slot_id is zero\n");
                                goto cleanup;
@@ -3323,7 +3324,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                /* Check TD length */
                if (running_total != td_len) {
                        xhci_err(xhci, "ISOC TD length unmatch\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto cleanup;
                }
        }
 
index 6bbe3c3a71115e61ee7fe663758789088c21d340..c939f5fdef9e2414f61f63cd07776041d5411cf9 100644 (file)
@@ -352,6 +352,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
                /* hcd->irq is -1, we have MSI */
                return 0;
 
+       if (!pdev->irq) {
+               xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
+               return -EINVAL;
+       }
+
        /* fall back to legacy interrupt*/
        ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
                        hcd->irq_descr, hcd);
index d9b6a0355443c8457b16e3e660f7a0edb7324d25..da97dcec1f32c88ee95c49a097517b1e9390b41d 100644 (file)
@@ -37,9 +37,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
 static int emi26_load_firmware (struct usb_device *dev);
 static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
 static void emi26_disconnect(struct usb_interface *intf);
-static int __init emi26_init (void);
-static void __exit emi26_exit (void);
-
 
 /* thanks to drivers/usb/serial/keyspan_pda.c code */
 static int emi26_writememory (struct usb_device *dev, int address,
index 9f39062ebb080dfe57644fdcb52ea2e74542576d..4e0f167a6c4ef49832bd1357517e738b397980a0 100644 (file)
@@ -46,9 +46,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
 static int emi62_load_firmware (struct usb_device *dev);
 static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
 static void emi62_disconnect(struct usb_interface *intf);
-static int __init emi62_init (void);
-static void __exit emi62_exit (void);
-
 
 /* thanks to drivers/usb/serial/keyspan_pda.c code */
 static int emi62_writememory(struct usb_device *dev, int address,
index 107bf13b1cf14e64619a081b3f28c4d6f67ae94d..b2d82b937392eb9b0186416938d2485b2fd29f18 100644 (file)
@@ -24,7 +24,7 @@
 
 #define VENDOR_ID      0x0fc5
 #define PRODUCT_ID     0x1227
-#define MAXLEN         6
+#define MAXLEN         8
 
 /* table of devices that work with this driver */
 static const struct usb_device_id id_table[] = {
index f9a3f62a83b51d82d9192a4d9325eb0318df689e..7c569f51212abeeed36e504dde9b6a1e5460817c 100644 (file)
@@ -33,9 +33,6 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/gpio.h>
 #include <mach/cputype.h>
 
 #include <asm/mach-types.h>
index 56cf0243979e504df48742f447dd1e6c977ab924..3d11cf64ebd17d6b318df2bd33f696a15029da8a 100644 (file)
@@ -981,6 +981,9 @@ static void musb_shutdown(struct platform_device *pdev)
        unsigned long   flags;
 
        pm_runtime_get_sync(musb->controller);
+
+       musb_gadget_cleanup(musb);
+
        spin_lock_irqsave(&musb->lock, flags);
        musb_platform_disable(musb);
        musb_generic_disable(musb);
@@ -1827,8 +1830,6 @@ static void musb_free(struct musb *musb)
        sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
 #endif
 
-       musb_gadget_cleanup(musb);
-
        if (musb->nIrq >= 0) {
                if (musb->irq_wake)
                        disable_irq_wake(musb->nIrq);
index e61aa95f2d2aa0a1c1b4818dc8b41f62239a6aa4..1d5eda26fbd13baf97fcb98bac8c5d9b74acc097 100644 (file)
@@ -39,7 +39,8 @@
 
 #if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
        && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
-       && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN)
+       && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \
+       && !defined(CONFIG_MIPS)
 static inline void readsl(const void __iomem *addr, void *buf, int len)
        { insl((unsigned long)addr, buf, len); }
 static inline void readsw(const void __iomem *addr, void *buf, int len)
index c27bbbf32b522376d51c5b089d96508680c0e2bf..df719eae3b033a23431fbdb164b2e435b222487c 100644 (file)
@@ -222,7 +222,6 @@ static inline void omap2430_low_level_init(struct musb *musb)
        musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 }
 
-/* blocking notifier support */
 static int musb_otg_notifications(struct notifier_block *nb,
                unsigned long event, void *unused)
 {
@@ -231,7 +230,7 @@ static int musb_otg_notifications(struct notifier_block *nb,
        musb->xceiv_event = event;
        schedule_work(&musb->otg_notifier_work);
 
-       return 0;
+       return NOTIFY_OK;
 }
 
 static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
@@ -386,6 +385,7 @@ static void omap2430_musb_disable(struct musb *musb)
 static int omap2430_musb_exit(struct musb *musb)
 {
        del_timer_sync(&musb_idle_timer);
+       cancel_work_sync(&musb->otg_notifier_work);
 
        omap2430_low_level_exit(musb);
        otg_put_transceiver(musb->xceiv);
index a163632877afa5a0a68fdbeb297c721ef2308273..97cb45916c4351110e3a21fb2613c2954855ee9b 100644 (file)
@@ -84,7 +84,7 @@ static bool ux500_configure_channel(struct dma_channel *channel,
        struct musb_hw_ep *hw_ep = ux500_channel->hw_ep;
        struct dma_chan *dma_chan = ux500_channel->dma_chan;
        struct dma_async_tx_descriptor *dma_desc;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        struct scatterlist sg;
        struct dma_slave_config slave_conf;
        enum dma_slave_buswidth addr_width;
@@ -104,7 +104,7 @@ static bool ux500_configure_channel(struct dma_channel *channel,
        sg_dma_address(&sg) = dma_addr;
        sg_dma_len(&sg) = len;
 
-       direction = ux500_channel->is_tx ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       direction = ux500_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
        addr_width = (len & 0x3) ? DMA_SLAVE_BUSWIDTH_1_BYTE :
                                        DMA_SLAVE_BUSWIDTH_4_BYTES;
 
index 2a25955881fc77cb2ac97cb6d182b628aecedda7..735ef4c2339ae9a69c51a87e09bc5ddf68aefa30 100644 (file)
@@ -86,20 +86,6 @@ config NOP_USB_XCEIV
          built-in with usb ip or which are autonomous and doesn't require any
          phy programming such as ISP1x04 etc.
 
-config USB_LANGWELL_OTG
-       tristate "Intel Langwell USB OTG dual-role support"
-       depends on USB && PCI && INTEL_SCU_IPC
-       select USB_OTG
-       select USB_OTG_UTILS
-       help
-         Say Y here if you want to build Intel Langwell USB OTG
-         transciever driver in kernel. This driver implements role
-         switch between EHCI host driver and Langwell USB OTG
-         client driver.
-
-         To compile this driver as a module, choose M here: the
-         module will be called langwell_otg.
-
 config USB_MSM_OTG
        tristate "OTG support for Qualcomm on-chip USB controller"
        depends on (USB || USB_GADGET) && ARCH_MSM
@@ -124,7 +110,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2
+       depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND
        select USB_OTG
        select USB_OTG_UTILS
        help
@@ -132,7 +118,7 @@ config FSL_USB2_OTG
 
 config USB_MV_OTG
        tristate "Marvell USB OTG support"
-       depends on USB_MV_UDC
+       depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
        select USB_OTG
        select USB_OTG_UTILS
        help
index b2c5a9598637d98bb5d7e40e74145d33b7a20bea..41aa5098b139973a4b7e961b7227d2718690eb05 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_USB_GPIO_VBUS)   += gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)      += twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)      += twl6030-usb.o
-obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)    += nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)         += ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)        += ulpi_viewport.o
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
deleted file mode 100644 (file)
index f08f784..0000000
+++ /dev/null
@@ -1,2347 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/* This driver helps to switch Langwell OTG controller function between host
- * and peripheral. It works with EHCI driver and Langwell client controller
- * driver together.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/hcd.h>
-#include <linux/notifier.h>
-#include <linux/delay.h>
-#include <asm/intel_scu_ipc.h>
-
-#include <linux/usb/langwell_otg.h>
-
-#define        DRIVER_DESC             "Intel Langwell USB OTG transceiver driver"
-#define        DRIVER_VERSION          "July 10, 2010"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "langwell_otg";
-
-static int langwell_otg_probe(struct pci_dev *pdev,
-                       const struct pci_device_id *id);
-static void langwell_otg_remove(struct pci_dev *pdev);
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
-static int langwell_otg_resume(struct pci_dev *pdev);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
-                               struct usb_bus *host);
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
-                               struct usb_gadget *gadget);
-static int langwell_otg_start_srp(struct otg_transceiver *otg);
-
-static const struct pci_device_id pci_ids[] = {{
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       0x8086,
-       .device =       0x0811,
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-static struct pci_driver otg_pci_driver = {
-       .name =         (char *) driver_name,
-       .id_table =     pci_ids,
-
-       .probe =        langwell_otg_probe,
-       .remove =       langwell_otg_remove,
-
-       .suspend =      langwell_otg_suspend,
-       .resume =       langwell_otg_resume,
-};
-
-/* HSM timers */
-static inline struct langwell_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
-       struct langwell_otg_timer *timer;
-       timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
-       if (timer == NULL)
-               return timer;
-
-       timer->function = function;
-       timer->expires = expires;
-       timer->data = data;
-       return timer;
-}
-
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
-       *b_se0_srp_tmr, *b_srp_init_tmr;
-
-static struct list_head active_timers;
-
-static struct langwell_otg *the_transceiver;
-
-/* host/client notify transceiver when event affects HNP state */
-void langwell_update_transceiver(void)
-{
-       struct langwell_otg *lnw = the_transceiver;
-
-       dev_dbg(lnw->dev, "transceiver is updated\n");
-
-       if (!lnw->qwork)
-               return ;
-
-       queue_work(lnw->qwork, &lnw->work);
-}
-EXPORT_SYMBOL(langwell_update_transceiver);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
-                                       struct usb_bus *host)
-{
-       otg->host = host;
-
-       return 0;
-}
-
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
-                                       struct usb_gadget *gadget)
-{
-       otg->gadget = gadget;
-
-       return 0;
-}
-
-static int langwell_otg_set_power(struct otg_transceiver *otg,
-                               unsigned mA)
-{
-       return 0;
-}
-
-/* A-device drives vbus, controlled through IPC commands */
-static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       u8                              sub_id;
-
-       dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off");
-
-       if (enabled)
-               sub_id = 0x8; /* Turn on the VBus */
-       else
-               sub_id = 0x9; /* Turn off the VBus */
-
-       if (intel_scu_ipc_simple_command(0xef, sub_id)) {
-               dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n");
-               return -EBUSY;
-       }
-
-       dev_dbg(lnw->dev, "%s --->\n", __func__);
-
-       return 0;
-}
-
-/* charge vbus or discharge vbus through a resistor to ground */
-static void langwell_otg_chrg_vbus(int on)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       u32     val;
-
-       val = readl(lnw->iotg.base + CI_OTGSC);
-
-       if (on)
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
-                               lnw->iotg.base + CI_OTGSC);
-       else
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
-                               lnw->iotg.base + CI_OTGSC);
-}
-
-/* Start SRP */
-static int langwell_otg_start_srp(struct otg_transceiver *otg)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             val;
-
-       dev_dbg(lnw->dev, "%s --->\n", __func__);
-
-       val = readl(iotg->base + CI_OTGSC);
-
-       writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
-                               iotg->base + CI_OTGSC);
-
-       /* Check if the data plus is finished or not */
-       msleep(8);
-       val = readl(iotg->base + CI_OTGSC);
-       if (val & (OTGSC_HADP | OTGSC_DP))
-               dev_dbg(lnw->dev, "DataLine SRP Error\n");
-
-       /* Disable interrupt - b_sess_vld */
-       val = readl(iotg->base + CI_OTGSC);
-       val &= (~(OTGSC_BSVIE | OTGSC_BSEIE));
-       writel(val, iotg->base + CI_OTGSC);
-
-       /* Start VBus SRP, drive vbus to generate VBus pulse */
-       iotg->otg.set_vbus(&iotg->otg, true);
-       msleep(15);
-       iotg->otg.set_vbus(&iotg->otg, false);
-
-       /* Enable interrupt - b_sess_vld*/
-       val = readl(iotg->base + CI_OTGSC);
-       dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val);
-
-       val |= (OTGSC_BSVIE | OTGSC_BSEIE);
-       writel(val, iotg->base + CI_OTGSC);
-
-       /* If Vbus is valid, then update the hsm */
-       if (val & OTGSC_BSV) {
-               dev_dbg(lnw->dev, "no b_sess_vld interrupt\n");
-
-               lnw->iotg.hsm.b_sess_vld = 1;
-               langwell_update_transceiver();
-       }
-
-       dev_dbg(lnw->dev, "%s <---\n", __func__);
-       return 0;
-}
-
-/* stop SOF via bus_suspend */
-static void langwell_otg_loc_sof(int on)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       struct usb_hcd          *hcd;
-       int                     err;
-
-       dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume");
-
-       hcd = bus_to_hcd(lnw->iotg.otg.host);
-       if (on)
-               err = hcd->driver->bus_resume(hcd);
-       else
-               err = hcd->driver->bus_suspend(hcd);
-
-       if (err)
-               dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err);
-
-       dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_otgsc(void)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       u32                             otgsc, usbcfg;
-
-       dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n");
-
-       otgsc = readl(lnw->iotg.base + CI_OTGSC);
-       usbcfg = readl(lnw->usbcfg);
-
-       dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n",
-                                       otgsc, usbcfg);
-       dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV));
-       dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n",
-                                       !!(usbcfg & USBCFG_VBUSVAL));
-       dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV));
-       dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n",
-                                       !!(usbcfg & USBCFG_AVALID));
-       dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV));
-       dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n",
-                                       !!(usbcfg & USBCFG_BVALID));
-       dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE));
-       dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n",
-                                       !!(usbcfg & USBCFG_SESEND));
-
-       /* Check USBCFG VBusValid/AValid/BValid/SessEnd */
-       if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) {
-               dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n");
-               goto err;
-       }
-       if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) {
-               dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n");
-               goto err;
-       }
-       if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) {
-               dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n");
-               goto err;
-       }
-       if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) {
-               dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n");
-               goto err;
-       }
-
-       dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n");
-
-       return 0;
-
-err:
-       dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n");
-       return -EPIPE;
-}
-
-
-static void langwell_otg_phy_low_power(int on)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u8                              val, phcd;
-       int                             retval;
-
-       dev_dbg(lnw->dev, "%s ---> %s mode\n",
-                       __func__, on ? "Low power" : "Normal");
-
-       phcd = 0x40;
-
-       val = readb(iotg->base + CI_HOSTPC1 + 2);
-
-       if (on) {
-               /* Due to hardware issue, after set PHCD, sync will failed
-                * between USBCFG and OTGSC, so before set PHCD, check if
-                * sync is in process now. If the answer is "yes", then do
-                * not touch PHCD bit */
-               retval = langwell_otg_check_otgsc();
-               if (retval) {
-                       dev_dbg(lnw->dev, "Skip PHCD programming..\n");
-                       return ;
-               }
-
-               writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2);
-       } else
-               writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2);
-
-       dev_dbg(lnw->dev, "%s <--- done\n", __func__);
-}
-
-/* After drv vbus, add 5 ms delay to set PHCD */
-static void langwell_otg_phy_low_power_wait(int on)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-
-       dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n");
-
-       mdelay(5);
-       langwell_otg_phy_low_power(on);
-}
-
-/* Enable/Disable OTG interrupt */
-static void langwell_otg_intr(int on)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             val;
-
-       dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
-       val = readl(iotg->base + CI_OTGSC);
-
-       /* OTGSC_INT_MASK doesn't contains 1msInt */
-       if (on) {
-               val = val | (OTGSC_INT_MASK);
-               writel(val, iotg->base + CI_OTGSC);
-       } else {
-               val = val & ~(OTGSC_INT_MASK);
-               writel(val, iotg->base + CI_OTGSC);
-       }
-
-       dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HAAR: Hardware Assist Auto-Reset */
-static void langwell_otg_HAAR(int on)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             val;
-
-       dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
-       val = readl(iotg->base + CI_OTGSC);
-       if (on)
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
-                                       iotg->base + CI_OTGSC);
-       else
-               writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
-                                       iotg->base + CI_OTGSC);
-
-       dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HABA: Hardware Assist B-Disconnect to A-Connect */
-static void langwell_otg_HABA(int on)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             val;
-
-       dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
-       val = readl(iotg->base + CI_OTGSC);
-       if (on)
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
-                                       iotg->base + CI_OTGSC);
-       else
-               writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
-                                       iotg->base + CI_OTGSC);
-
-       dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_se0_srp(int on)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       int                     delay_time = TB_SE0_SRP * 10;
-       u32                     val;
-
-       dev_dbg(lnw->dev, "%s --->\n", __func__);
-
-       do {
-               udelay(100);
-               if (!delay_time--)
-                       break;
-               val = readl(lnw->iotg.base + CI_PORTSC1);
-               val &= PORTSC_LS;
-       } while (!val);
-
-       dev_dbg(lnw->dev, "%s <---\n", __func__);
-       return val;
-}
-
-/* The timeout callback function to set time out bit */
-static void set_tmout(unsigned long indicator)
-{
-       *(int *)indicator = 1;
-}
-
-void langwell_otg_nsf_msg(unsigned long indicator)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-
-       switch (indicator) {
-       case 2:
-       case 4:
-       case 6:
-       case 7:
-               dev_warn(lnw->dev,
-                       "OTG:NSF-%lu - deivce not responding\n", indicator);
-               break;
-       case 3:
-               dev_warn(lnw->dev,
-                       "OTG:NSF-%lu - deivce not supported\n", indicator);
-               break;
-       default:
-               dev_warn(lnw->dev, "Do not have this kind of NSF\n");
-               break;
-       }
-}
-
-/* Initialize timers */
-static int langwell_otg_init_timers(struct otg_hsm *hsm)
-{
-       /* HSM used timers */
-       a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
-                               (unsigned long)&hsm->a_wait_vrise_tmout);
-       if (a_wait_vrise_tmr == NULL)
-               return -ENOMEM;
-       a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
-                               (unsigned long)&hsm->a_aidl_bdis_tmout);
-       if (a_aidl_bdis_tmr == NULL)
-               return -ENOMEM;
-       b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
-                               (unsigned long)&hsm->b_se0_srp);
-       if (b_se0_srp_tmr == NULL)
-               return -ENOMEM;
-       b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
-                               (unsigned long)&hsm->b_srp_init_tmout);
-       if (b_srp_init_tmr == NULL)
-               return -ENOMEM;
-
-       return 0;
-}
-
-/* Free timers */
-static void langwell_otg_free_timers(void)
-{
-       kfree(a_wait_vrise_tmr);
-       kfree(a_aidl_bdis_tmr);
-       kfree(b_se0_srp_tmr);
-       kfree(b_srp_init_tmr);
-}
-
-/* The timeout callback function to set time out bit */
-static void langwell_otg_timer_fn(unsigned long indicator)
-{
-       struct langwell_otg *lnw = the_transceiver;
-
-       *(int *)indicator = 1;
-
-       dev_dbg(lnw->dev, "kernel timer - timeout\n");
-
-       langwell_update_transceiver();
-}
-
-/* kernel timer used instead of HW based interrupt */
-static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       unsigned long           j = jiffies;
-       unsigned long           data, time;
-
-       switch (timers) {
-       case TA_WAIT_VRISE_TMR:
-               iotg->hsm.a_wait_vrise_tmout = 0;
-               data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout;
-               time = TA_WAIT_VRISE;
-               break;
-       case TA_WAIT_BCON_TMR:
-               iotg->hsm.a_wait_bcon_tmout = 0;
-               data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout;
-               time = TA_WAIT_BCON;
-               break;
-       case TA_AIDL_BDIS_TMR:
-               iotg->hsm.a_aidl_bdis_tmout = 0;
-               data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout;
-               time = TA_AIDL_BDIS;
-               break;
-       case TB_ASE0_BRST_TMR:
-               iotg->hsm.b_ase0_brst_tmout = 0;
-               data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout;
-               time = TB_ASE0_BRST;
-               break;
-       case TB_SRP_INIT_TMR:
-               iotg->hsm.b_srp_init_tmout = 0;
-               data = (unsigned long)&iotg->hsm.b_srp_init_tmout;
-               time = TB_SRP_INIT;
-               break;
-       case TB_SRP_FAIL_TMR:
-               iotg->hsm.b_srp_fail_tmout = 0;
-               data = (unsigned long)&iotg->hsm.b_srp_fail_tmout;
-               time = TB_SRP_FAIL;
-               break;
-       case TB_BUS_SUSPEND_TMR:
-               iotg->hsm.b_bus_suspend_tmout = 0;
-               data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout;
-               time = TB_BUS_SUSPEND;
-               break;
-       default:
-               dev_dbg(lnw->dev, "unknown timer, cannot enable it\n");
-               return;
-       }
-
-       lnw->hsm_timer.data = data;
-       lnw->hsm_timer.function = langwell_otg_timer_fn;
-       lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
-
-       add_timer(&lnw->hsm_timer);
-
-       dev_dbg(lnw->dev, "add timer successfully\n");
-}
-
-/* Add timer to timer list */
-static void langwell_otg_add_timer(void *gtimer)
-{
-       struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
-       struct langwell_otg_timer *tmp_timer;
-       struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg;
-       u32     val32;
-
-       /* Check if the timer is already in the active list,
-        * if so update timer count
-        */
-       list_for_each_entry(tmp_timer, &active_timers, list)
-               if (tmp_timer == timer) {
-                       timer->count = timer->expires;
-                       return;
-               }
-       timer->count = timer->expires;
-
-       if (list_empty(&active_timers)) {
-               val32 = readl(iotg->base + CI_OTGSC);
-               writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC);
-       }
-
-       list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-static void langwell_otg_del_timer(void *gtimer)
-{
-       struct langwell_otg *lnw = the_transceiver;
-       struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
-       struct langwell_otg_timer *tmp_timer, *del_tmp;
-       u32 val32;
-
-       list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
-               if (tmp_timer == timer)
-                       list_del(&timer->list);
-
-       if (list_empty(&active_timers)) {
-               val32 = readl(lnw->iotg.base + CI_OTGSC);
-               writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC);
-       }
-}
-
-/* Reduce timer count by 1, and find timeout conditions.*/
-static int langwell_otg_tick_timer(u32 *int_sts)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       struct langwell_otg_timer *tmp_timer, *del_tmp;
-       int expired = 0;
-
-       list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
-               tmp_timer->count--;
-               /* check if timer expires */
-               if (!tmp_timer->count) {
-                       list_del(&tmp_timer->list);
-                       tmp_timer->function(tmp_timer->data);
-                       expired = 1;
-               }
-       }
-
-       if (list_empty(&active_timers)) {
-               dev_dbg(lnw->dev, "tick timer: disable 1ms int\n");
-               *int_sts = *int_sts & ~OTGSC_1MSE;
-       }
-       return expired;
-}
-
-static void reset_otg(void)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       int                     delay_time = 1000;
-       u32                     val;
-
-       dev_dbg(lnw->dev, "reseting OTG controller ...\n");
-       val = readl(lnw->iotg.base + CI_USBCMD);
-       writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD);
-       do {
-               udelay(100);
-               if (!delay_time--)
-                       dev_dbg(lnw->dev, "reset timeout\n");
-               val = readl(lnw->iotg.base + CI_USBCMD);
-               val &= USBCMD_RST;
-       } while (val != 0);
-       dev_dbg(lnw->dev, "reset done.\n");
-}
-
-static void set_host_mode(void)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       u32                     val;
-
-       reset_otg();
-       val = readl(lnw->iotg.base + CI_USBMODE);
-       val = (val & (~USBMODE_CM)) | USBMODE_HOST;
-       writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void set_client_mode(void)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       u32                     val;
-
-       reset_otg();
-       val = readl(lnw->iotg.base + CI_USBMODE);
-       val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
-       writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void init_hsm(void)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             val32;
-
-       /* read OTGSC after reset */
-       val32 = readl(lnw->iotg.base + CI_OTGSC);
-       dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32);
-
-       /* set init state */
-       if (val32 & OTGSC_ID) {
-               iotg->hsm.id = 1;
-               iotg->otg.default_a = 0;
-               set_client_mode();
-               iotg->otg.state = OTG_STATE_B_IDLE;
-       } else {
-               iotg->hsm.id = 0;
-               iotg->otg.default_a = 1;
-               set_host_mode();
-               iotg->otg.state = OTG_STATE_A_IDLE;
-       }
-
-       /* set session indicator */
-       if (val32 & OTGSC_BSE)
-               iotg->hsm.b_sess_end = 1;
-       if (val32 & OTGSC_BSV)
-               iotg->hsm.b_sess_vld = 1;
-       if (val32 & OTGSC_ASV)
-               iotg->hsm.a_sess_vld = 1;
-       if (val32 & OTGSC_AVV)
-               iotg->hsm.a_vbus_vld = 1;
-
-       /* defautly power the bus */
-       iotg->hsm.a_bus_req = 1;
-       iotg->hsm.a_bus_drop = 0;
-       /* defautly don't request bus as B device */
-       iotg->hsm.b_bus_req = 0;
-       /* no system error */
-       iotg->hsm.a_clr_err = 0;
-
-       langwell_otg_phy_low_power_wait(1);
-}
-
-static void update_hsm(void)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             val32;
-
-       /* read OTGSC */
-       val32 = readl(lnw->iotg.base + CI_OTGSC);
-       dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32);
-
-       iotg->hsm.id = !!(val32 & OTGSC_ID);
-       iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE);
-       iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV);
-       iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV);
-       iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV);
-}
-
-static irqreturn_t otg_dummy_irq(int irq, void *_dev)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       void __iomem            *reg_base = _dev;
-       u32                     val;
-       u32                     int_mask = 0;
-
-       val = readl(reg_base + CI_USBMODE);
-       if ((val & USBMODE_CM) != USBMODE_DEVICE)
-               return IRQ_NONE;
-
-       val = readl(reg_base + CI_USBSTS);
-       int_mask = val & INTR_DUMMY_MASK;
-
-       if (int_mask == 0)
-               return IRQ_NONE;
-
-       /* clear hsm.b_conn here since host driver can't detect it
-       *  otg_dummy_irq called means B-disconnect happened.
-       */
-       if (lnw->iotg.hsm.b_conn) {
-               lnw->iotg.hsm.b_conn = 0;
-               if (spin_trylock(&lnw->wq_lock)) {
-                       langwell_update_transceiver();
-                       spin_unlock(&lnw->wq_lock);
-               }
-       }
-
-       /* Clear interrupts */
-       writel(int_mask, reg_base + CI_USBSTS);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t otg_irq(int irq, void *_dev)
-{
-       struct langwell_otg             *lnw = _dev;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       u32                             int_sts, int_en;
-       u32                             int_mask = 0;
-       int                             flag = 0;
-
-       int_sts = readl(lnw->iotg.base + CI_OTGSC);
-       int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
-       int_mask = int_sts & int_en;
-       if (int_mask == 0)
-               return IRQ_NONE;
-
-       if (int_mask & OTGSC_IDIS) {
-               dev_dbg(lnw->dev, "%s: id change int\n", __func__);
-               iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
-               dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id);
-               flag = 1;
-       }
-       if (int_mask & OTGSC_DPIS) {
-               dev_dbg(lnw->dev, "%s: data pulse int\n", __func__);
-               iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
-               dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det);
-               flag = 1;
-       }
-       if (int_mask & OTGSC_BSEIS) {
-               dev_dbg(lnw->dev, "%s: b session end int\n", __func__);
-               iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
-               dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end);
-               flag = 1;
-       }
-       if (int_mask & OTGSC_BSVIS) {
-               dev_dbg(lnw->dev, "%s: b session valid int\n", __func__);
-               iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
-               dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end);
-               flag = 1;
-       }
-       if (int_mask & OTGSC_ASVIS) {
-               dev_dbg(lnw->dev, "%s: a session valid int\n", __func__);
-               iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
-               dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld);
-               flag = 1;
-       }
-       if (int_mask & OTGSC_AVVIS) {
-               dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__);
-               iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
-               dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld);
-               flag = 1;
-       }
-
-       if (int_mask & OTGSC_1MSS) {
-               /* need to schedule otg_work if any timer is expired */
-               if (langwell_otg_tick_timer(&int_sts))
-                       flag = 1;
-       }
-
-       writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
-                                       lnw->iotg.base + CI_OTGSC);
-       if (flag)
-               langwell_update_transceiver();
-
-       return IRQ_HANDLED;
-}
-
-static int langwell_otg_iotg_notify(struct notifier_block *nb,
-                               unsigned long action, void *data)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = data;
-       int                             flag = 0;
-
-       if (iotg == NULL)
-               return NOTIFY_BAD;
-
-       if (lnw == NULL)
-               return NOTIFY_BAD;
-
-       switch (action) {
-       case MID_OTG_NOTIFY_CONNECT:
-               dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n");
-               if (iotg->otg.default_a == 1)
-                       iotg->hsm.b_conn = 1;
-               else
-                       iotg->hsm.a_conn = 1;
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_DISCONN:
-               dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n");
-               if (iotg->otg.default_a == 1)
-                       iotg->hsm.b_conn = 0;
-               else
-                       iotg->hsm.a_conn = 0;
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_HSUSPEND:
-               dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n");
-               if (iotg->otg.default_a == 1)
-                       iotg->hsm.a_suspend_req = 1;
-               else
-                       iotg->hsm.b_bus_req = 0;
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_HRESUME:
-               dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n");
-               if (iotg->otg.default_a == 1)
-                       iotg->hsm.b_bus_resume = 1;
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_CSUSPEND:
-               dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n");
-               if (iotg->otg.default_a == 1) {
-                       if (iotg->hsm.b_bus_suspend_vld == 2) {
-                               iotg->hsm.b_bus_suspend = 1;
-                               iotg->hsm.b_bus_suspend_vld = 0;
-                               flag = 1;
-                       } else {
-                               iotg->hsm.b_bus_suspend_vld++;
-                               flag = 0;
-                       }
-               } else {
-                       if (iotg->hsm.a_bus_suspend == 0) {
-                               iotg->hsm.a_bus_suspend = 1;
-                               flag = 1;
-                       }
-               }
-               break;
-       case MID_OTG_NOTIFY_CRESUME:
-               dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n");
-               if (iotg->otg.default_a == 0)
-                       iotg->hsm.a_bus_suspend = 0;
-               flag = 0;
-               break;
-       case MID_OTG_NOTIFY_HOSTADD:
-               dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n");
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_HOSTREMOVE:
-               dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n");
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_CLIENTADD:
-               dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n");
-               flag = 1;
-               break;
-       case MID_OTG_NOTIFY_CLIENTREMOVE:
-               dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n");
-               flag = 1;
-               break;
-       default:
-               dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n");
-               return NOTIFY_DONE;
-       }
-
-       if (flag)
-               langwell_update_transceiver();
-
-       return NOTIFY_OK;
-}
-
-static void langwell_otg_work(struct work_struct *work)
-{
-       struct langwell_otg             *lnw;
-       struct intel_mid_otg_xceiv      *iotg;
-       int                             retval;
-       struct pci_dev                  *pdev;
-
-       lnw = container_of(work, struct langwell_otg, work);
-       iotg = &lnw->iotg;
-       pdev = to_pci_dev(lnw->dev);
-
-       dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
-                       otg_state_string(iotg->otg.state));
-
-       switch (iotg->otg.state) {
-       case OTG_STATE_UNDEFINED:
-       case OTG_STATE_B_IDLE:
-               if (!iotg->hsm.id) {
-                       langwell_otg_del_timer(b_srp_init_tmr);
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       iotg->otg.default_a = 1;
-                       iotg->hsm.a_srp_det = 0;
-
-                       langwell_otg_chrg_vbus(0);
-                       set_host_mode();
-                       langwell_otg_phy_low_power(1);
-
-                       iotg->otg.state = OTG_STATE_A_IDLE;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.b_sess_vld) {
-                       langwell_otg_del_timer(b_srp_init_tmr);
-                       del_timer_sync(&lnw->hsm_timer);
-                       iotg->hsm.b_sess_end = 0;
-                       iotg->hsm.a_bus_suspend = 0;
-                       langwell_otg_chrg_vbus(0);
-
-                       if (lnw->iotg.start_peripheral) {
-                               lnw->iotg.start_peripheral(&lnw->iotg);
-                               iotg->otg.state = OTG_STATE_B_PERIPHERAL;
-                       } else
-                               dev_dbg(lnw->dev, "client driver not loaded\n");
-
-               } else if (iotg->hsm.b_srp_init_tmout) {
-                       iotg->hsm.b_srp_init_tmout = 0;
-                       dev_warn(lnw->dev, "SRP init timeout\n");
-               } else if (iotg->hsm.b_srp_fail_tmout) {
-                       iotg->hsm.b_srp_fail_tmout = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       /* No silence failure */
-                       langwell_otg_nsf_msg(6);
-               } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
-                       del_timer_sync(&lnw->hsm_timer);
-                       /* workaround for b_se0_srp detection */
-                       retval = langwell_otg_check_se0_srp(0);
-                       if (retval) {
-                               iotg->hsm.b_bus_req = 0;
-                               dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
-                       } else {
-                               /* clear the PHCD before start srp */
-                               langwell_otg_phy_low_power(0);
-
-                               /* Start SRP */
-                               langwell_otg_add_timer(b_srp_init_tmr);
-                               iotg->otg.start_srp(&iotg->otg);
-                               langwell_otg_del_timer(b_srp_init_tmr);
-                               langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
-
-                               /* reset PHY low power mode here */
-                               langwell_otg_phy_low_power_wait(1);
-                       }
-               }
-               break;
-       case OTG_STATE_B_SRP_INIT:
-               if (!iotg->hsm.id) {
-                       iotg->otg.default_a = 1;
-                       iotg->hsm.a_srp_det = 0;
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       langwell_otg_chrg_vbus(0);
-                       set_host_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_A_IDLE;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.b_sess_vld) {
-                       langwell_otg_chrg_vbus(0);
-                       if (lnw->iotg.start_peripheral) {
-                               lnw->iotg.start_peripheral(&lnw->iotg);
-                               iotg->otg.state = OTG_STATE_B_PERIPHERAL;
-                       } else
-                               dev_dbg(lnw->dev, "client driver not loaded\n");
-               }
-               break;
-       case OTG_STATE_B_PERIPHERAL:
-               if (!iotg->hsm.id) {
-                       iotg->otg.default_a = 1;
-                       iotg->hsm.a_srp_det = 0;
-
-                       langwell_otg_chrg_vbus(0);
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       set_host_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_A_IDLE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.b_sess_vld) {
-                       iotg->hsm.b_hnp_enable = 0;
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-               } else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
-                                       iotg->otg.gadget->b_hnp_enable &&
-                                       iotg->hsm.a_bus_suspend) {
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       langwell_otg_HAAR(1);
-                       iotg->hsm.a_conn = 0;
-
-                       if (lnw->iotg.start_host) {
-                               lnw->iotg.start_host(&lnw->iotg);
-                               iotg->otg.state = OTG_STATE_B_WAIT_ACON;
-                       } else
-                               dev_dbg(lnw->dev,
-                                               "host driver not loaded.\n");
-
-                       iotg->hsm.a_bus_resume = 0;
-                       langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
-               }
-               break;
-
-       case OTG_STATE_B_WAIT_ACON:
-               if (!iotg->hsm.id) {
-                       /* delete hsm timer for b_ase0_brst_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       iotg->otg.default_a = 1;
-                       iotg->hsm.a_srp_det = 0;
-
-                       langwell_otg_chrg_vbus(0);
-
-                       langwell_otg_HAAR(0);
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       set_host_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_A_IDLE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.b_sess_vld) {
-                       /* delete hsm timer for b_ase0_brst_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       iotg->hsm.b_hnp_enable = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       langwell_otg_chrg_vbus(0);
-                       langwell_otg_HAAR(0);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       set_client_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-               } else if (iotg->hsm.a_conn) {
-                       /* delete hsm timer for b_ase0_brst_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       langwell_otg_HAAR(0);
-                       iotg->otg.state = OTG_STATE_B_HOST;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.a_bus_resume ||
-                               iotg->hsm.b_ase0_brst_tmout) {
-                       /* delete hsm timer for b_ase0_brst_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       langwell_otg_HAAR(0);
-                       langwell_otg_nsf_msg(7);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       iotg->hsm.a_bus_suspend = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       if (lnw->iotg.start_peripheral)
-                               lnw->iotg.start_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver not loaded.\n");
-
-                       iotg->otg.state = OTG_STATE_B_PERIPHERAL;
-               }
-               break;
-
-       case OTG_STATE_B_HOST:
-               if (!iotg->hsm.id) {
-                       iotg->otg.default_a = 1;
-                       iotg->hsm.a_srp_det = 0;
-
-                       langwell_otg_chrg_vbus(0);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       set_host_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_A_IDLE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.b_sess_vld) {
-                       iotg->hsm.b_hnp_enable = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       langwell_otg_chrg_vbus(0);
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       set_client_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-               } else if ((!iotg->hsm.b_bus_req) ||
-                               (!iotg->hsm.a_conn)) {
-                       iotg->hsm.b_bus_req = 0;
-                       langwell_otg_loc_sof(0);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       iotg->hsm.a_bus_suspend = 0;
-
-                       if (lnw->iotg.start_peripheral)
-                               lnw->iotg.start_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                               "client driver not loaded.\n");
-
-                       iotg->otg.state = OTG_STATE_B_PERIPHERAL;
-               }
-               break;
-
-       case OTG_STATE_A_IDLE:
-               iotg->otg.default_a = 1;
-               if (iotg->hsm.id) {
-                       iotg->otg.default_a = 0;
-                       iotg->hsm.b_bus_req = 0;
-                       iotg->hsm.vbus_srp_up = 0;
-
-                       langwell_otg_chrg_vbus(0);
-                       set_client_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.a_bus_drop &&
-                       (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
-                       langwell_otg_phy_low_power(0);
-
-                       /* Turn on VBus */
-                       iotg->otg.set_vbus(&iotg->otg, true);
-
-                       iotg->hsm.vbus_srp_up = 0;
-                       iotg->hsm.a_wait_vrise_tmout = 0;
-                       langwell_otg_add_timer(a_wait_vrise_tmr);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
-                       iotg->hsm.vbus_srp_up = 1;
-               } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
-                       msleep(10);
-                       langwell_otg_phy_low_power(0);
-
-                       /* Turn on VBus */
-                       iotg->otg.set_vbus(&iotg->otg, true);
-                       iotg->hsm.a_srp_det = 1;
-                       iotg->hsm.vbus_srp_up = 0;
-                       iotg->hsm.a_wait_vrise_tmout = 0;
-                       langwell_otg_add_timer(a_wait_vrise_tmr);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.a_sess_vld &&
-                               !iotg->hsm.vbus_srp_up) {
-                       langwell_otg_phy_low_power(1);
-               }
-               break;
-       case OTG_STATE_A_WAIT_VRISE:
-               if (iotg->hsm.id) {
-                       langwell_otg_del_timer(a_wait_vrise_tmr);
-                       iotg->hsm.b_bus_req = 0;
-                       iotg->otg.default_a = 0;
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       set_client_mode();
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-               } else if (iotg->hsm.a_vbus_vld) {
-                       langwell_otg_del_timer(a_wait_vrise_tmr);
-                       iotg->hsm.b_conn = 0;
-                       if (lnw->iotg.start_host)
-                               lnw->iotg.start_host(&lnw->iotg);
-                       else {
-                               dev_dbg(lnw->dev, "host driver not loaded.\n");
-                               break;
-                       }
-
-                       langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
-                       iotg->otg.state = OTG_STATE_A_WAIT_BCON;
-               } else if (iotg->hsm.a_wait_vrise_tmout) {
-                       iotg->hsm.b_conn = 0;
-                       if (iotg->hsm.a_vbus_vld) {
-                               if (lnw->iotg.start_host)
-                                       lnw->iotg.start_host(&lnw->iotg);
-                               else {
-                                       dev_dbg(lnw->dev,
-                                               "host driver not loaded.\n");
-                                       break;
-                               }
-                               langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
-                               iotg->otg.state = OTG_STATE_A_WAIT_BCON;
-                       } else {
-
-                               /* Turn off VBus */
-                               iotg->otg.set_vbus(&iotg->otg, false);
-                               langwell_otg_phy_low_power_wait(1);
-                               iotg->otg.state = OTG_STATE_A_VBUS_ERR;
-                       }
-               }
-               break;
-       case OTG_STATE_A_WAIT_BCON:
-               if (iotg->hsm.id) {
-                       /* delete hsm timer for a_wait_bcon_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       iotg->otg.default_a = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       set_client_mode();
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.a_vbus_vld) {
-                       /* delete hsm timer for a_wait_bcon_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_A_VBUS_ERR;
-               } else if (iotg->hsm.a_bus_drop ||
-                               (iotg->hsm.a_wait_bcon_tmout &&
-                               !iotg->hsm.a_bus_req)) {
-                       /* delete hsm timer for a_wait_bcon_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (iotg->hsm.b_conn) {
-                       /* delete hsm timer for a_wait_bcon_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       iotg->hsm.a_suspend_req = 0;
-                       iotg->otg.state = OTG_STATE_A_HOST;
-                       if (iotg->hsm.a_srp_det && iotg->otg.host &&
-                                       !iotg->otg.host->b_hnp_enable) {
-                               /* SRP capable peripheral-only device */
-                               iotg->hsm.a_bus_req = 1;
-                               iotg->hsm.a_srp_det = 0;
-                       } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
-                                       iotg->otg.host->b_hnp_enable) {
-                               /* It is not safe enough to do a fast
-                                * transition from A_WAIT_BCON to
-                                * A_SUSPEND */
-                               msleep(10000);
-                               if (iotg->hsm.a_bus_req)
-                                       break;
-
-                               if (request_irq(pdev->irq,
-                                       otg_dummy_irq, IRQF_SHARED,
-                                       driver_name, iotg->base) != 0) {
-                                       dev_dbg(lnw->dev,
-                                               "request interrupt %d fail\n",
-                                               pdev->irq);
-                               }
-
-                               langwell_otg_HABA(1);
-                               iotg->hsm.b_bus_resume = 0;
-                               iotg->hsm.a_aidl_bdis_tmout = 0;
-
-                               langwell_otg_loc_sof(0);
-                               /* clear PHCD to enable HW timer */
-                               langwell_otg_phy_low_power(0);
-                               langwell_otg_add_timer(a_aidl_bdis_tmr);
-                               iotg->otg.state = OTG_STATE_A_SUSPEND;
-                       } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
-                               !iotg->otg.host->b_hnp_enable) {
-                               if (lnw->iotg.stop_host)
-                                       lnw->iotg.stop_host(&lnw->iotg);
-                               else
-                                       dev_dbg(lnw->dev,
-                                               "host driver removed.\n");
-
-                               /* Turn off VBus */
-                               iotg->otg.set_vbus(&iotg->otg, false);
-                               iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
-                       }
-               }
-               break;
-       case OTG_STATE_A_HOST:
-               if (iotg->hsm.id) {
-                       iotg->otg.default_a = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       set_client_mode();
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.a_bus_drop ||
-                               (iotg->otg.host &&
-                               !iotg->otg.host->b_hnp_enable &&
-                                       !iotg->hsm.a_bus_req)) {
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (!iotg->hsm.a_vbus_vld) {
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_A_VBUS_ERR;
-               } else if (iotg->otg.host &&
-                               iotg->otg.host->b_hnp_enable &&
-                               !iotg->hsm.a_bus_req) {
-                       /* Set HABA to enable hardware assistance to signal
-                        *  A-connect after receiver B-disconnect. Hardware
-                        *  will then set client mode and enable URE, SLE and
-                        *  PCE after the assistance. otg_dummy_irq is used to
-                        *  clean these ints when client driver is not resumed.
-                        */
-                       if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
-                                       driver_name, iotg->base) != 0) {
-                               dev_dbg(lnw->dev,
-                                       "request interrupt %d failed\n",
-                                               pdev->irq);
-                       }
-
-                       /* set HABA */
-                       langwell_otg_HABA(1);
-                       iotg->hsm.b_bus_resume = 0;
-                       iotg->hsm.a_aidl_bdis_tmout = 0;
-                       langwell_otg_loc_sof(0);
-                       /* clear PHCD to enable HW timer */
-                       langwell_otg_phy_low_power(0);
-                       langwell_otg_add_timer(a_aidl_bdis_tmr);
-                       iotg->otg.state = OTG_STATE_A_SUSPEND;
-               } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
-                       langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
-                       iotg->otg.state = OTG_STATE_A_WAIT_BCON;
-               }
-               break;
-       case OTG_STATE_A_SUSPEND:
-               if (iotg->hsm.id) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(pdev->irq, iotg->base);
-                       iotg->otg.default_a = 0;
-                       iotg->hsm.b_bus_req = 0;
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       set_client_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.a_bus_req ||
-                               iotg->hsm.b_bus_resume) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(pdev->irq, iotg->base);
-                       iotg->hsm.a_suspend_req = 0;
-                       langwell_otg_loc_sof(1);
-                       iotg->otg.state = OTG_STATE_A_HOST;
-               } else if (iotg->hsm.a_aidl_bdis_tmout ||
-                               iotg->hsm.a_bus_drop) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(pdev->irq, iotg->base);
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (!iotg->hsm.b_conn && iotg->otg.host &&
-                               iotg->otg.host->b_hnp_enable) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(pdev->irq, iotg->base);
-
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       iotg->hsm.b_bus_suspend = 0;
-                       iotg->hsm.b_bus_suspend_vld = 0;
-
-                       /* msleep(200); */
-                       if (lnw->iotg.start_peripheral)
-                               lnw->iotg.start_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver not loaded.\n");
-
-                       langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
-                       iotg->otg.state = OTG_STATE_A_PERIPHERAL;
-                       break;
-               } else if (!iotg->hsm.a_vbus_vld) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(pdev->irq, iotg->base);
-                       if (lnw->iotg.stop_host)
-                               lnw->iotg.stop_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "host driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_A_VBUS_ERR;
-               }
-               break;
-       case OTG_STATE_A_PERIPHERAL:
-               if (iotg->hsm.id) {
-                       /* delete hsm timer for b_bus_suspend_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-                       iotg->otg.default_a = 0;
-                       iotg->hsm.b_bus_req = 0;
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       set_client_mode();
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (!iotg->hsm.a_vbus_vld) {
-                       /* delete hsm timer for b_bus_suspend_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       langwell_otg_phy_low_power_wait(1);
-                       iotg->otg.state = OTG_STATE_A_VBUS_ERR;
-               } else if (iotg->hsm.a_bus_drop) {
-                       /* delete hsm timer for b_bus_suspend_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       /* Turn off VBus */
-                       iotg->otg.set_vbus(&iotg->otg, false);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (iotg->hsm.b_bus_suspend) {
-                       /* delete hsm timer for b_bus_suspend_tmr */
-                       del_timer_sync(&lnw->hsm_timer);
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       if (lnw->iotg.start_host)
-                               lnw->iotg.start_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                               "host driver not loaded.\n");
-                       langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
-                       iotg->otg.state = OTG_STATE_A_WAIT_BCON;
-               } else if (iotg->hsm.b_bus_suspend_tmout) {
-                       u32     val;
-                       val = readl(lnw->iotg.base + CI_PORTSC1);
-                       if (!(val & PORTSC_SUSP))
-                               break;
-
-                       if (lnw->iotg.stop_peripheral)
-                               lnw->iotg.stop_peripheral(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                       "client driver has been removed.\n");
-
-                       if (lnw->iotg.start_host)
-                               lnw->iotg.start_host(&lnw->iotg);
-                       else
-                               dev_dbg(lnw->dev,
-                                               "host driver not loaded.\n");
-                       langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
-                       iotg->otg.state = OTG_STATE_A_WAIT_BCON;
-               }
-               break;
-       case OTG_STATE_A_VBUS_ERR:
-               if (iotg->hsm.id) {
-                       iotg->otg.default_a = 0;
-                       iotg->hsm.a_clr_err = 0;
-                       iotg->hsm.a_srp_det = 0;
-                       set_client_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.a_clr_err) {
-                       iotg->hsm.a_clr_err = 0;
-                       iotg->hsm.a_srp_det = 0;
-                       reset_otg();
-                       init_hsm();
-                       if (iotg->otg.state == OTG_STATE_A_IDLE)
-                               langwell_update_transceiver();
-               } else {
-                       /* FW will clear PHCD bit when any VBus
-                        * event detected. Reset PHCD to 1 again */
-                       langwell_otg_phy_low_power(1);
-               }
-               break;
-       case OTG_STATE_A_WAIT_VFALL:
-               if (iotg->hsm.id) {
-                       iotg->otg.default_a = 0;
-                       set_client_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_B_IDLE;
-                       langwell_update_transceiver();
-               } else if (iotg->hsm.a_bus_req) {
-
-                       /* Turn on VBus */
-                       iotg->otg.set_vbus(&iotg->otg, true);
-                       iotg->hsm.a_wait_vrise_tmout = 0;
-                       langwell_otg_add_timer(a_wait_vrise_tmr);
-                       iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
-               } else if (!iotg->hsm.a_sess_vld) {
-                       iotg->hsm.a_srp_det = 0;
-                       set_host_mode();
-                       langwell_otg_phy_low_power(1);
-                       iotg->otg.state = OTG_STATE_A_IDLE;
-               }
-               break;
-       default:
-               ;
-       }
-
-       dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
-                       otg_state_string(iotg->otg.state));
-}
-
-static ssize_t
-show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       char                    *next;
-       unsigned                size, t;
-
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size,
-               "\n"
-               "USBCMD = 0x%08x\n"
-               "USBSTS = 0x%08x\n"
-               "USBINTR = 0x%08x\n"
-               "ASYNCLISTADDR = 0x%08x\n"
-               "PORTSC1 = 0x%08x\n"
-               "HOSTPC1 = 0x%08x\n"
-               "OTGSC = 0x%08x\n"
-               "USBMODE = 0x%08x\n",
-               readl(lnw->iotg.base + 0x30),
-               readl(lnw->iotg.base + 0x34),
-               readl(lnw->iotg.base + 0x38),
-               readl(lnw->iotg.base + 0x48),
-               readl(lnw->iotg.base + 0x74),
-               readl(lnw->iotg.base + 0xb4),
-               readl(lnw->iotg.base + 0xf4),
-               readl(lnw->iotg.base + 0xf8)
-            );
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       char                            *next;
-       unsigned                        size, t;
-
-       next = buf;
-       size = PAGE_SIZE;
-
-       if (iotg->otg.host)
-               iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable;
-
-       if (iotg->otg.gadget)
-               iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable;
-
-       t = scnprintf(next, size,
-               "\n"
-               "current state = %s\n"
-               "a_bus_resume = \t%d\n"
-               "a_bus_suspend = \t%d\n"
-               "a_conn = \t%d\n"
-               "a_sess_vld = \t%d\n"
-               "a_srp_det = \t%d\n"
-               "a_vbus_vld = \t%d\n"
-               "b_bus_resume = \t%d\n"
-               "b_bus_suspend = \t%d\n"
-               "b_conn = \t%d\n"
-               "b_se0_srp = \t%d\n"
-               "b_sess_end = \t%d\n"
-               "b_sess_vld = \t%d\n"
-               "id = \t%d\n"
-               "a_set_b_hnp_en = \t%d\n"
-               "b_srp_done = \t%d\n"
-               "b_hnp_enable = \t%d\n"
-               "a_wait_vrise_tmout = \t%d\n"
-               "a_wait_bcon_tmout = \t%d\n"
-               "a_aidl_bdis_tmout = \t%d\n"
-               "b_ase0_brst_tmout = \t%d\n"
-               "a_bus_drop = \t%d\n"
-               "a_bus_req = \t%d\n"
-               "a_clr_err = \t%d\n"
-               "a_suspend_req = \t%d\n"
-               "b_bus_req = \t%d\n"
-               "b_bus_suspend_tmout = \t%d\n"
-               "b_bus_suspend_vld = \t%d\n",
-               otg_state_string(iotg->otg.state),
-               iotg->hsm.a_bus_resume,
-               iotg->hsm.a_bus_suspend,
-               iotg->hsm.a_conn,
-               iotg->hsm.a_sess_vld,
-               iotg->hsm.a_srp_det,
-               iotg->hsm.a_vbus_vld,
-               iotg->hsm.b_bus_resume,
-               iotg->hsm.b_bus_suspend,
-               iotg->hsm.b_conn,
-               iotg->hsm.b_se0_srp,
-               iotg->hsm.b_sess_end,
-               iotg->hsm.b_sess_vld,
-               iotg->hsm.id,
-               iotg->hsm.a_set_b_hnp_en,
-               iotg->hsm.b_srp_done,
-               iotg->hsm.b_hnp_enable,
-               iotg->hsm.a_wait_vrise_tmout,
-               iotg->hsm.a_wait_bcon_tmout,
-               iotg->hsm.a_aidl_bdis_tmout,
-               iotg->hsm.b_ase0_brst_tmout,
-               iotg->hsm.a_bus_drop,
-               iotg->hsm.a_bus_req,
-               iotg->hsm.a_clr_err,
-               iotg->hsm.a_suspend_req,
-               iotg->hsm.b_bus_req,
-               iotg->hsm.b_bus_suspend_tmout,
-               iotg->hsm.b_bus_suspend_vld
-               );
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       char                    *next;
-       unsigned                size, t;
-
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req);
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-
-       if (!iotg->otg.default_a)
-               return -1;
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '0') {
-               iotg->hsm.a_bus_req = 0;
-               dev_dbg(lnw->dev, "User request: a_bus_req = 0\n");
-       } else if (buf[0] == '1') {
-               /* If a_bus_drop is TRUE, a_bus_req can't be set */
-               if (iotg->hsm.a_bus_drop)
-                       return -1;
-               iotg->hsm.a_bus_req = 1;
-               dev_dbg(lnw->dev, "User request: a_bus_req = 1\n");
-       }
-       if (spin_trylock(&lnw->wq_lock)) {
-               langwell_update_transceiver();
-               spin_unlock(&lnw->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       char                    *next;
-       unsigned                size, t;
-
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop);
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-
-       if (!iotg->otg.default_a)
-               return -1;
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '0') {
-               iotg->hsm.a_bus_drop = 0;
-               dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n");
-       } else if (buf[0] == '1') {
-               iotg->hsm.a_bus_drop = 1;
-               iotg->hsm.a_bus_req = 0;
-               dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n");
-               dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n");
-       }
-       if (spin_trylock(&lnw->wq_lock)) {
-               langwell_update_transceiver();
-               spin_unlock(&lnw->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop);
-
-static ssize_t
-get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       char                    *next;
-       unsigned                size, t;
-
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req);
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_b_bus_req(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-
-       if (iotg->otg.default_a)
-               return -1;
-
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '0') {
-               iotg->hsm.b_bus_req = 0;
-               dev_dbg(lnw->dev, "User request: b_bus_req = 0\n");
-       } else if (buf[0] == '1') {
-               iotg->hsm.b_bus_req = 1;
-               dev_dbg(lnw->dev, "User request: b_bus_req = 1\n");
-       }
-       if (spin_trylock(&lnw->wq_lock)) {
-               langwell_update_transceiver();
-               spin_unlock(&lnw->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-
-       if (!iotg->otg.default_a)
-               return -1;
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '1') {
-               iotg->hsm.a_clr_err = 1;
-               dev_dbg(lnw->dev, "User request: a_clr_err = 1\n");
-       }
-       if (spin_trylock(&lnw->wq_lock)) {
-               langwell_update_transceiver();
-               spin_unlock(&lnw->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
-
-static struct attribute *inputs_attrs[] = {
-       &dev_attr_a_bus_req.attr,
-       &dev_attr_a_bus_drop.attr,
-       &dev_attr_b_bus_req.attr,
-       &dev_attr_a_clr_err.attr,
-       NULL,
-};
-
-static struct attribute_group debug_dev_attr_group = {
-       .name = "inputs",
-       .attrs = inputs_attrs,
-};
-
-static int langwell_otg_probe(struct pci_dev *pdev,
-               const struct pci_device_id *id)
-{
-       unsigned long           resource, len;
-       void __iomem            *base = NULL;
-       int                     retval;
-       u32                     val32;
-       struct langwell_otg     *lnw;
-       char                    qname[] = "langwell_otg_queue";
-
-       retval = 0;
-       dev_dbg(&pdev->dev, "\notg controller is detected.\n");
-       if (pci_enable_device(pdev) < 0) {
-               retval = -ENODEV;
-               goto done;
-       }
-
-       lnw = kzalloc(sizeof *lnw, GFP_KERNEL);
-       if (lnw == NULL) {
-               retval = -ENOMEM;
-               goto done;
-       }
-       the_transceiver = lnw;
-
-       /* control register: BAR 0 */
-       resource = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-       if (!request_mem_region(resource, len, driver_name)) {
-               retval = -EBUSY;
-               goto err;
-       }
-       lnw->region = 1;
-
-       base = ioremap_nocache(resource, len);
-       if (base == NULL) {
-               retval = -EFAULT;
-               goto err;
-       }
-       lnw->iotg.base = base;
-
-       if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) {
-               retval = -EBUSY;
-               goto err;
-       }
-       lnw->cfg_region = 1;
-
-       /* For the SCCB.USBCFG register */
-       base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN);
-       if (base == NULL) {
-               retval = -EFAULT;
-               goto err;
-       }
-       lnw->usbcfg = base;
-
-       if (!pdev->irq) {
-               dev_dbg(&pdev->dev, "No IRQ.\n");
-               retval = -ENODEV;
-               goto err;
-       }
-
-       lnw->qwork = create_singlethread_workqueue(qname);
-       if (!lnw->qwork) {
-               dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname);
-               retval = -ENOMEM;
-               goto err;
-       }
-       INIT_WORK(&lnw->work, langwell_otg_work);
-
-       /* OTG common part */
-       lnw->dev = &pdev->dev;
-       lnw->iotg.otg.dev = lnw->dev;
-       lnw->iotg.otg.label = driver_name;
-       lnw->iotg.otg.set_host = langwell_otg_set_host;
-       lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral;
-       lnw->iotg.otg.set_power = langwell_otg_set_power;
-       lnw->iotg.otg.set_vbus = langwell_otg_set_vbus;
-       lnw->iotg.otg.start_srp = langwell_otg_start_srp;
-       lnw->iotg.otg.state = OTG_STATE_UNDEFINED;
-
-       if (otg_set_transceiver(&lnw->iotg.otg)) {
-               dev_dbg(lnw->dev, "can't set transceiver\n");
-               retval = -EBUSY;
-               goto err;
-       }
-
-       reset_otg();
-       init_hsm();
-
-       spin_lock_init(&lnw->lock);
-       spin_lock_init(&lnw->wq_lock);
-       INIT_LIST_HEAD(&active_timers);
-       retval = langwell_otg_init_timers(&lnw->iotg.hsm);
-       if (retval) {
-               dev_dbg(&pdev->dev, "Failed to init timers\n");
-               goto err;
-       }
-
-       init_timer(&lnw->hsm_timer);
-       ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier);
-
-       lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify;
-
-       retval = intel_mid_otg_register_notifier(&lnw->iotg,
-                                               &lnw->iotg_notifier);
-       if (retval) {
-               dev_dbg(lnw->dev, "Failed to register notifier\n");
-               goto err;
-       }
-
-       if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
-                               driver_name, lnw) != 0) {
-               dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq);
-               retval = -EBUSY;
-               goto err;
-       }
-
-       /* enable OTGSC int */
-       val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
-               OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
-       writel(val32, lnw->iotg.base + CI_OTGSC);
-
-       retval = device_create_file(&pdev->dev, &dev_attr_registers);
-       if (retval < 0) {
-               dev_dbg(lnw->dev,
-                       "Can't register sysfs attribute: %d\n", retval);
-               goto err;
-       }
-
-       retval = device_create_file(&pdev->dev, &dev_attr_hsm);
-       if (retval < 0) {
-               dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval);
-               goto err;
-       }
-
-       retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
-       if (retval < 0) {
-               dev_dbg(lnw->dev,
-                       "Can't register sysfs attr group: %d\n", retval);
-               goto err;
-       }
-
-       if (lnw->iotg.otg.state == OTG_STATE_A_IDLE)
-               langwell_update_transceiver();
-
-       return 0;
-
-err:
-       if (the_transceiver)
-               langwell_otg_remove(pdev);
-done:
-       return retval;
-}
-
-static void langwell_otg_remove(struct pci_dev *pdev)
-{
-       struct langwell_otg *lnw = the_transceiver;
-
-       if (lnw->qwork) {
-               flush_workqueue(lnw->qwork);
-               destroy_workqueue(lnw->qwork);
-       }
-       intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier);
-       langwell_otg_free_timers();
-
-       /* disable OTGSC interrupt as OTGSC doesn't change in reset */
-       writel(0, lnw->iotg.base + CI_OTGSC);
-
-       if (pdev->irq)
-               free_irq(pdev->irq, lnw);
-       if (lnw->usbcfg)
-               iounmap(lnw->usbcfg);
-       if (lnw->cfg_region)
-               release_mem_region(USBCFG_ADDR, USBCFG_LEN);
-       if (lnw->iotg.base)
-               iounmap(lnw->iotg.base);
-       if (lnw->region)
-               release_mem_region(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-
-       otg_set_transceiver(NULL);
-       pci_disable_device(pdev);
-       sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
-       device_remove_file(&pdev->dev, &dev_attr_hsm);
-       device_remove_file(&pdev->dev, &dev_attr_registers);
-       kfree(lnw);
-       lnw = NULL;
-}
-
-static void transceiver_suspend(struct pci_dev *pdev)
-{
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-       langwell_otg_phy_low_power(1);
-}
-
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
-{
-       struct langwell_otg             *lnw = the_transceiver;
-       struct intel_mid_otg_xceiv      *iotg = &lnw->iotg;
-       int                             ret = 0;
-
-       /* Disbale OTG interrupts */
-       langwell_otg_intr(0);
-
-       if (pdev->irq)
-               free_irq(pdev->irq, lnw);
-
-       /* Prevent more otg_work */
-       flush_workqueue(lnw->qwork);
-       destroy_workqueue(lnw->qwork);
-       lnw->qwork = NULL;
-
-       /* start actions */
-       switch (iotg->otg.state) {
-       case OTG_STATE_A_WAIT_VFALL:
-               iotg->otg.state = OTG_STATE_A_IDLE;
-       case OTG_STATE_A_IDLE:
-       case OTG_STATE_B_IDLE:
-       case OTG_STATE_A_VBUS_ERR:
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_WAIT_VRISE:
-               langwell_otg_del_timer(a_wait_vrise_tmr);
-               iotg->hsm.a_srp_det = 0;
-
-               /* Turn off VBus */
-               iotg->otg.set_vbus(&iotg->otg, false);
-               iotg->otg.state = OTG_STATE_A_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_WAIT_BCON:
-               del_timer_sync(&lnw->hsm_timer);
-               if (lnw->iotg.stop_host)
-                       lnw->iotg.stop_host(&lnw->iotg);
-               else
-                       dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
-               iotg->hsm.a_srp_det = 0;
-
-               /* Turn off VBus */
-               iotg->otg.set_vbus(&iotg->otg, false);
-               iotg->otg.state = OTG_STATE_A_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_HOST:
-               if (lnw->iotg.stop_host)
-                       lnw->iotg.stop_host(&lnw->iotg);
-               else
-                       dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
-               iotg->hsm.a_srp_det = 0;
-
-               /* Turn off VBus */
-               iotg->otg.set_vbus(&iotg->otg, false);
-
-               iotg->otg.state = OTG_STATE_A_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_SUSPEND:
-               langwell_otg_del_timer(a_aidl_bdis_tmr);
-               langwell_otg_HABA(0);
-               if (lnw->iotg.stop_host)
-                       lnw->iotg.stop_host(&lnw->iotg);
-               else
-                       dev_dbg(lnw->dev, "host driver has been removed.\n");
-               iotg->hsm.a_srp_det = 0;
-
-               /* Turn off VBus */
-               iotg->otg.set_vbus(&iotg->otg, false);
-               iotg->otg.state = OTG_STATE_A_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_PERIPHERAL:
-               del_timer_sync(&lnw->hsm_timer);
-
-               if (lnw->iotg.stop_peripheral)
-                       lnw->iotg.stop_peripheral(&lnw->iotg);
-               else
-                       dev_dbg(&pdev->dev,
-                               "client driver has been removed.\n");
-               iotg->hsm.a_srp_det = 0;
-
-               /* Turn off VBus */
-               iotg->otg.set_vbus(&iotg->otg, false);
-               iotg->otg.state = OTG_STATE_A_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_B_HOST:
-               if (lnw->iotg.stop_host)
-                       lnw->iotg.stop_host(&lnw->iotg);
-               else
-                       dev_dbg(&pdev->dev, "host driver has been removed.\n");
-               iotg->hsm.b_bus_req = 0;
-               iotg->otg.state = OTG_STATE_B_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_B_PERIPHERAL:
-               if (lnw->iotg.stop_peripheral)
-                       lnw->iotg.stop_peripheral(&lnw->iotg);
-               else
-                       dev_dbg(&pdev->dev,
-                               "client driver has been removed.\n");
-               iotg->otg.state = OTG_STATE_B_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_B_WAIT_ACON:
-               /* delete hsm timer for b_ase0_brst_tmr */
-               del_timer_sync(&lnw->hsm_timer);
-
-               langwell_otg_HAAR(0);
-
-               if (lnw->iotg.stop_host)
-                       lnw->iotg.stop_host(&lnw->iotg);
-               else
-                       dev_dbg(&pdev->dev, "host driver has been removed.\n");
-               iotg->hsm.b_bus_req = 0;
-               iotg->otg.state = OTG_STATE_B_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       default:
-               dev_dbg(lnw->dev, "error state before suspend\n");
-               break;
-       }
-
-       return ret;
-}
-
-static void transceiver_resume(struct pci_dev *pdev)
-{
-       pci_restore_state(pdev);
-       pci_set_power_state(pdev, PCI_D0);
-}
-
-static int langwell_otg_resume(struct pci_dev *pdev)
-{
-       struct langwell_otg     *lnw = the_transceiver;
-       int                     ret = 0;
-
-       transceiver_resume(pdev);
-
-       lnw->qwork = create_singlethread_workqueue("langwell_otg_queue");
-       if (!lnw->qwork) {
-               dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen");
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
-                               driver_name, lnw) != 0) {
-               dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq);
-               ret = -EBUSY;
-               goto error;
-       }
-
-       /* enable OTG interrupts */
-       langwell_otg_intr(1);
-
-       update_hsm();
-
-       langwell_update_transceiver();
-
-       return ret;
-error:
-       langwell_otg_intr(0);
-       transceiver_suspend(pdev);
-       return ret;
-}
-
-static int __init langwell_otg_init(void)
-{
-       return pci_register_driver(&otg_pci_driver);
-}
-module_init(langwell_otg_init);
-
-static void __exit langwell_otg_cleanup(void)
-{
-       pci_unregister_driver(&otg_pci_driver);
-}
-module_exit(langwell_otg_cleanup);
index db0d4fcdc8e21902705343b1497743d5cc157845..b5fbe1452ab00e83b2a25dff027548a31b56ff29 100644 (file)
@@ -202,6 +202,7 @@ static void mv_otg_init_irq(struct mv_otg *mvotg)
 
 static void mv_otg_start_host(struct mv_otg *mvotg, int on)
 {
+#ifdef CONFIG_USB
        struct otg_transceiver *otg = &mvotg->otg;
        struct usb_hcd *hcd;
 
@@ -216,6 +217,7 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on)
                usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
        else
                usb_remove_hcd(hcd);
+#endif /* CONFIG_USB */
 }
 
 static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
index b51fcd80d244b57ca75a540276ff45b1c1c3c8c0..72339bd6fcab862565ee222aa4ead450f1d2945d 100644 (file)
@@ -772,10 +772,10 @@ static void usbhsf_dma_prepare_tasklet(unsigned long data)
        struct dma_async_tx_descriptor *desc;
        struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
        struct device *dev = usbhs_priv_to_dev(priv);
-       enum dma_data_direction dir;
+       enum dma_transfer_direction dir;
        dma_cookie_t cookie;
 
-       dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
 
        sg_init_table(&sg, 1);
        sg_set_page(&sg, virt_to_page(pkt->dma),
index 528691d5f3e261119282145e775536a50ea2dc9e..7542aa94a4622421219237598c8db20ff1f46a87 100644 (file)
@@ -425,7 +425,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
        struct usbhs_pipe *pipe;
        int recip = ctrl->bRequestType & USB_RECIP_MASK;
        int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
-       int ret;
+       int ret = 0;
        int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
                    struct usb_ctrlrequest *ctrl);
        char *msg;
index fba1147ed9169c1711027a693fcb8df5788aa031..08a5575724cd3f12b1a55966db21ac95e8495806 100644 (file)
@@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *,
        struct usb_serial_port *port);
 static void cp210x_get_termios_port(struct usb_serial_port *port,
        unsigned int *cflagp, unsigned int *baudp);
+static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
+                                                       struct ktermios *);
 static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
                                                        struct ktermios*);
 static int cp210x_tiocmget(struct tty_struct *);
@@ -134,10 +136,13 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
        { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
        { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+       { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
+       { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
        { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
        { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+       { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
        { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
        { } /* Terminating Entry */
 };
@@ -201,6 +206,8 @@ static struct usb_serial_driver cp210x_device = {
 #define CP210X_EMBED_EVENTS    0x15
 #define CP210X_GET_EVENTSTATE  0x16
 #define CP210X_SET_CHARS       0x19
+#define CP210X_GET_BAUDRATE    0x1D
+#define CP210X_SET_BAUDRATE    0x1E
 
 /* CP210X_IFC_ENABLE */
 #define UART_ENABLE            0x0001
@@ -360,8 +367,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
  * Quantises the baud rate as per AN205 Table 1
  */
 static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
-       if      (baud <= 56)       baud = 0;
-       else if (baud <= 300)      baud = 300;
+       if (baud <= 300)
+               baud = 300;
        else if (baud <= 600)      baud = 600;
        else if (baud <= 1200)     baud = 1200;
        else if (baud <= 1800)     baud = 1800;
@@ -389,10 +396,10 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
        else if (baud <= 491520)   baud = 460800;
        else if (baud <= 567138)   baud = 500000;
        else if (baud <= 670254)   baud = 576000;
-       else if (baud <= 1053257)  baud = 921600;
-       else if (baud <= 1474560)  baud = 1228800;
-       else if (baud <= 2457600)  baud = 1843200;
-       else                       baud = 3686400;
+       else if (baud < 1000000)
+               baud = 921600;
+       else if (baud > 2000000)
+               baud = 2000000;
        return baud;
 }
 
@@ -409,13 +416,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
                return result;
        }
 
-       result = usb_serial_generic_open(tty, port);
-       if (result)
-               return result;
-
        /* Configure the termios structure */
        cp210x_get_termios(tty, port);
-       return 0;
+
+       /* The baud rate must be initialised on cp2104 */
+       if (tty)
+               cp210x_change_speed(tty, port, NULL);
+
+       return usb_serial_generic_open(tty, port);
 }
 
 static void cp210x_close(struct usb_serial_port *port)
@@ -467,10 +475,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
 
        dbg("%s - port %d", __func__, port->number);
 
-       cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
-       /* Convert to baudrate */
-       if (baud)
-               baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+       cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
 
        dbg("%s - baud rate = %d", __func__, baud);
        *baudp = baud;
@@ -579,11 +584,64 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
        *cflagp = cflag;
 }
 
+/*
+ * CP2101 supports the following baud rates:
+ *
+ *     300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
+ *     38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
+ *
+ * CP2102 and CP2103 support the following additional rates:
+ *
+ *     4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
+ *     576000
+ *
+ * The device will map a requested rate to a supported one, but the result
+ * of requests for rates greater than 1053257 is undefined (see AN205).
+ *
+ * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
+ * respectively, with an error less than 1%. The actual rates are determined
+ * by
+ *
+ *     div = round(freq / (2 x prescale x request))
+ *     actual = freq / (2 x prescale x div)
+ *
+ * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
+ * or 1 otherwise.
+ * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
+ * otherwise.
+ */
+static void cp210x_change_speed(struct tty_struct *tty,
+               struct usb_serial_port *port, struct ktermios *old_termios)
+{
+       u32 baud;
+
+       baud = tty->termios->c_ospeed;
+
+       /* This maps the requested rate to a rate valid on cp2102 or cp2103,
+        * or to an arbitrary rate in [1M,2M].
+        *
+        * NOTE: B0 is not implemented.
+        */
+       baud = cp210x_quantise_baudrate(baud);
+
+       dbg("%s - setting baud rate to %u", __func__, baud);
+       if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
+                                                       sizeof(baud))) {
+               dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
+               if (old_termios)
+                       baud = old_termios->c_ospeed;
+               else
+                       baud = 9600;
+       }
+
+       tty_encode_baud_rate(tty, baud, baud);
+}
+
 static void cp210x_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
        unsigned int cflag, old_cflag;
-       unsigned int baud = 0, bits;
+       unsigned int bits;
        unsigned int modem_ctl[4];
 
        dbg("%s - port %d", __func__, port->number);
@@ -593,20 +651,9 @@ static void cp210x_set_termios(struct tty_struct *tty,
 
        cflag = tty->termios->c_cflag;
        old_cflag = old_termios->c_cflag;
-       baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty));
-
-       /* If the baud rate is to be updated*/
-       if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
-               dbg("%s - Setting baud rate to %d baud", __func__,
-                               baud);
-               if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
-                                       ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
-                       dbg("Baud rate requested not supported by device");
-                       baud = tty_termios_baud_rate(old_termios);
-               }
-       }
-       /* Report back the resulting baud rate */
-       tty_encode_baud_rate(tty, baud, baud);
+
+       if (tty->termios->c_ospeed != old_termios->c_ospeed)
+               cp210x_change_speed(tty, port, old_termios);
 
        /* If the number of data bits is to be updated */
        if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
index 01b6404df395bd3c2a042c2f8c92b15b0905f6bd..f770415305f8578556c14b2e1ebbcf8facd947ea 100644 (file)
@@ -797,6 +797,7 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
        { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
        { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -805,6 +806,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
        { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
        { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
        { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
@@ -836,11 +839,13 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
        { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
                .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -1333,8 +1338,7 @@ static int set_serial_info(struct tty_struct *tty,
                goto check_and_exit;
        }
 
-       if ((new_serial.baud_base != priv->baud_base) &&
-           (new_serial.baud_base < 9600)) {
+       if (new_serial.baud_base != priv->baud_base) {
                mutex_unlock(&priv->cfg_lock);
                return -EINVAL;
        }
@@ -1824,6 +1828,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
 
 static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
+       struct ktermios dummy;
        struct usb_device *dev = port->serial->dev;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        int result;
@@ -1842,8 +1847,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
           This is same behaviour as serial.c/rs_open() - Kuba */
 
        /* ftdi_set_termios  will send usb control messages */
-       if (tty)
-               ftdi_set_termios(tty, port, tty->termios);
+       if (tty) {
+               memset(&dummy, 0, sizeof(dummy));
+               ftdi_set_termios(tty, port, &dummy);
+       }
 
        /* Start reading from the device */
        result = usb_serial_generic_open(tty, port);
index df1d7da933ec6f45281f116f57128a0707b4c4d9..6f6058f0db1ba31a53e947933d703785d1324136 100644 (file)
 /* www.candapter.com Ewert Energy Systems CANdapter device */
 #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
 
+/*
+ * Texas Instruments XDS100v2 JTAG / BeagleBone A3
+ * http://processors.wiki.ti.com/index.php/XDS100
+ * http://beagleboard.org/bone
+ */
+#define TI_XDS100V2_PID                0xa6d0
+
 #define FTDI_NXTCAM_PID                0xABB8 /* NXTCam for Mindstorms NXT */
 
 /* US Interface Navigator (http://www.usinterface.com/) */
 #define ADI_GNICE_PID          0xF000
 #define ADI_GNICEPLUS_PID      0xF001
 
+/*
+ * Hornby Elite
+ */
+#define HORNBY_VID             0x04D8
+#define HORNBY_ELITE_PID       0x000A
+
 /*
  * RATOC REX-USB60F
  */
  */
 /* TagTracer MIFARE*/
 #define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID   0xF7C0
+
+/*
+ * Rainforest Automation
+ */
+/* ZigBee controller */
+#define FTDI_RF_R106           0x8A28
+
+/*
+ * Product: HCP HIT GPRS modem
+ * Manufacturer: HCP d.o.o.
+ * ATI command output: Cinterion MC55i
+ */
+#define FTDI_CINTERION_MC55I_PID       0xA951
index 65bf06aa591a091616b084943388194209b913a6..5818bfc3261ebb2418a54406e768abbe76245ed9 100644 (file)
@@ -2657,15 +2657,7 @@ cleanup:
 
 static void edge_disconnect(struct usb_serial *serial)
 {
-       int i;
-       struct edgeport_port *edge_port;
-
        dbg("%s", __func__);
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = usb_get_serial_port_data(serial->port[i]);
-               edge_remove_sysfs_attrs(edge_port->port);
-       }
 }
 
 static void edge_release(struct usb_serial *serial)
@@ -2744,6 +2736,7 @@ static struct usb_serial_driver edgeport_1port_device = {
        .disconnect             = edge_disconnect,
        .release                = edge_release,
        .port_probe             = edge_create_sysfs_attrs,
+       .port_remove            = edge_remove_sysfs_attrs,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -2775,6 +2768,7 @@ static struct usb_serial_driver edgeport_2port_device = {
        .disconnect             = edge_disconnect,
        .release                = edge_release,
        .port_probe             = edge_create_sysfs_attrs,
+       .port_remove            = edge_remove_sysfs_attrs,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
index 5d3beeeb5fd9b527359190b3e0076b6b85fb2d43..a92a3efb507bdaa45f7134919b30c4bf8b495917 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/ioctl.h>
 #include "kobil_sct.h"
 
-static int debug;
+static bool debug;
 
 /* Version Information */
 #define DRIVER_VERSION "21/05/2004"
index 420d9857394a090a6bf1aae5d9ef86541585dd4d..b54afceb9611badc2b3e7cb45c33a12bcefbd0cc 100644 (file)
@@ -480,6 +480,10 @@ static void option_instat_callback(struct urb *urb);
 #define ZD_VENDOR_ID                           0x0685
 #define ZD_PRODUCT_7000                                0x7000
 
+/* LG products */
+#define LG_VENDOR_ID                           0x1004
+#define LG_PRODUCT_L02C                                0x618f
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -784,7 +788,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
@@ -799,7 +802,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
-       /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
@@ -824,7 +826,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
-       /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -832,7 +833,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff),
@@ -842,7 +842,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
@@ -851,6 +850,16 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
@@ -871,23 +880,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1062,17 +1066,27 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
+         0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
-         0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
@@ -1183,6 +1197,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
        { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 30b73e68a904d65e7dadb3fdeee8acd73f65607c..a34819884c1ad6b82e732f069e7392f0272d766f 100644 (file)
@@ -36,6 +36,7 @@
 #define UTSTARCOM_PRODUCT_UM175_V1             0x3712
 #define UTSTARCOM_PRODUCT_UM175_V2             0x3714
 #define UTSTARCOM_PRODUCT_UM175_ALLTEL         0x3715
+#define PANTECH_PRODUCT_UML190_VZW             0x3716
 #define PANTECH_PRODUCT_UML290_VZW             0x3718
 
 /* CMOTECH devices */
@@ -67,7 +68,11 @@ static struct usb_device_id id_table[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
-       { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) },  /* NMEA */
+       { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) },  /* WMC */
+       { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },  /* DIAG */
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 1d5deee3be52211d10c6cc02edb7f121efc57541..f98800f2324c22afda070ca85af221af64060310 100644 (file)
@@ -36,6 +36,11 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x413c, 0x8171)},   /* Dell Gobi QDL device */
        {USB_DEVICE(0x1410, 0xa001)},   /* Novatel Gobi Modem device */
        {USB_DEVICE(0x1410, 0xa008)},   /* Novatel Gobi QDL device */
+       {USB_DEVICE(0x1410, 0xa010)},   /* Novatel Gobi QDL device */
+       {USB_DEVICE(0x1410, 0xa011)},   /* Novatel Gobi QDL device */
+       {USB_DEVICE(0x1410, 0xa012)},   /* Novatel Gobi QDL device */
+       {USB_DEVICE(0x1410, 0xa013)},   /* Novatel Gobi QDL device */
+       {USB_DEVICE(0x1410, 0xa014)},   /* Novatel Gobi QDL device */
        {USB_DEVICE(0x0b05, 0x1776)},   /* Asus Gobi Modem device */
        {USB_DEVICE(0x0b05, 0x1774)},   /* Asus Gobi QDL device */
        {USB_DEVICE(0x19d2, 0xfff3)},   /* ONDA Gobi Modem device */
@@ -86,7 +91,16 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x16d8, 0x8002)},   /* CMDTech Gobi 2000 Modem device (VU922) */
        {USB_DEVICE(0x05c6, 0x9204)},   /* Gobi 2000 QDL device */
        {USB_DEVICE(0x05c6, 0x9205)},   /* Gobi 2000 Modem device */
+
+       {USB_DEVICE(0x05c6, 0x920c)},   /* Gobi 3000 QDL */
+       {USB_DEVICE(0x05c6, 0x920d)},   /* Gobi 3000 Composite */
+       {USB_DEVICE(0x1410, 0xa020)},   /* Novatel Gobi 3000 QDL */
+       {USB_DEVICE(0x1410, 0xa021)},   /* Novatel Gobi 3000 Composite */
+       {USB_DEVICE(0x413c, 0x8193)},   /* Dell Gobi 3000 QDL */
+       {USB_DEVICE(0x413c, 0x8194)},   /* Dell Gobi 3000 Composite */
        {USB_DEVICE(0x1199, 0x9013)},   /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+       {USB_DEVICE(0x12D1, 0x14F0)},   /* Sony Gobi 3000 QDL */
+       {USB_DEVICE(0x12D1, 0x14F1)},   /* Sony Gobi 3000 Composite */
        { }                             /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -123,8 +137,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 
        spin_lock_init(&data->susp_lock);
 
-       usb_enable_autosuspend(serial->dev);
-
        switch (nintf) {
        case 1:
                /* QDL mode */
index 8468eb769a2919d38316993e670cb2810dfacbd7..75b838eff178ca743a3f53069ef2d515cb6f0b15 100644 (file)
@@ -165,7 +165,7 @@ static unsigned int product_5052_count;
 /* the array dimension is the number of default entries plus */
 /* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
 /* null entry */
-static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
        { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
        { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -179,6 +179,7 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
        { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
        { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
        { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+       { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
 };
 
 static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -188,7 +189,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
        { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
 };
 
-static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = {
        { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
        { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -206,6 +207,7 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1]
        { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
        { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
        { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+       { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
        { }
 };
 
index 2aac1953993b1c9508283a8ecfef303c9fa26f1e..f140f1b9d5c078283a18816d9afd718ca68c5be1 100644 (file)
 #define MTS_MT9234ZBA_PRODUCT_ID       0xF115
 #define MTS_MT9234ZBAOLD_PRODUCT_ID    0x0319
 
+/* Abbott Diabetics vendor and product ids */
+#define ABBOTT_VENDOR_ID               0x1a61
+#define ABBOTT_PRODUCT_ID              0x3410
+
 /* Commands */
 #define TI_GET_VERSION                 0x01
 #define TI_GET_PORT_STATUS             0x02
index 1f62723ef1a86013a8f1dbd5d96356559ea0ceda..d32f72061c099ddae5aca09758bed77feddf7319 100644 (file)
@@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data)
                        rts51x_set_stat(chip, RTS51X_STAT_SS);
                        /* ignore mass storage interface's children */
                        pm_suspend_ignore_children(&us->pusb_intf->dev, true);
-                       usb_autopm_put_interface(us->pusb_intf);
+                       usb_autopm_put_interface_async(us->pusb_intf);
                        US_DEBUGP("%s: RTS51X_STAT_SS 01,"
                                "intf->pm_usage_cnt:%d, power.usage:%d\n",
                                __func__,
index 3dd7da9fd5043cad98a00e552ba8c11ebe9ff581..db51ba16dc0755d6b7876c115abd10eba6e876c7 100644 (file)
@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(struct us_data *us)
        struct Scsi_Host *host = us_to_host(us);
 
        /* If the device is really gone, cut short reset delays */
-       if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+       if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
                set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+               wake_up(&us->delay_wait);
+       }
 
-       /* Prevent SCSI-scanning (if it hasn't started yet)
-        * and wait for the SCSI-scanning thread to stop.
+       /* Prevent SCSI scanning (if it hasn't started yet)
+        * or wait for the SCSI-scanning routine to stop.
         */
-       set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
-       wake_up(&us->delay_wait);
-       wait_for_completion(&us->scanning_done);
+       cancel_delayed_work_sync(&us->scan_dwork);
+
+       /* Balance autopm calls if scanning was cancelled */
+       if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
+               usb_autopm_put_interface_no_suspend(us->pusb_intf);
 
        /* Removing the host will perform an orderly shutdown: caches
         * synchronized, disks spun down, etc.
@@ -823,53 +827,28 @@ static void release_everything(struct us_data *us)
        scsi_host_put(us_to_host(us));
 }
 
-/* Thread to carry out delayed SCSI-device scanning */
-static int usb_stor_scan_thread(void * __us)
+/* Delayed-work routine to carry out SCSI-device scanning */
+static void usb_stor_scan_dwork(struct work_struct *work)
 {
-       struct us_data *us = (struct us_data *)__us;
+       struct us_data *us = container_of(work, struct us_data,
+                       scan_dwork.work);
        struct device *dev = &us->pusb_intf->dev;
 
-       dev_dbg(dev, "device found\n");
-
-       set_freezable();
+       dev_dbg(dev, "starting scan\n");
 
-       /*
-        * Wait for the timeout to expire or for a disconnect
-        *
-        * We can't freeze in this thread or we risk causing khubd to
-        * fail to freeze, but we can't be non-freezable either. Nor can
-        * khubd freeze while waiting for scanning to complete as it may
-        * hold the device lock, causing a hang when suspending devices.
-        * So instead of using wait_event_freezable(), explicitly test
-        * for (DONT_SCAN || freezing) in interruptible wait and proceed
-        * if any of DONT_SCAN, freezing or timeout has happened.
-        */
-       if (delay_use > 0) {
-               dev_dbg(dev, "waiting for device to settle "
-                               "before scanning\n");
-               wait_event_interruptible_timeout(us->delay_wait,
-                               test_bit(US_FLIDX_DONT_SCAN, &us->dflags) ||
-                               freezing(current), delay_use * HZ);
+       /* For bulk-only devices, determine the max LUN value */
+       if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
+               mutex_lock(&us->dev_mutex);
+               us->max_lun = usb_stor_Bulk_max_lun(us);
+               mutex_unlock(&us->dev_mutex);
        }
+       scsi_scan_host(us_to_host(us));
+       dev_dbg(dev, "scan complete\n");
 
-       /* If the device is still connected, perform the scanning */
-       if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
-
-               /* For bulk-only devices, determine the max LUN value */
-               if (us->protocol == USB_PR_BULK &&
-                               !(us->fflags & US_FL_SINGLE_LUN)) {
-                       mutex_lock(&us->dev_mutex);
-                       us->max_lun = usb_stor_Bulk_max_lun(us);
-                       mutex_unlock(&us->dev_mutex);
-               }
-               scsi_scan_host(us_to_host(us));
-               dev_dbg(dev, "scan complete\n");
-
-               /* Should we unbind if no devices were detected? */
-       }
+       /* Should we unbind if no devices were detected? */
 
        usb_autopm_put_interface(us->pusb_intf);
-       complete_and_exit(&us->scanning_done, 0);
+       clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
 }
 
 static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
@@ -916,7 +895,7 @@ int usb_stor_probe1(struct us_data **pus,
        init_completion(&us->cmnd_ready);
        init_completion(&(us->notify));
        init_waitqueue_head(&us->delay_wait);
-       init_completion(&us->scanning_done);
+       INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
 
        /* Associate the us_data structure with the USB device */
        result = associate_dev(us, intf);
@@ -947,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
 /* Second part of general USB mass-storage probing */
 int usb_stor_probe2(struct us_data *us)
 {
-       struct task_struct *th;
        int result;
        struct device *dev = &us->pusb_intf->dev;
 
@@ -988,20 +966,14 @@ int usb_stor_probe2(struct us_data *us)
                goto BadDevice;
        }
 
-       /* Start up the thread for delayed SCSI-device scanning */
-       th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
-       if (IS_ERR(th)) {
-               dev_warn(dev,
-                               "Unable to start the device-scanning thread\n");
-               complete(&us->scanning_done);
-               quiesce_and_remove_host(us);
-               result = PTR_ERR(th);
-               goto BadDevice;
-       }
-
+       /* Submit the delayed_work for SCSI-device scanning */
        usb_autopm_get_interface_no_resume(us->pusb_intf);
-       wake_up_process(th);
+       set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
 
+       if (delay_use > 0)
+               dev_dbg(dev, "waiting for device to settle before scanning\n");
+       queue_delayed_work(system_freezable_wq, &us->scan_dwork,
+                       delay_use * HZ);
        return 0;
 
        /* We come here if there are any problems */
index 7b0f2113632efb52ada464fc17dd83a74f34ea5a..75f70f04f37b89ba0ee63495298bc995da0024e4 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
 
 struct us_data;
@@ -72,7 +73,7 @@ struct us_unusual_dev {
 #define US_FLIDX_DISCONNECTING 3       /* disconnect in progress   */
 #define US_FLIDX_RESETTING     4       /* device reset in progress */
 #define US_FLIDX_TIMED_OUT     5       /* SCSI midlayer timed out  */
-#define US_FLIDX_DONT_SCAN     6       /* don't scan (disconnect)  */
+#define US_FLIDX_SCAN_PENDING  6       /* scanning not yet done    */
 #define US_FLIDX_REDO_READ10   7       /* redo READ(10) command    */
 #define US_FLIDX_READ10_WORKED 8       /* previous READ(10) succeeded */
 
@@ -147,8 +148,8 @@ struct us_data {
        /* mutual exclusion and synchronization structures */
        struct completion       cmnd_ready;      /* to sleep thread on      */
        struct completion       notify;          /* thread begin/end        */
-       wait_queue_head_t       delay_wait;      /* wait during scan, reset */
-       struct completion       scanning_done;   /* wait for scan thread    */
+       wait_queue_head_t       delay_wait;      /* wait during reset       */
+       struct delayed_work     scan_dwork;      /* for async scanning      */
 
        /* subdriver information */
        void                    *extra;          /* Any extra data          */
index 8efeae24764f97dedfe016f7006520fa61b8a09f..b4a71679c933def94e684c0d68c3d6a0b1c315c0 100644 (file)
@@ -27,8 +27,6 @@
 #define USB_SKEL_VENDOR_ID     0xfff0
 #define USB_SKEL_PRODUCT_ID    0xfff0
 
-static DEFINE_MUTEX(skel_mutex);
-
 /* table of devices that work with this driver */
 static const struct usb_device_id skel_table[] = {
        { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
@@ -101,25 +99,18 @@ static int skel_open(struct inode *inode, struct file *file)
                goto exit;
        }
 
-       mutex_lock(&skel_mutex);
        dev = usb_get_intfdata(interface);
        if (!dev) {
-               mutex_unlock(&skel_mutex);
                retval = -ENODEV;
                goto exit;
        }
 
        /* increment our usage count for the device */
        kref_get(&dev->kref);
-       mutex_unlock(&skel_mutex);
 
        /* lock the device to allow correctly handling errors
         * in resumption */
        mutex_lock(&dev->io_mutex);
-       if (!dev->interface) {
-               retval = -ENODEV;
-               goto out_err;
-       }
 
        retval = usb_autopm_get_interface(interface);
        if (retval)
@@ -127,11 +118,7 @@ static int skel_open(struct inode *inode, struct file *file)
 
        /* save our object in the file's private structure */
        file->private_data = dev;
-
-out_err:
        mutex_unlock(&dev->io_mutex);
-       if (retval)
-               kref_put(&dev->kref, skel_delete);
 
 exit:
        return retval;
@@ -611,6 +598,7 @@ static void skel_disconnect(struct usb_interface *interface)
        int minor = interface->minor;
 
        dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
 
        /* give back our minor */
        usb_deregister_dev(interface, &skel_class);
@@ -622,12 +610,8 @@ static void skel_disconnect(struct usb_interface *interface)
 
        usb_kill_anchored_urbs(&dev->submitted);
 
-       mutex_lock(&skel_mutex);
-       usb_set_intfdata(interface, NULL);
-
        /* decrement our usage count */
        kref_put(&dev->kref, skel_delete);
-       mutex_unlock(&skel_mutex);
 
        dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
 }
index 0ead8826ec7947f8abf2721b8609094987055cef..f29fdd7f6d750b6849c8d0d57d8ca5c948efe2e6 100644 (file)
@@ -6,7 +6,7 @@ config USB_WUSB
        depends on EXPERIMENTAL
        depends on USB
        depends on PCI
-        select UWB
+       depends on UWB
         select CRYPTO
         select CRYPTO_BLKCIPHER
         select CRYPTO_CBC
index 882a51fe7b3c8cd000dddc5f6b2214536f7b7636..9dab1f51dd43b3bac6e275eac77f995fb245d48d 100644 (file)
@@ -856,9 +856,9 @@ static const struct file_operations vhost_net_fops = {
 };
 
 static struct miscdevice vhost_net_misc = {
-       MISC_DYNAMIC_MINOR,
-       "vhost-net",
-       &vhost_net_fops,
+       .minor = VHOST_NET_MINOR,
+       .name = "vhost-net",
+       .fops = &vhost_net_fops,
 };
 
 static int vhost_net_init(void)
@@ -879,3 +879,5 @@ MODULE_VERSION("0.0.1");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Michael S. Tsirkin");
 MODULE_DESCRIPTION("Host kernel accelerator for virtio net");
+MODULE_ALIAS_MISCDEV(VHOST_NET_MINOR);
+MODULE_ALIAS("devname:vhost-net");
index 0d7b20d4285d3cb47fc1894c237321756512942a..e40c00f2c2ba8ecf7dfa6a1f35655ee3fa419ffc 100644 (file)
@@ -1108,7 +1108,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
         */
        lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
 
-       sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+       sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
        lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
        if (sinfo->atmel_lcdfb_power_control)
                sinfo->atmel_lcdfb_power_control(0);
index 66bc74d9ce2af30889d026835d00442923cbc822..378276c9d3cfdaa2926740da3aa6faba5213a3ae 100644 (file)
@@ -146,7 +146,7 @@ static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask
 
        ret = adp8860_read(client, reg, &reg_val);
 
-       if (!ret && ((reg_val & bit_mask) == 0)) {
+       if (!ret && ((reg_val & bit_mask) != bit_mask)) {
                reg_val |= bit_mask;
                ret = adp8860_write(client, reg, reg_val);
        }
index 6c68a6899e8769c0f131c91860e3467240bcb87c..6735059376d63840d95067ee4564500cd70fe390 100644 (file)
@@ -160,7 +160,7 @@ static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask
 
        ret = adp8870_read(client, reg, &reg_val);
 
-       if (!ret && ((reg_val & bit_mask) == 0)) {
+       if (!ret && ((reg_val & bit_mask) != bit_mask)) {
                reg_val |= bit_mask;
                ret = adp8870_write(client, reg, reg_val);
        }
index 4f5d1c4cb6aba0a53c7bb75c2605bf9c000241f3..27d1d7a29c77ef501c29a043b309ce7f4bb290db 100644 (file)
@@ -190,6 +190,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
 
        priv->io_reg = regulator_get(&spi->dev, "vdd");
        if (IS_ERR(priv->io_reg)) {
+               ret = PTR_ERR(priv->io_reg);
                dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
                       __func__);
                goto err3;
@@ -197,6 +198,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
 
        priv->core_reg = regulator_get(&spi->dev, "vcore");
        if (IS_ERR(priv->core_reg)) {
+               ret = PTR_ERR(priv->core_reg);
                dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
                       __func__);
                goto err4;
index acf292bfba021a93206de3b028e147138b5ced99..6af3f16754f0e2bd8e5062312164f05a80219a78 100644 (file)
@@ -1432,7 +1432,7 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
        struct fsl_diu_data *data;
 
        data = dev_get_drvdata(&ofdev->dev);
-       disable_lcdc(data->fsl_diu_info[0]);
+       disable_lcdc(data->fsl_diu_info);
 
        return 0;
 }
@@ -1442,7 +1442,7 @@ static int fsl_diu_resume(struct platform_device *ofdev)
        struct fsl_diu_data *data;
 
        data = dev_get_drvdata(&ofdev->dev);
-       enable_lcdc(data->fsl_diu_info[0]);
+       enable_lcdc(data->fsl_diu_info);
 
        return 0;
 }
index c6afa33a45322b4f70c57e2672535ab8cabef715..02fd2263610c1c63d1cdb8cd8173373a3ce88200 100644 (file)
@@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
        if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
                ERR_MSG("Could not allocate cmap for intelfb_info.\n");
                goto err_out_cmap;
-               return -ENODEV;
        }
 
        dinfo = info->par;
index 43207cc6cc1953099b2804717e173e47ad7e27f1..fe01add3700e05769dc035cde599040b43460328 100644 (file)
@@ -592,12 +592,12 @@ static int __init macfb_init(void)
        if (!fb_info.screen_base)
                return -ENODEV;
 
-       printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
-              macfb_fix.smem_start, fb_info.screen_base,
-              macfb_fix.smem_len / 1024);
-       printk("macfb: mode is %dx%dx%d, linelength=%d\n",
-              macfb_defined.xres, macfb_defined.yres,
-              macfb_defined.bits_per_pixel, macfb_fix.line_length);
+       pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
+               macfb_fix.smem_start, fb_info.screen_base,
+               macfb_fix.smem_len / 1024);
+       pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
+               macfb_defined.xres, macfb_defined.yres,
+               macfb_defined.bits_per_pixel, macfb_fix.line_length);
 
        /* Fill in the available video resolution */
        macfb_defined.xres_virtual = macfb_defined.xres;
@@ -613,14 +613,10 @@ static int __init macfb_init(void)
 
        switch (macfb_defined.bits_per_pixel) {
        case 1:
-               /*
-                * XXX: I think this will catch any program that tries
-                * to do FBIO_PUTCMAP when the visual is monochrome.
-                */
                macfb_defined.red.length = macfb_defined.bits_per_pixel;
                macfb_defined.green.length = macfb_defined.bits_per_pixel;
                macfb_defined.blue.length = macfb_defined.bits_per_pixel;
-               video_cmap_len = 0;
+               video_cmap_len = 2;
                macfb_fix.visual = FB_VISUAL_MONO01;
                break;
        case 2:
@@ -660,11 +656,10 @@ static int __init macfb_init(void)
                macfb_fix.visual = FB_VISUAL_TRUECOLOR;
                break;
        default:
-               video_cmap_len = 0;
-               macfb_fix.visual = FB_VISUAL_MONO01;
-               printk("macfb: unknown or unsupported bit depth: %d\n",
+               pr_err("macfb: unknown or unsupported bit depth: %d\n",
                       macfb_defined.bits_per_pixel);
-               break;
+               err = -EINVAL;
+               goto fail_unmap;
        }
        
        /*
@@ -734,8 +729,8 @@ static int __init macfb_init(void)
                case MAC_MODEL_Q950:
                        strcpy(macfb_fix.id, "DAFB");
                        macfb_setpalette = dafb_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                /*
@@ -744,8 +739,8 @@ static int __init macfb_init(void)
                case MAC_MODEL_LCII:
                        strcpy(macfb_fix.id, "V8");
                        macfb_setpalette = v8_brazil_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                /*
@@ -758,8 +753,8 @@ static int __init macfb_init(void)
                case MAC_MODEL_P600:
                        strcpy(macfb_fix.id, "Brazil");
                        macfb_setpalette = v8_brazil_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                /*
@@ -773,10 +768,10 @@ static int __init macfb_init(void)
                case MAC_MODEL_P520:
                case MAC_MODEL_P550:
                case MAC_MODEL_P460:
-                       macfb_setpalette = v8_brazil_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        strcpy(macfb_fix.id, "Sonora");
+                       macfb_setpalette = v8_brazil_setpalette;
                        v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                /*
@@ -786,10 +781,10 @@ static int __init macfb_init(void)
                 */
                case MAC_MODEL_IICI:
                case MAC_MODEL_IISI:
-                       macfb_setpalette = rbv_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        strcpy(macfb_fix.id, "RBV");
+                       macfb_setpalette = rbv_setpalette;
                        rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                /*
@@ -797,10 +792,10 @@ static int __init macfb_init(void)
                 */
                case MAC_MODEL_Q840:
                case MAC_MODEL_C660:
-                       macfb_setpalette = civic_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        strcpy(macfb_fix.id, "Civic");
+                       macfb_setpalette = civic_setpalette;
                        civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                
@@ -809,26 +804,26 @@ static int __init macfb_init(void)
                 * We think this may be like the LC II
                 */
                case MAC_MODEL_LC:
+                       strcpy(macfb_fix.id, "LC");
                        if (vidtest) {
                                macfb_setpalette = v8_brazil_setpalette;
-                               macfb_defined.activate = FB_ACTIVATE_NOW;
                                v8_brazil_cmap_regs =
                                        ioremap(DAC_BASE, 0x1000);
+                               macfb_defined.activate = FB_ACTIVATE_NOW;
                        }
-                       strcpy(macfb_fix.id, "LC");
                        break;
 
                /*
                 * We think this may be like the LC II
                 */
                case MAC_MODEL_CCL:
+                       strcpy(macfb_fix.id, "Color Classic");
                        if (vidtest) {
                                macfb_setpalette = v8_brazil_setpalette;
-                               macfb_defined.activate = FB_ACTIVATE_NOW;
                                v8_brazil_cmap_regs =
                                        ioremap(DAC_BASE, 0x1000);
+                               macfb_defined.activate = FB_ACTIVATE_NOW;
                        }
-                       strcpy(macfb_fix.id, "Color Classic");
                        break;
 
                /*
@@ -893,10 +888,10 @@ static int __init macfb_init(void)
                case MAC_MODEL_PB270C:
                case MAC_MODEL_PB280:
                case MAC_MODEL_PB280C:
-                       macfb_setpalette = csc_setpalette;
-                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        strcpy(macfb_fix.id, "CSC");
+                       macfb_setpalette = csc_setpalette;
                        csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+                       macfb_defined.activate = FB_ACTIVATE_NOW;
                        break;
 
                default:
@@ -918,8 +913,9 @@ static int __init macfb_init(void)
        if (err)
                goto fail_dealloc;
 
-       printk("fb%d: %s frame buffer device\n",
-              fb_info.node, fb_info.fix.id);
+       pr_info("fb%d: %s frame buffer device\n",
+               fb_info.node, fb_info.fix.id);
+
        return 0;
 
 fail_dealloc:
index e3406ab313059fcde53187f7bd9ea3f6352aff11..727a5149d81806be71c7b902be7d4a20b3309a2e 100644 (file)
@@ -245,6 +245,7 @@ struct mx3fb_data {
 
        uint32_t                h_start_width;
        uint32_t                v_start_width;
+       enum disp_data_mapping  disp_data_fmt;
 };
 
 struct dma_chan_request {
@@ -287,11 +288,14 @@ static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long r
        __raw_writel(value, mx3fb->reg_base + reg);
 }
 
-static const uint32_t di_mappings[] = {
-       0x1600AAAA, 0x00E05555, 0x00070000, 3,  /* RGB888 */
-       0x0005000F, 0x000B000F, 0x0011000F, 1,  /* RGB666 */
-       0x0011000F, 0x000B000F, 0x0005000F, 1,  /* BGR666 */
-       0x0004003F, 0x000A000F, 0x000F003F, 1   /* RGB565 */
+struct di_mapping {
+       uint32_t b0, b1, b2;
+};
+
+static const struct di_mapping di_mappings[] = {
+       [IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f },
+       [IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f },
+       [IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 },
 };
 
 static void sdc_fb_init(struct mx3fb_info *fbi)
@@ -334,7 +338,7 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
        /* This enables the channel */
        if (mx3_fbi->cookie < 0) {
                mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan,
-                     &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
+                     &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
                if (!mx3_fbi->txd) {
                        dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
                                dma_chan->chan_id);
@@ -425,7 +429,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel
  * @pixel_clk:         desired pixel clock frequency in Hz.
  * @width:             width of panel in pixels.
  * @height:            height of panel in pixels.
- * @pixel_fmt:         pixel format of buffer as FOURCC ASCII code.
  * @h_start_width:     number of pixel clocks between the HSYNC signal pulse
  *                     and the start of valid data.
  * @h_sync_width:      width of the HSYNC signal in units of pixel clocks.
@@ -442,7 +445,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel
 static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
                          uint32_t pixel_clk,
                          uint16_t width, uint16_t height,
-                         enum pixel_fmt pixel_fmt,
                          uint16_t h_start_width, uint16_t h_sync_width,
                          uint16_t h_end_width, uint16_t v_start_width,
                          uint16_t v_sync_width, uint16_t v_end_width,
@@ -453,6 +455,7 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
        uint32_t old_conf;
        uint32_t div;
        struct clk *ipu_clk;
+       const struct di_mapping *map;
 
        dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
 
@@ -540,36 +543,10 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
                sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
        mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
 
-       switch (pixel_fmt) {
-       case IPU_PIX_FMT_RGB24:
-               mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       case IPU_PIX_FMT_RGB666:
-               mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       case IPU_PIX_FMT_BGR666:
-               mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       default:
-               mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       }
+       map = &di_mappings[mx3fb->disp_data_fmt];
+       mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP);
+       mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP);
+       mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP);
 
        spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
 
@@ -780,8 +757,6 @@ static int __set_par(struct fb_info *fbi, bool lock)
                if (sdc_init_panel(mx3fb, mode,
                                   (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
                                   fbi->var.xres, fbi->var.yres,
-                                  (fbi->var.sync & FB_SYNC_SWAP_RGB) ?
-                                  IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,
                                   fbi->var.left_margin,
                                   fbi->var.hsync_len,
                                   fbi->var.right_margin +
@@ -1117,7 +1092,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
                async_tx_ack(mx3_fbi->txd);
 
        txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
-               mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
+               mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
        if (!txd) {
                dev_err(fbi->device,
                        "Error preparing a DMA transaction descriptor.\n");
@@ -1349,6 +1324,12 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
        const struct fb_videomode *mode;
        int ret, num_modes;
 
+       if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) {
+               dev_err(dev, "Illegal display data format %d\n",
+                               mx3fb_pdata->disp_data_fmt);
+               return -EINVAL;
+       }
+
        ichan->client = mx3fb;
        irq = ichan->eof_irq;
 
@@ -1402,6 +1383,8 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
        mx3fbi->mx3fb           = mx3fb;
        mx3fbi->blank           = FB_BLANK_NORMAL;
 
+       mx3fb->disp_data_fmt    = mx3fb_pdata->disp_data_fmt;
+
        init_completion(&mx3fbi->flip_cmpl);
        disable_irq(ichan->eof_irq);
        dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
index a5ec7f37c1857f99fdd411e38e0384f05c3e1936..e1626a1d5c451ffe0d3b829326ddf462423f5274 100644 (file)
@@ -401,7 +401,7 @@ void dispc_runtime_put(void)
 
        DSSDBG("dispc_runtime_put\n");
 
-       r = pm_runtime_put(&dispc.pdev->dev);
+       r = pm_runtime_put_sync(&dispc.pdev->dev);
        WARN_ON(r < 0);
 }
 
index 395d658a94fcab1e7e54131e96485b379fee07a7..faaf305fda279615a6748ff0cfbbe78e315049a2 100644 (file)
@@ -180,6 +180,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
+       if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
+               DSSERR("no VDSS_DSI regulator\n");
+               return -ENODEV;
+       }
+
        if (dssdev->manager == NULL) {
                DSSERR("failed to enable display: no manager\n");
                return -ENODEV;
index d4d676c82c12fbe9789edc354c85b5a14bd19cbb..52f36ec1c8bb3889e9e23cb2c6b6eca2181a454a 100644 (file)
@@ -1079,7 +1079,7 @@ void dsi_runtime_put(struct platform_device *dsidev)
 
        DSSDBG("dsi_runtime_put\n");
 
-       r = pm_runtime_put(&dsi->pdev->dev);
+       r = pm_runtime_put_sync(&dsi->pdev->dev);
        WARN_ON(r < 0);
 }
 
index 17033457ee89baa2e557b4dbd0d53215977ee6ce..77c2b5a32b5d639687e84b8faa1e0385f55b86f9 100644 (file)
@@ -720,7 +720,7 @@ void dss_runtime_put(void)
 
        DSSDBG("dss_runtime_put\n");
 
-       r = pm_runtime_put(&dss.pdev->dev);
+       r = pm_runtime_put_sync(&dss.pdev->dev);
        WARN_ON(r < 0);
 }
 
index b4c270edb915bde5ce721d8373950ee8fa2df667..d7aa3b056529e9469a8e3c0346ebbe421a2df1be 100644 (file)
@@ -176,7 +176,7 @@ static void hdmi_runtime_put(void)
 
        DSSDBG("hdmi_runtime_put\n");
 
-       r = pm_runtime_put(&hdmi.pdev->dev);
+       r = pm_runtime_put_sync(&hdmi.pdev->dev);
        WARN_ON(r < 0);
 }
 
@@ -497,6 +497,7 @@ bool omapdss_hdmi_detect(void)
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
+       struct omap_dss_hdmi_data *priv = dssdev->data;
        int r = 0;
 
        DSSDBG("ENTER hdmi_display_enable\n");
@@ -509,6 +510,8 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
+       hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
+
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
index 814bb9500dca77a9b47c6216aedadd361ba5cdaf..55f398014f33b31863e0718a6600c25c368bac8e 100644 (file)
@@ -140,7 +140,7 @@ static void rfbi_runtime_put(void)
 
        DSSDBG("rfbi_runtime_put\n");
 
-       r = pm_runtime_put(&rfbi.pdev->dev);
+       r = pm_runtime_put_sync(&rfbi.pdev->dev);
        WARN_ON(r < 0);
 }
 
index 7503f7f619a7fe43b7be266f04e9bf4cd7c8579a..50dadba5070a6fc862cb514979e30e7faf8f9f34 100644 (file)
@@ -126,6 +126,10 @@ struct hdmi_ip_data {
        const struct ti_hdmi_ip_ops *ops;
        struct hdmi_config cfg;
        struct hdmi_pll_info pll_data;
+
+       /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
+       int hpd_gpio;
+       bool phy_tx_enabled;
 };
 int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
 void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
index 9af81f18f1633ffaaeae842d922f8800cd9d285c..2d72334ca3da9a7d3bac43fba0c7e1ce6c26621e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
+#include <linux/gpio.h>
 
 #include "ti_hdmi_4xxx_ip.h"
 #include "dss.h"
@@ -223,6 +224,49 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
        hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
 }
 
+static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data)
+{
+       unsigned long flags;
+       bool hpd;
+       int r;
+       /* this should be in ti_hdmi_4xxx_ip private data */
+       static DEFINE_SPINLOCK(phy_tx_lock);
+
+       spin_lock_irqsave(&phy_tx_lock, flags);
+
+       hpd = gpio_get_value(ip_data->hpd_gpio);
+
+       if (hpd == ip_data->phy_tx_enabled) {
+               spin_unlock_irqrestore(&phy_tx_lock, flags);
+               return 0;
+       }
+
+       if (hpd)
+               r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
+       else
+               r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+
+       if (r) {
+               DSSERR("Failed to %s PHY TX power\n",
+                               hpd ? "enable" : "disable");
+               goto err;
+       }
+
+       ip_data->phy_tx_enabled = hpd;
+err:
+       spin_unlock_irqrestore(&phy_tx_lock, flags);
+       return r;
+}
+
+static irqreturn_t hpd_irq_handler(int irq, void *data)
+{
+       struct hdmi_ip_data *ip_data = data;
+
+       hdmi_check_hpd_state(ip_data);
+
+       return IRQ_HANDLED;
+}
+
 int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
 {
        u16 r = 0;
@@ -232,10 +276,6 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
        if (r)
                return r;
 
-       r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
-       if (r)
-               return r;
-
        /*
         * Read address 0 in order to get the SCP reset done completed
         * Dummy access performed to make sure reset is done
@@ -257,12 +297,32 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
        /* Write to phy address 3 to change the polarity control */
        REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
 
+       r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
+                       NULL, hpd_irq_handler,
+                       IRQF_DISABLED | IRQF_TRIGGER_RISING |
+                       IRQF_TRIGGER_FALLING, "hpd", ip_data);
+       if (r) {
+               DSSERR("HPD IRQ request failed\n");
+               hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+               return r;
+       }
+
+       r = hdmi_check_hpd_state(ip_data);
+       if (r) {
+               free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+               hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+               return r;
+       }
+
        return 0;
 }
 
 void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
 {
+       free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+
        hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+       ip_data->phy_tx_enabled = false;
 }
 
 static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
index b3e9f90915815f4e82950743c72b6d36acad8913..5c3d0f9015105beb1d3a3946847097a181035ef1 100644 (file)
@@ -401,7 +401,7 @@ static void venc_runtime_put(void)
 
        DSSDBG("venc_runtime_put\n");
 
-       r = pm_runtime_put(&venc.pdev->dev);
+       r = pm_runtime_put_sync(&venc.pdev->dev);
        WARN_ON(r < 0);
 }
 
index 79e1b292c0309b8175a84d7e4353ff94b8e13eb0..5aa43c3392a2a061ed9fb35f3caa53605690e7fd 100644 (file)
@@ -35,7 +35,7 @@
 #define virtio_rmb(vq) \
        do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
 #define virtio_wmb(vq) \
-       do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
+       do { if ((vq)->weak_barriers) smp_wmb(); else wmb(); } while(0)
 #else
 /* We must force memory ordering even if guest is UP since host could be
  * running on another CPU, but SMP barriers are defined to barrier() in that
@@ -308,9 +308,9 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq)
        bool needs_kick;
 
        START_USE(vq);
-       /* Descriptors and available array need to be set before we expose the
-        * new available array entries. */
-       virtio_wmb(vq);
+       /* We need to expose available array entries before checking avail
+        * event. */
+       virtio_mb(vq);
 
        old = vq->vring.avail->idx - vq->num_added;
        new = vq->vring.avail->idx;
index 1b0e3dd81c1a2751be3db157790f677d27eee5e9..63d7b58f1c7d35edb71baee715d6a18c930c9783 100644 (file)
@@ -300,11 +300,7 @@ static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
        if (!mem)
                return -EINVAL;
 
-       if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
-                                    "dw_wdt"))
-               return -ENOMEM;
-
-       dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+       dw_wdt.regs = devm_request_and_ioremap(&pdev->dev, mem);
        if (!dw_wdt.regs)
                return -ENOMEM;
 
index 99796c5d913db2c9f354dbd06b503d8d65580cdf..bdf401b240b547af6877e00b3286e358eb8f1184 100644 (file)
@@ -36,6 +36,7 @@
  *     document number TBD                   : Patsburg (PBG)
  *     document number TBD                   : DH89xxCC
  *     document number TBD                   : Panther Point
+ *     document number TBD                   : Lynx Point
  */
 
 /*
@@ -126,6 +127,7 @@ enum iTCO_chipsets {
        TCO_PBG,        /* Patsburg */
        TCO_DH89XXCC,   /* DH89xxCC */
        TCO_PPT,        /* Panther Point */
+       TCO_LPT,        /* Lynx Point */
 };
 
 static struct {
@@ -189,6 +191,7 @@ static struct {
        {"Patsburg", 2},
        {"DH89xxCC", 2},
        {"Panther Point", 2},
+       {"Lynx Point", 2},
        {NULL, 0}
 };
 
@@ -331,6 +334,38 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
        { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT},
        { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT},
        { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT},
+       { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT},
+       { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
index b8ef2c6dca7ca900fdf6ae752b59ca1e49c1ad6a..c44c3334003a11aa3a8cb53e5099c0309c77830f 100644 (file)
@@ -247,7 +247,6 @@ static struct miscdevice imx2_wdt_miscdev = {
 static int __init imx2_wdt_probe(struct platform_device *pdev)
 {
        int ret;
-       int res_size;
        struct resource *res;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -256,15 +255,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       res_size = resource_size(res);
-       if (!devm_request_mem_region(&pdev->dev, res->start, res_size,
-               res->name)) {
-               dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
-                       res_size, res->start);
-               return -ENOMEM;
-       }
-
-       imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size);
+       imx2_wdt.base = devm_request_and_ioremap(&pdev->dev, res);
        if (!imx2_wdt.base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                return -ENOMEM;
index 50359bad91770d41d8b3dedbb959cc0dac1d4ad0..529085b8b8fb0358275b3cbbf65801b5eee74445 100644 (file)
@@ -72,7 +72,7 @@ struct nuc900_wdt {
 };
 
 static unsigned long nuc900wdt_busy;
-struct nuc900_wdt *nuc900_wdt;
+static struct nuc900_wdt *nuc900_wdt;
 
 static inline void nuc900_wdt_keepalive(void)
 {
@@ -287,7 +287,8 @@ static int __devinit nuc900wdt_probe(struct platform_device *pdev)
 
        setup_timer(&nuc900_wdt->timer, nuc900_wdt_timer_ping, 0);
 
-       if (misc_register(&nuc900wdt_miscdev)) {
+       ret = misc_register(&nuc900wdt_miscdev);
+       if (ret) {
                dev_err(&pdev->dev, "err register miscdev on minor=%d (%d)\n",
                        WATCHDOG_MINOR, ret);
                goto err_clk;
index 4b33e3fd726bb4b2664dbc3c8ff66d0cef71be3d..d19ff5145e8260fff0eb102bbbfcd7b058b85eeb 100644 (file)
@@ -339,6 +339,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
        return 0;
 
 err_misc:
+       pm_runtime_disable(wdev->dev);
        platform_set_drvdata(pdev, NULL);
        iounmap(wdev->base);
 
@@ -371,6 +372,7 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev)
        struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
+       pm_runtime_disable(wdev->dev);
        if (!res)
                return -ENOENT;
 
index bd143c9dd3e6d0084c08c40d972082e4b9f9db29..8e210aafdfd05396db165bd32c4f68a07e25e05f 100644 (file)
@@ -226,7 +226,7 @@ static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd,
 static int pnx4008_wdt_release(struct inode *inode, struct file *file)
 {
        if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");
+               printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n");
 
        wdt_disable();
        clk_disable(wdt_clk);
index 4c2a4e8698f9922813f8d31b86bca583f9985239..e37d81178b9e7bd5326cd5dbbbfafe3f91a2d885 100644 (file)
@@ -174,7 +174,7 @@ static int stmp3xxx_wdt_release(struct inode *inode, struct file *file)
        if (!nowayout) {
                if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
                        wdt_ping();
-                       pr_debug("%s: Device closed unexpectdly\n", __func__);
+                       pr_debug("%s: Device closed unexpectedly\n", __func__);
                        ret = -EINVAL;
                } else {
                        wdt_disable();
index 026b4bbfa0aa2a0fd783ad178a261f0f3744738a..8f07dd4bd94a67385d3c44093a8a9f5c75e8f960 100644 (file)
@@ -124,8 +124,6 @@ static int wdt_stop(struct watchdog_device *wdd)
 static int wdt_set_timeout(struct watchdog_device *wdd,
                           unsigned int new_timeout)
 {
-       if (new_timeout < 1 || new_timeout > WDT_TIMEOUT_MAX)
-               return -EINVAL;
        writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
        timeout = new_timeout;
        return 0;
@@ -150,6 +148,8 @@ static const struct watchdog_ops wdt_ops = {
 static struct watchdog_device wdt_dev = {
        .info =         &wdt_info,
        .ops =          &wdt_ops,
+       .min_timeout =  1,
+       .max_timeout =  WDT_TIMEOUT_MAX,
 };
 
 static int __devinit wdt_probe(struct pci_dev *pdev,
@@ -233,7 +233,7 @@ static void __devexit wdt_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
+static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
index 42e940c238914172e199d5e232369ccc33ccf35e..c3c3188c34d744312cf8e1dbe3e2c30426e87248 100644 (file)
@@ -152,12 +152,12 @@ static long wafwdt_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                if (options & WDIOS_DISABLECARD) {
-                       wafwdt_start();
+                       wafwdt_stop();
                        retval = 0;
                }
 
                if (options & WDIOS_ENABLECARD) {
-                       wafwdt_stop();
+                       wafwdt_start();
                        retval = 0;
                }
 
index 909c78650d3e8942e7b7c3bb70de90d7c208f9fc..5d7113c7e501d1b5b00f8f991bbe475a6504dd88 100644 (file)
@@ -212,10 +212,10 @@ static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd,
 
                /* Setting both simultaneously means at least one must fail */
                if (options == WDIOS_DISABLECARD)
-                       ret = wm8350_wdt_start(wm8350);
+                       ret = wm8350_wdt_stop(wm8350);
 
                if (options == WDIOS_ENABLECARD)
-                       ret = wm8350_wdt_stop(wm8350);
+                       ret = wm8350_wdt_start(wm8350);
                break;
        }
 
index ba6eda4b51433e20e87f4ae977cdd565f7d3c300..0edb91c0de6bf2b69d6de3ec41d43d38b5d823b5 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/bio.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <xen/page.h>
 
 bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
@@ -11,3 +12,4 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
        return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&
                ((mfn1 == mfn2) || ((mfn1+1) == mfn2));
 }
+EXPORT_SYMBOL(xen_biovec_phys_mergeable);
index 14e2d995e95800ca88a064ac5ba09caec2b48973..4dcfced107f50e41c518405b28747064d62d78bc 100644 (file)
@@ -30,7 +30,8 @@ static int vcpu_online(unsigned int cpu)
        sprintf(dir, "cpu/%u", cpu);
        err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
        if (err != 1) {
-               printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
+               if (!xen_initial_domain())
+                       printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
                return err;
        }
 
index 1cd94daa71db8379443115dd052bc5705fc74432..b4d4eac761db6241042e60db3b604caa9150e91e 100644 (file)
@@ -948,9 +948,12 @@ static void gnttab_request_version(void)
        int rc;
        struct gnttab_set_version gsv;
 
-       gsv.version = 2;
+       if (xen_hvm_domain())
+               gsv.version = 1;
+       else
+               gsv.version = 2;
        rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
-       if (rc == 0) {
+       if (rc == 0 && gsv.version == 2) {
                grant_table_version = 2;
                gnttab_interface = &gnttab_v2_ops;
        } else if (grant_table_version == 2) {
index 3832e303c33aca5ceabf0bb1540e02a28b7765bc..596e6a7b17d68bc3ebf424cc11344da1cc32f1e5 100644 (file)
@@ -221,7 +221,7 @@ static int register_balloon(struct device *dev)
 {
        int i, error;
 
-       error = bus_register(&balloon_subsys);
+       error = subsys_system_register(&balloon_subsys, NULL);
        if (error)
                return error;
 
index 7944a17f5cbf5f073cefac62652a3f0ea53034b1..19834d1c7c3679668fd50b3b3514ed0390014dfe 100644 (file)
@@ -884,7 +884,7 @@ static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
        int err;
 
        err =
-           sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+           sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot,
                   func, reg, size, mask);
        if (err == 7)
                return 0;
@@ -904,7 +904,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
        pci_dev_id->bus = bus;
        pci_dev_id->devfn = PCI_DEVFN(slot, func);
 
-       pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%01x\n",
+       pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n",
                 domain, bus, slot, func);
 
        spin_lock_irqsave(&device_ids_lock, flags);
@@ -934,7 +934,7 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
 
                        err = 0;
 
-                       pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%01x from "
+                       pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%d from "
                                 "seize list\n", domain, bus, slot, func);
                }
        }
@@ -1029,7 +1029,7 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
                        break;
 
                count += scnprintf(buf + count, PAGE_SIZE - count,
-                                  "%04x:%02x:%02x.%01x\n",
+                                  "%04x:%02x:%02x.%d\n",
                                   pci_dev_id->domain, pci_dev_id->bus,
                                   PCI_SLOT(pci_dev_id->devfn),
                                   PCI_FUNC(pci_dev_id->devfn));
index d5dcf8d5d3d91efbaba633f4c2f60259b9c455d0..64b11f99eacc87c758e50736a565d793d4c5c415 100644 (file)
@@ -206,6 +206,7 @@ static int xen_pcibk_publish_pci_dev(struct xen_pcibk_device *pdev,
                goto out;
        }
 
+       /* Note: The PV protocol uses %02x, don't change it */
        err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
                            "%04x:%02x:%02x.%02x", domain, bus,
                            PCI_SLOT(devfn), PCI_FUNC(devfn));
@@ -229,7 +230,7 @@ static int xen_pcibk_export_device(struct xen_pcibk_device *pdev,
                err = -EINVAL;
                xenbus_dev_fatal(pdev->xdev, err,
                                 "Couldn't locate PCI device "
-                                "(%04x:%02x:%02x.%01x)! "
+                                "(%04x:%02x:%02x.%d)! "
                                 "perhaps already in-use?",
                                 domain, bus, slot, func);
                goto out;
@@ -274,7 +275,7 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev,
        if (!dev) {
                err = -EINVAL;
                dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
-                       "(%04x:%02x:%02x.%01x)! not owned by this domain\n",
+                       "(%04x:%02x:%02x.%d)! not owned by this domain\n",
                        domain, bus, slot, func);
                goto out;
        }
index 527dc2a3b89f167cd35cc919bf0da1442c49d238..89f76252a16f20e2638ee578faf4e3cbb4a316c6 100644 (file)
@@ -369,6 +369,10 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
                goto out;
        }
        token++;
+       if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) {
+               rc = -EILSEQ;
+               goto out;
+       }
 
        if (msg_type == XS_WATCH) {
                watch = alloc_watch_adapter(path, token);
index 5f43bfba3c7a76906244b47fce383ab310c08c5b..0d15a3d113a2c77bb119913f6fa2229a7c0605fa 100644 (file)
@@ -82,7 +82,6 @@ fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \
 fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
 fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
                                      advansys/3550.bin advansys/38C0800.bin
-fw-shipped-$(CONFIG_SCSI_ISCI) += isci/isci_firmware.bin
 fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \
                                         qlogic/12160.bin
 fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin
diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex
deleted file mode 100644 (file)
index 2e66195..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-:10000000495343554F454D42E80018100002000087
-:1000100000000000000000000101000000000000DE
-:10002000FFFFCF5F0100000008DD0B0000FC0F00A8
-:10003000097C0B006EFC0A00FFFFCF5F010000008F
-:1000400008DD0B0000FC0F00097C0B006EFC0A00B1
-:10005000FFFFCF5F0100000008DD0B0000FC0F0078
-:10006000097C0B006EFC0A00FFFFCF5F010000005F
-:1000700008DD0B0000FC0F00097C0B006EFC0A0081
-:100080000101000000000000FFFFCF5F0200000040
-:1000900008DD0B0000FC0F00097C0B006EFC0A0061
-:1000A000FFFFCF5F0200000008DD0B0000FC0F0027
-:1000B000097C0B006EFC0A00FFFFCF5F020000000E
-:1000C00008DD0B0000FC0F00097C0B006EFC0A0031
-:1000D000FFFFCF5F0200000008DD0B0000FC0F00F7
-:0800E000097C0B006EFC0A0014
-:00000001FF
index 450f529a4eaeb6e6d48bd147548a2ad3fb72f961..1feb68ecef9509dd88a4323f3193845af6a84e15 100644 (file)
@@ -124,6 +124,7 @@ start:
        /* Negative dentry - try next */
        if (!simple_positive(q)) {
                spin_unlock(&p->d_lock);
+               lock_set_subclass(&q->d_lock.dep_map, 0, _RET_IP_);
                p = q;
                goto again;
        }
@@ -186,6 +187,7 @@ again:
        /* Negative dentry - try next */
        if (!simple_positive(ret)) {
                spin_unlock(&p->d_lock);
+               lock_set_subclass(&ret->d_lock.dep_map, 0, _RET_IP_);
                p = ret;
                goto again;
        }
index b1fe82cf88cfe0864a2d9603b713f8caacecde4e..b980ecde026a3a0e1fca405053572e93ba86c44d 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -505,13 +505,9 @@ EXPORT_SYMBOL(bio_clone);
 int bio_get_nr_vecs(struct block_device *bdev)
 {
        struct request_queue *q = bdev_get_queue(bdev);
-       int nr_pages;
-
-       nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       if (nr_pages > queue_max_segments(q))
-               nr_pages = queue_max_segments(q);
-
-       return nr_pages;
+       return min_t(unsigned,
+                    queue_max_segments(q),
+                    queue_max_sectors(q) / (PAGE_SIZE >> 9) + 1);
 }
 EXPORT_SYMBOL(bio_get_nr_vecs);
 
index ecb9fd3be1433838911f4c947627436d816cb136..d33f01c08b60b329247fe4d8729a387af7c263e4 100644 (file)
@@ -31,3 +31,22 @@ config BTRFS_FS_POSIX_ACL
          Linux website <http://acl.bestbits.at/>.
 
          If you don't know what Access Control Lists are, say N
+
+config BTRFS_FS_CHECK_INTEGRITY
+       bool "Btrfs with integrity check tool compiled in (DANGEROUS)"
+       depends on BTRFS_FS
+       help
+         Adds code that examines all block write requests (including
+         writes of the super block). The goal is to verify that the
+         state of the filesystem on disk is always consistent, i.e.,
+         after a power-loss or kernel panic event the filesystem is
+         in a consistent state.
+
+         If the integrity check tool is included and activated in
+         the mount options, plenty of kernel memory is used, and
+         plenty of additional CPU cycles are spent. Enabling this
+         functionality is not intended for normal use.
+
+         In most cases, unless you are a btrfs developer who needs
+         to verify the integrity of (super)-block write requests
+         during the run of a regression test, say N
index c0ddfd29c5e5a348464d5c3d15a77a7708fd8d79..0c4fa2befae793f1a6845322d7ba71aaa5da4374 100644 (file)
@@ -8,6 +8,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
           extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
           export.o tree-log.o free-space-cache.o zlib.o lzo.o \
           compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
-          reada.o backref.o
+          reada.o backref.o ulist.o
 
 btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
+btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
index 22c64fff1bd524b213ce8b13a233f861680d8424..633c701a287d4be0242d5b1706515aad4845ecfb 100644 (file)
 #include "ctree.h"
 #include "disk-io.h"
 #include "backref.h"
+#include "ulist.h"
+#include "transaction.h"
+#include "delayed-ref.h"
 
-struct __data_ref {
+/*
+ * this structure records all encountered refs on the way up to the root
+ */
+struct __prelim_ref {
        struct list_head list;
-       u64 inum;
-       u64 root;
-       u64 extent_data_item_offset;
+       u64 root_id;
+       struct btrfs_key key;
+       int level;
+       int count;
+       u64 parent;
+       u64 wanted_disk_byte;
 };
 
-struct __shared_ref {
-       struct list_head list;
+static int __add_prelim_ref(struct list_head *head, u64 root_id,
+                           struct btrfs_key *key, int level, u64 parent,
+                           u64 wanted_disk_byte, int count)
+{
+       struct __prelim_ref *ref;
+
+       /* in case we're adding delayed refs, we're holding the refs spinlock */
+       ref = kmalloc(sizeof(*ref), GFP_ATOMIC);
+       if (!ref)
+               return -ENOMEM;
+
+       ref->root_id = root_id;
+       if (key)
+               ref->key = *key;
+       else
+               memset(&ref->key, 0, sizeof(ref->key));
+
+       ref->level = level;
+       ref->count = count;
+       ref->parent = parent;
+       ref->wanted_disk_byte = wanted_disk_byte;
+       list_add_tail(&ref->list, head);
+
+       return 0;
+}
+
+static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
+                               struct ulist *parents,
+                               struct extent_buffer *eb, int level,
+                               u64 wanted_objectid, u64 wanted_disk_byte)
+{
+       int ret;
+       int slot;
+       struct btrfs_file_extent_item *fi;
+       struct btrfs_key key;
        u64 disk_byte;
-};
+
+add_parent:
+       ret = ulist_add(parents, eb->start, 0, GFP_NOFS);
+       if (ret < 0)
+               return ret;
+
+       if (level != 0)
+               return 0;
+
+       /*
+        * if the current leaf is full with EXTENT_DATA items, we must
+        * check the next one if that holds a reference as well.
+        * ref->count cannot be used to skip this check.
+        * repeat this until we don't find any additional EXTENT_DATA items.
+        */
+       while (1) {
+               ret = btrfs_next_leaf(root, path);
+               if (ret < 0)
+                       return ret;
+               if (ret)
+                       return 0;
+
+               eb = path->nodes[0];
+               for (slot = 0; slot < btrfs_header_nritems(eb); ++slot) {
+                       btrfs_item_key_to_cpu(eb, &key, slot);
+                       if (key.objectid != wanted_objectid ||
+                           key.type != BTRFS_EXTENT_DATA_KEY)
+                               return 0;
+                       fi = btrfs_item_ptr(eb, slot,
+                                               struct btrfs_file_extent_item);
+                       disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
+                       if (disk_byte == wanted_disk_byte)
+                               goto add_parent;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * resolve an indirect backref in the form (root_id, key, level)
+ * to a logical address
+ */
+static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
+                                       struct __prelim_ref *ref,
+                                       struct ulist *parents)
+{
+       struct btrfs_path *path;
+       struct btrfs_root *root;
+       struct btrfs_key root_key;
+       struct btrfs_key key = {0};
+       struct extent_buffer *eb;
+       int ret = 0;
+       int root_level;
+       int level = ref->level;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       root_key.objectid = ref->root_id;
+       root_key.type = BTRFS_ROOT_ITEM_KEY;
+       root_key.offset = (u64)-1;
+       root = btrfs_read_fs_root_no_name(fs_info, &root_key);
+       if (IS_ERR(root)) {
+               ret = PTR_ERR(root);
+               goto out;
+       }
+
+       rcu_read_lock();
+       root_level = btrfs_header_level(root->node);
+       rcu_read_unlock();
+
+       if (root_level + 1 == level)
+               goto out;
+
+       path->lowest_level = level;
+       ret = btrfs_search_slot(NULL, root, &ref->key, path, 0, 0);
+       pr_debug("search slot in root %llu (level %d, ref count %d) returned "
+                "%d for key (%llu %u %llu)\n",
+                (unsigned long long)ref->root_id, level, ref->count, ret,
+                (unsigned long long)ref->key.objectid, ref->key.type,
+                (unsigned long long)ref->key.offset);
+       if (ret < 0)
+               goto out;
+
+       eb = path->nodes[level];
+       if (!eb) {
+               WARN_ON(1);
+               ret = 1;
+               goto out;
+       }
+
+       if (level == 0) {
+               if (ret == 1 && path->slots[0] >= btrfs_header_nritems(eb)) {
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret)
+                               goto out;
+                       eb = path->nodes[0];
+               }
+
+               btrfs_item_key_to_cpu(eb, &key, path->slots[0]);
+       }
+
+       /* the last two parameters will only be used for level == 0 */
+       ret = add_all_parents(root, path, parents, eb, level, key.objectid,
+                               ref->wanted_disk_byte);
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+/*
+ * resolve all indirect backrefs from the list
+ */
+static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
+                                  struct list_head *head)
+{
+       int err;
+       int ret = 0;
+       struct __prelim_ref *ref;
+       struct __prelim_ref *ref_safe;
+       struct __prelim_ref *new_ref;
+       struct ulist *parents;
+       struct ulist_node *node;
+
+       parents = ulist_alloc(GFP_NOFS);
+       if (!parents)
+               return -ENOMEM;
+
+       /*
+        * _safe allows us to insert directly after the current item without
+        * iterating over the newly inserted items.
+        * we're also allowed to re-assign ref during iteration.
+        */
+       list_for_each_entry_safe(ref, ref_safe, head, list) {
+               if (ref->parent)        /* already direct */
+                       continue;
+               if (ref->count == 0)
+                       continue;
+               err = __resolve_indirect_ref(fs_info, ref, parents);
+               if (err) {
+                       if (ret == 0)
+                               ret = err;
+                       continue;
+               }
+
+               /* we put the first parent into the ref at hand */
+               node = ulist_next(parents, NULL);
+               ref->parent = node ? node->val : 0;
+
+               /* additional parents require new refs being added here */
+               while ((node = ulist_next(parents, node))) {
+                       new_ref = kmalloc(sizeof(*new_ref), GFP_NOFS);
+                       if (!new_ref) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       memcpy(new_ref, ref, sizeof(*ref));
+                       new_ref->parent = node->val;
+                       list_add(&new_ref->list, &ref->list);
+               }
+               ulist_reinit(parents);
+       }
+
+       ulist_free(parents);
+       return ret;
+}
+
+/*
+ * merge two lists of backrefs and adjust counts accordingly
+ *
+ * mode = 1: merge identical keys, if key is set
+ * mode = 2: merge identical parents
+ */
+static int __merge_refs(struct list_head *head, int mode)
+{
+       struct list_head *pos1;
+
+       list_for_each(pos1, head) {
+               struct list_head *n2;
+               struct list_head *pos2;
+               struct __prelim_ref *ref1;
+
+               ref1 = list_entry(pos1, struct __prelim_ref, list);
+
+               if (mode == 1 && ref1->key.type == 0)
+                       continue;
+               for (pos2 = pos1->next, n2 = pos2->next; pos2 != head;
+                    pos2 = n2, n2 = pos2->next) {
+                       struct __prelim_ref *ref2;
+
+                       ref2 = list_entry(pos2, struct __prelim_ref, list);
+
+                       if (mode == 1) {
+                               if (memcmp(&ref1->key, &ref2->key,
+                                          sizeof(ref1->key)) ||
+                                   ref1->level != ref2->level ||
+                                   ref1->root_id != ref2->root_id)
+                                       continue;
+                               ref1->count += ref2->count;
+                       } else {
+                               if (ref1->parent != ref2->parent)
+                                       continue;
+                               ref1->count += ref2->count;
+                       }
+                       list_del(&ref2->list);
+                       kfree(ref2);
+               }
+
+       }
+       return 0;
+}
+
+/*
+ * add all currently queued delayed refs from this head whose seq nr is
+ * smaller or equal that seq to the list
+ */
+static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
+                             struct btrfs_key *info_key,
+                             struct list_head *prefs)
+{
+       struct btrfs_delayed_extent_op *extent_op = head->extent_op;
+       struct rb_node *n = &head->node.rb_node;
+       int sgn;
+       int ret = 0;
+
+       if (extent_op && extent_op->update_key)
+               btrfs_disk_key_to_cpu(info_key, &extent_op->key);
+
+       while ((n = rb_prev(n))) {
+               struct btrfs_delayed_ref_node *node;
+               node = rb_entry(n, struct btrfs_delayed_ref_node,
+                               rb_node);
+               if (node->bytenr != head->node.bytenr)
+                       break;
+               WARN_ON(node->is_head);
+
+               if (node->seq > seq)
+                       continue;
+
+               switch (node->action) {
+               case BTRFS_ADD_DELAYED_EXTENT:
+               case BTRFS_UPDATE_DELAYED_HEAD:
+                       WARN_ON(1);
+                       continue;
+               case BTRFS_ADD_DELAYED_REF:
+                       sgn = 1;
+                       break;
+               case BTRFS_DROP_DELAYED_REF:
+                       sgn = -1;
+                       break;
+               default:
+                       BUG_ON(1);
+               }
+               switch (node->type) {
+               case BTRFS_TREE_BLOCK_REF_KEY: {
+                       struct btrfs_delayed_tree_ref *ref;
+
+                       ref = btrfs_delayed_node_to_tree_ref(node);
+                       ret = __add_prelim_ref(prefs, ref->root, info_key,
+                                              ref->level + 1, 0, node->bytenr,
+                                              node->ref_mod * sgn);
+                       break;
+               }
+               case BTRFS_SHARED_BLOCK_REF_KEY: {
+                       struct btrfs_delayed_tree_ref *ref;
+
+                       ref = btrfs_delayed_node_to_tree_ref(node);
+                       ret = __add_prelim_ref(prefs, ref->root, info_key,
+                                              ref->level + 1, ref->parent,
+                                              node->bytenr,
+                                              node->ref_mod * sgn);
+                       break;
+               }
+               case BTRFS_EXTENT_DATA_REF_KEY: {
+                       struct btrfs_delayed_data_ref *ref;
+                       struct btrfs_key key;
+
+                       ref = btrfs_delayed_node_to_data_ref(node);
+
+                       key.objectid = ref->objectid;
+                       key.type = BTRFS_EXTENT_DATA_KEY;
+                       key.offset = ref->offset;
+                       ret = __add_prelim_ref(prefs, ref->root, &key, 0, 0,
+                                              node->bytenr,
+                                              node->ref_mod * sgn);
+                       break;
+               }
+               case BTRFS_SHARED_DATA_REF_KEY: {
+                       struct btrfs_delayed_data_ref *ref;
+                       struct btrfs_key key;
+
+                       ref = btrfs_delayed_node_to_data_ref(node);
+
+                       key.objectid = ref->objectid;
+                       key.type = BTRFS_EXTENT_DATA_KEY;
+                       key.offset = ref->offset;
+                       ret = __add_prelim_ref(prefs, ref->root, &key, 0,
+                                              ref->parent, node->bytenr,
+                                              node->ref_mod * sgn);
+                       break;
+               }
+               default:
+                       WARN_ON(1);
+               }
+               BUG_ON(ret);
+       }
+
+       return 0;
+}
+
+/*
+ * add all inline backrefs for bytenr to the list
+ */
+static int __add_inline_refs(struct btrfs_fs_info *fs_info,
+                            struct btrfs_path *path, u64 bytenr,
+                            struct btrfs_key *info_key, int *info_level,
+                            struct list_head *prefs)
+{
+       int ret = 0;
+       int slot;
+       struct extent_buffer *leaf;
+       struct btrfs_key key;
+       unsigned long ptr;
+       unsigned long end;
+       struct btrfs_extent_item *ei;
+       u64 flags;
+       u64 item_size;
+
+       /*
+        * enumerate all inline refs
+        */
+       leaf = path->nodes[0];
+       slot = path->slots[0] - 1;
+
+       item_size = btrfs_item_size_nr(leaf, slot);
+       BUG_ON(item_size < sizeof(*ei));
+
+       ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
+       flags = btrfs_extent_flags(leaf, ei);
+
+       ptr = (unsigned long)(ei + 1);
+       end = (unsigned long)ei + item_size;
+
+       if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
+               struct btrfs_tree_block_info *info;
+               struct btrfs_disk_key disk_key;
+
+               info = (struct btrfs_tree_block_info *)ptr;
+               *info_level = btrfs_tree_block_level(leaf, info);
+               btrfs_tree_block_key(leaf, info, &disk_key);
+               btrfs_disk_key_to_cpu(info_key, &disk_key);
+               ptr += sizeof(struct btrfs_tree_block_info);
+               BUG_ON(ptr > end);
+       } else {
+               BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA));
+       }
+
+       while (ptr < end) {
+               struct btrfs_extent_inline_ref *iref;
+               u64 offset;
+               int type;
+
+               iref = (struct btrfs_extent_inline_ref *)ptr;
+               type = btrfs_extent_inline_ref_type(leaf, iref);
+               offset = btrfs_extent_inline_ref_offset(leaf, iref);
+
+               switch (type) {
+               case BTRFS_SHARED_BLOCK_REF_KEY:
+                       ret = __add_prelim_ref(prefs, 0, info_key,
+                                               *info_level + 1, offset,
+                                               bytenr, 1);
+                       break;
+               case BTRFS_SHARED_DATA_REF_KEY: {
+                       struct btrfs_shared_data_ref *sdref;
+                       int count;
+
+                       sdref = (struct btrfs_shared_data_ref *)(iref + 1);
+                       count = btrfs_shared_data_ref_count(leaf, sdref);
+                       ret = __add_prelim_ref(prefs, 0, NULL, 0, offset,
+                                              bytenr, count);
+                       break;
+               }
+               case BTRFS_TREE_BLOCK_REF_KEY:
+                       ret = __add_prelim_ref(prefs, offset, info_key,
+                                              *info_level + 1, 0, bytenr, 1);
+                       break;
+               case BTRFS_EXTENT_DATA_REF_KEY: {
+                       struct btrfs_extent_data_ref *dref;
+                       int count;
+                       u64 root;
+
+                       dref = (struct btrfs_extent_data_ref *)(&iref->offset);
+                       count = btrfs_extent_data_ref_count(leaf, dref);
+                       key.objectid = btrfs_extent_data_ref_objectid(leaf,
+                                                                     dref);
+                       key.type = BTRFS_EXTENT_DATA_KEY;
+                       key.offset = btrfs_extent_data_ref_offset(leaf, dref);
+                       root = btrfs_extent_data_ref_root(leaf, dref);
+                       ret = __add_prelim_ref(prefs, root, &key, 0, 0, bytenr,
+                                               count);
+                       break;
+               }
+               default:
+                       WARN_ON(1);
+               }
+               BUG_ON(ret);
+               ptr += btrfs_extent_inline_ref_size(type);
+       }
+
+       return 0;
+}
+
+/*
+ * add all non-inline backrefs for bytenr to the list
+ */
+static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
+                           struct btrfs_path *path, u64 bytenr,
+                           struct btrfs_key *info_key, int info_level,
+                           struct list_head *prefs)
+{
+       struct btrfs_root *extent_root = fs_info->extent_root;
+       int ret;
+       int slot;
+       struct extent_buffer *leaf;
+       struct btrfs_key key;
+
+       while (1) {
+               ret = btrfs_next_item(extent_root, path);
+               if (ret < 0)
+                       break;
+               if (ret) {
+                       ret = 0;
+                       break;
+               }
+
+               slot = path->slots[0];
+               leaf = path->nodes[0];
+               btrfs_item_key_to_cpu(leaf, &key, slot);
+
+               if (key.objectid != bytenr)
+                       break;
+               if (key.type < BTRFS_TREE_BLOCK_REF_KEY)
+                       continue;
+               if (key.type > BTRFS_SHARED_DATA_REF_KEY)
+                       break;
+
+               switch (key.type) {
+               case BTRFS_SHARED_BLOCK_REF_KEY:
+                       ret = __add_prelim_ref(prefs, 0, info_key,
+                                               info_level + 1, key.offset,
+                                               bytenr, 1);
+                       break;
+               case BTRFS_SHARED_DATA_REF_KEY: {
+                       struct btrfs_shared_data_ref *sdref;
+                       int count;
+
+                       sdref = btrfs_item_ptr(leaf, slot,
+                                             struct btrfs_shared_data_ref);
+                       count = btrfs_shared_data_ref_count(leaf, sdref);
+                       ret = __add_prelim_ref(prefs, 0, NULL, 0, key.offset,
+                                               bytenr, count);
+                       break;
+               }
+               case BTRFS_TREE_BLOCK_REF_KEY:
+                       ret = __add_prelim_ref(prefs, key.offset, info_key,
+                                               info_level + 1, 0, bytenr, 1);
+                       break;
+               case BTRFS_EXTENT_DATA_REF_KEY: {
+                       struct btrfs_extent_data_ref *dref;
+                       int count;
+                       u64 root;
+
+                       dref = btrfs_item_ptr(leaf, slot,
+                                             struct btrfs_extent_data_ref);
+                       count = btrfs_extent_data_ref_count(leaf, dref);
+                       key.objectid = btrfs_extent_data_ref_objectid(leaf,
+                                                                     dref);
+                       key.type = BTRFS_EXTENT_DATA_KEY;
+                       key.offset = btrfs_extent_data_ref_offset(leaf, dref);
+                       root = btrfs_extent_data_ref_root(leaf, dref);
+                       ret = __add_prelim_ref(prefs, root, &key, 0, 0,
+                                               bytenr, count);
+                       break;
+               }
+               default:
+                       WARN_ON(1);
+               }
+               BUG_ON(ret);
+       }
+
+       return ret;
+}
+
+/*
+ * this adds all existing backrefs (inline backrefs, backrefs and delayed
+ * refs) for the given bytenr to the refs list, merges duplicates and resolves
+ * indirect refs to their parent bytenr.
+ * When roots are found, they're added to the roots list
+ *
+ * FIXME some caching might speed things up
+ */
+static int find_parent_nodes(struct btrfs_trans_handle *trans,
+                            struct btrfs_fs_info *fs_info, u64 bytenr,
+                            u64 seq, struct ulist *refs, struct ulist *roots)
+{
+       struct btrfs_key key;
+       struct btrfs_path *path;
+       struct btrfs_key info_key = { 0 };
+       struct btrfs_delayed_ref_root *delayed_refs = NULL;
+       struct btrfs_delayed_ref_head *head = NULL;
+       int info_level = 0;
+       int ret;
+       struct list_head prefs_delayed;
+       struct list_head prefs;
+       struct __prelim_ref *ref;
+
+       INIT_LIST_HEAD(&prefs);
+       INIT_LIST_HEAD(&prefs_delayed);
+
+       key.objectid = bytenr;
+       key.type = BTRFS_EXTENT_ITEM_KEY;
+       key.offset = (u64)-1;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       /*
+        * grab both a lock on the path and a lock on the delayed ref head.
+        * We need both to get a consistent picture of how the refs look
+        * at a specified point in time
+        */
+again:
+       ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
+       if (ret < 0)
+               goto out;
+       BUG_ON(ret == 0);
+
+       /*
+        * look if there are updates for this ref queued and lock the head
+        */
+       delayed_refs = &trans->transaction->delayed_refs;
+       spin_lock(&delayed_refs->lock);
+       head = btrfs_find_delayed_ref_head(trans, bytenr);
+       if (head) {
+               if (!mutex_trylock(&head->mutex)) {
+                       atomic_inc(&head->node.refs);
+                       spin_unlock(&delayed_refs->lock);
+
+                       btrfs_release_path(path);
+
+                       /*
+                        * Mutex was contended, block until it's
+                        * released and try again
+                        */
+                       mutex_lock(&head->mutex);
+                       mutex_unlock(&head->mutex);
+                       btrfs_put_delayed_ref(&head->node);
+                       goto again;
+               }
+               ret = __add_delayed_refs(head, seq, &info_key, &prefs_delayed);
+               if (ret)
+                       goto out;
+       }
+       spin_unlock(&delayed_refs->lock);
+
+       if (path->slots[0]) {
+               struct extent_buffer *leaf;
+               int slot;
+
+               leaf = path->nodes[0];
+               slot = path->slots[0] - 1;
+               btrfs_item_key_to_cpu(leaf, &key, slot);
+               if (key.objectid == bytenr &&
+                   key.type == BTRFS_EXTENT_ITEM_KEY) {
+                       ret = __add_inline_refs(fs_info, path, bytenr,
+                                               &info_key, &info_level, &prefs);
+                       if (ret)
+                               goto out;
+                       ret = __add_keyed_refs(fs_info, path, bytenr, &info_key,
+                                              info_level, &prefs);
+                       if (ret)
+                               goto out;
+               }
+       }
+       btrfs_release_path(path);
+
+       /*
+        * when adding the delayed refs above, the info_key might not have
+        * been known yet. Go over the list and replace the missing keys
+        */
+       list_for_each_entry(ref, &prefs_delayed, list) {
+               if ((ref->key.offset | ref->key.type | ref->key.objectid) == 0)
+                       memcpy(&ref->key, &info_key, sizeof(ref->key));
+       }
+       list_splice_init(&prefs_delayed, &prefs);
+
+       ret = __merge_refs(&prefs, 1);
+       if (ret)
+               goto out;
+
+       ret = __resolve_indirect_refs(fs_info, &prefs);
+       if (ret)
+               goto out;
+
+       ret = __merge_refs(&prefs, 2);
+       if (ret)
+               goto out;
+
+       while (!list_empty(&prefs)) {
+               ref = list_first_entry(&prefs, struct __prelim_ref, list);
+               list_del(&ref->list);
+               if (ref->count < 0)
+                       WARN_ON(1);
+               if (ref->count && ref->root_id && ref->parent == 0) {
+                       /* no parent == root of tree */
+                       ret = ulist_add(roots, ref->root_id, 0, GFP_NOFS);
+                       BUG_ON(ret < 0);
+               }
+               if (ref->count && ref->parent) {
+                       ret = ulist_add(refs, ref->parent, 0, GFP_NOFS);
+                       BUG_ON(ret < 0);
+               }
+               kfree(ref);
+       }
+
+out:
+       if (head)
+               mutex_unlock(&head->mutex);
+       btrfs_free_path(path);
+       while (!list_empty(&prefs)) {
+               ref = list_first_entry(&prefs, struct __prelim_ref, list);
+               list_del(&ref->list);
+               kfree(ref);
+       }
+       while (!list_empty(&prefs_delayed)) {
+               ref = list_first_entry(&prefs_delayed, struct __prelim_ref,
+                                      list);
+               list_del(&ref->list);
+               kfree(ref);
+       }
+
+       return ret;
+}
+
+/*
+ * Finds all leafs with a reference to the specified combination of bytenr and
+ * offset. key_list_head will point to a list of corresponding keys (caller must
+ * free each list element). The leafs will be stored in the leafs ulist, which
+ * must be freed with ulist_free.
+ *
+ * returns 0 on success, <0 on error
+ */
+static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans,
+                               struct btrfs_fs_info *fs_info, u64 bytenr,
+                               u64 num_bytes, u64 seq, struct ulist **leafs)
+{
+       struct ulist *tmp;
+       int ret;
+
+       tmp = ulist_alloc(GFP_NOFS);
+       if (!tmp)
+               return -ENOMEM;
+       *leafs = ulist_alloc(GFP_NOFS);
+       if (!*leafs) {
+               ulist_free(tmp);
+               return -ENOMEM;
+       }
+
+       ret = find_parent_nodes(trans, fs_info, bytenr, seq, *leafs, tmp);
+       ulist_free(tmp);
+
+       if (ret < 0 && ret != -ENOENT) {
+               ulist_free(*leafs);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * walk all backrefs for a given extent to find all roots that reference this
+ * extent. Walking a backref means finding all extents that reference this
+ * extent and in turn walk the backrefs of those, too. Naturally this is a
+ * recursive process, but here it is implemented in an iterative fashion: We
+ * find all referencing extents for the extent in question and put them on a
+ * list. In turn, we find all referencing extents for those, further appending
+ * to the list. The way we iterate the list allows adding more elements after
+ * the current while iterating. The process stops when we reach the end of the
+ * list. Found roots are added to the roots list.
+ *
+ * returns 0 on success, < 0 on error.
+ */
+int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
+                               struct btrfs_fs_info *fs_info, u64 bytenr,
+                               u64 num_bytes, u64 seq, struct ulist **roots)
+{
+       struct ulist *tmp;
+       struct ulist_node *node = NULL;
+       int ret;
+
+       tmp = ulist_alloc(GFP_NOFS);
+       if (!tmp)
+               return -ENOMEM;
+       *roots = ulist_alloc(GFP_NOFS);
+       if (!*roots) {
+               ulist_free(tmp);
+               return -ENOMEM;
+       }
+
+       while (1) {
+               ret = find_parent_nodes(trans, fs_info, bytenr, seq,
+                                       tmp, *roots);
+               if (ret < 0 && ret != -ENOENT) {
+                       ulist_free(tmp);
+                       ulist_free(*roots);
+                       return ret;
+               }
+               node = ulist_next(tmp, node);
+               if (!node)
+                       break;
+               bytenr = node->val;
+       }
+
+       ulist_free(tmp);
+       return 0;
+}
+
 
 static int __inode_info(u64 inum, u64 ioff, u8 key_type,
                        struct btrfs_root *fs_root, struct btrfs_path *path,
@@ -181,8 +952,11 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
        btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]);
        if (found_key->type != BTRFS_EXTENT_ITEM_KEY ||
            found_key->objectid > logical ||
-           found_key->objectid + found_key->offset <= logical)
+           found_key->objectid + found_key->offset <= logical) {
+               pr_debug("logical %llu is not within any extent\n",
+                        (unsigned long long)logical);
                return -ENOENT;
+       }
 
        eb = path->nodes[0];
        item_size = btrfs_item_size_nr(eb, path->slots[0]);
@@ -191,6 +965,13 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
        ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
        flags = btrfs_extent_flags(eb, ei);
 
+       pr_debug("logical %llu is at position %llu within the extent (%llu "
+                "EXTENT_ITEM %llu) flags %#llx size %u\n",
+                (unsigned long long)logical,
+                (unsigned long long)(logical - found_key->objectid),
+                (unsigned long long)found_key->objectid,
+                (unsigned long long)found_key->offset,
+                (unsigned long long)flags, item_size);
        if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
                return BTRFS_EXTENT_FLAG_TREE_BLOCK;
        if (flags & BTRFS_EXTENT_FLAG_DATA)
@@ -287,128 +1068,11 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb,
        return 0;
 }
 
-static int __data_list_add(struct list_head *head, u64 inum,
-                               u64 extent_data_item_offset, u64 root)
-{
-       struct __data_ref *ref;
-
-       ref = kmalloc(sizeof(*ref), GFP_NOFS);
-       if (!ref)
-               return -ENOMEM;
-
-       ref->inum = inum;
-       ref->extent_data_item_offset = extent_data_item_offset;
-       ref->root = root;
-       list_add_tail(&ref->list, head);
-
-       return 0;
-}
-
-static int __data_list_add_eb(struct list_head *head, struct extent_buffer *eb,
-                               struct btrfs_extent_data_ref *dref)
-{
-       return __data_list_add(head, btrfs_extent_data_ref_objectid(eb, dref),
-                               btrfs_extent_data_ref_offset(eb, dref),
-                               btrfs_extent_data_ref_root(eb, dref));
-}
-
-static int __shared_list_add(struct list_head *head, u64 disk_byte)
-{
-       struct __shared_ref *ref;
-
-       ref = kmalloc(sizeof(*ref), GFP_NOFS);
-       if (!ref)
-               return -ENOMEM;
-
-       ref->disk_byte = disk_byte;
-       list_add_tail(&ref->list, head);
-
-       return 0;
-}
-
-static int __iter_shared_inline_ref_inodes(struct btrfs_fs_info *fs_info,
-                                          u64 logical, u64 inum,
-                                          u64 extent_data_item_offset,
-                                          u64 extent_offset,
-                                          struct btrfs_path *path,
-                                          struct list_head *data_refs,
-                                          iterate_extent_inodes_t *iterate,
-                                          void *ctx)
-{
-       u64 ref_root;
-       u32 item_size;
-       struct btrfs_key key;
-       struct extent_buffer *eb;
-       struct btrfs_extent_item *ei;
-       struct btrfs_extent_inline_ref *eiref;
-       struct __data_ref *ref;
-       int ret;
-       int type;
-       int last;
-       unsigned long ptr = 0;
-
-       WARN_ON(!list_empty(data_refs));
-       ret = extent_from_logical(fs_info, logical, path, &key);
-       if (ret & BTRFS_EXTENT_FLAG_DATA)
-               ret = -EIO;
-       if (ret < 0)
-               goto out;
-
-       eb = path->nodes[0];
-       ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
-       item_size = btrfs_item_size_nr(eb, path->slots[0]);
-
-       ret = 0;
-       ref_root = 0;
-       /*
-        * as done in iterate_extent_inodes, we first build a list of refs to
-        * iterate, then free the path and then iterate them to avoid deadlocks.
-        */
-       do {
-               last = __get_extent_inline_ref(&ptr, eb, ei, item_size,
-                                               &eiref, &type);
-               if (last < 0) {
-                       ret = last;
-                       goto out;
-               }
-               if (type == BTRFS_TREE_BLOCK_REF_KEY ||
-                   type == BTRFS_SHARED_BLOCK_REF_KEY) {
-                       ref_root = btrfs_extent_inline_ref_offset(eb, eiref);
-                       ret = __data_list_add(data_refs, inum,
-                                               extent_data_item_offset,
-                                               ref_root);
-               }
-       } while (!ret && !last);
-
-       btrfs_release_path(path);
-
-       if (ref_root == 0) {
-               printk(KERN_ERR "btrfs: failed to find tree block ref "
-                       "for shared data backref %llu\n", logical);
-               WARN_ON(1);
-               ret = -EIO;
-       }
-
-out:
-       while (!list_empty(data_refs)) {
-               ref = list_first_entry(data_refs, struct __data_ref, list);
-               list_del(&ref->list);
-               if (!ret)
-                       ret = iterate(ref->inum, extent_offset +
-                                       ref->extent_data_item_offset,
-                                       ref->root, ctx);
-               kfree(ref);
-       }
-
-       return ret;
-}
-
-static int __iter_shared_inline_ref(struct btrfs_fs_info *fs_info,
-                                   u64 logical, u64 orig_extent_item_objectid,
-                                   u64 extent_offset, struct btrfs_path *path,
-                                   struct list_head *data_refs,
-                                   iterate_extent_inodes_t *iterate,
-                                   void *ctx)
+static int iterate_leaf_refs(struct btrfs_fs_info *fs_info,
+                               struct btrfs_path *path, u64 logical,
+                               u64 orig_extent_item_objectid,
+                               u64 extent_item_pos, u64 root,
+                               iterate_extent_inodes_t *iterate, void *ctx)
 {
        u64 disk_byte;
        struct btrfs_key key;
@@ -416,8 +1080,10 @@ static int __iter_shared_inline_ref(struct btrfs_fs_info *fs_info,
        struct extent_buffer *eb;
        int slot;
        int nritems;
-       int ret;
-       int found = 0;
+       int ret = 0;
+       int extent_type;
+       u64 data_offset;
+       u64 data_len;
 
        eb = read_tree_block(fs_info->tree_root, logical,
                                fs_info->tree_root->leafsize, 0);
@@ -435,149 +1101,99 @@ static int __iter_shared_inline_ref(struct btrfs_fs_info *fs_info,
                if (key.type != BTRFS_EXTENT_DATA_KEY)
                        continue;
                fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
-               if (!fi) {
-                       free_extent_buffer(eb);
-                       return -EIO;
-               }
+               extent_type = btrfs_file_extent_type(eb, fi);
+               if (extent_type == BTRFS_FILE_EXTENT_INLINE)
+                       continue;
+               /* don't skip BTRFS_FILE_EXTENT_PREALLOC, we can handle that */
                disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
-               if (disk_byte != orig_extent_item_objectid) {
-                       if (found)
-                               break;
-                       else
-                               continue;
-               }
-               ++found;
-               ret = __iter_shared_inline_ref_inodes(fs_info, logical,
-                                                       key.objectid,
-                                                       key.offset,
-                                                       extent_offset, path,
-                                                       data_refs,
-                                                       iterate, ctx);
-               if (ret)
-                       break;
-       }
+               if (disk_byte != orig_extent_item_objectid)
+                       continue;
 
-       if (!found) {
-               printk(KERN_ERR "btrfs: failed to follow shared data backref "
-                       "to parent %llu\n", logical);
-               WARN_ON(1);
-               ret = -EIO;
+               data_offset = btrfs_file_extent_offset(eb, fi);
+               data_len = btrfs_file_extent_num_bytes(eb, fi);
+
+               if (extent_item_pos < data_offset ||
+                   extent_item_pos >= data_offset + data_len)
+                       continue;
+
+               pr_debug("ref for %llu resolved, key (%llu EXTEND_DATA %llu), "
+                               "root %llu\n", orig_extent_item_objectid,
+                               key.objectid, key.offset, root);
+               ret = iterate(key.objectid,
+                               key.offset + (extent_item_pos - data_offset),
+                               root, ctx);
+               if (ret) {
+                       pr_debug("stopping iteration because ret=%d\n", ret);
+                       break;
+               }
        }
 
        free_extent_buffer(eb);
+
        return ret;
 }
 
 /*
  * calls iterate() for every inode that references the extent identified by
- * the given parameters. will use the path given as a parameter and return it
- * released.
+ * the given parameters.
  * when the iterator function returns a non-zero value, iteration stops.
+ * path is guaranteed to be in released state when iterate() is called.
  */
 int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
                                struct btrfs_path *path,
-                               u64 extent_item_objectid,
-                               u64 extent_offset,
+                               u64 extent_item_objectid, u64 extent_item_pos,
                                iterate_extent_inodes_t *iterate, void *ctx)
 {
-       unsigned long ptr = 0;
-       int last;
        int ret;
-       int type;
-       u64 logical;
-       u32 item_size;
-       struct btrfs_extent_inline_ref *eiref;
-       struct btrfs_extent_data_ref *dref;
-       struct extent_buffer *eb;
-       struct btrfs_extent_item *ei;
-       struct btrfs_key key;
        struct list_head data_refs = LIST_HEAD_INIT(data_refs);
        struct list_head shared_refs = LIST_HEAD_INIT(shared_refs);
-       struct __data_ref *ref_d;
-       struct __shared_ref *ref_s;
+       struct btrfs_trans_handle *trans;
+       struct ulist *refs;
+       struct ulist *roots;
+       struct ulist_node *ref_node = NULL;
+       struct ulist_node *root_node = NULL;
+       struct seq_list seq_elem;
+       struct btrfs_delayed_ref_root *delayed_refs;
+
+       trans = btrfs_join_transaction(fs_info->extent_root);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
+
+       pr_debug("resolving all inodes for extent %llu\n",
+                       extent_item_objectid);
+
+       delayed_refs = &trans->transaction->delayed_refs;
+       spin_lock(&delayed_refs->lock);
+       btrfs_get_delayed_seq(delayed_refs, &seq_elem);
+       spin_unlock(&delayed_refs->lock);
+
+       ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
+                                  extent_item_pos, seq_elem.seq,
+                                  &refs);
 
-       eb = path->nodes[0];
-       ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
-       item_size = btrfs_item_size_nr(eb, path->slots[0]);
-
-       /* first we iterate the inline refs, ... */
-       do {
-               last = __get_extent_inline_ref(&ptr, eb, ei, item_size,
-                                               &eiref, &type);
-               if (last == -ENOENT) {
-                       ret = 0;
-                       break;
-               }
-               if (last < 0) {
-                       ret = last;
-                       break;
-               }
-
-               if (type == BTRFS_EXTENT_DATA_REF_KEY) {
-                       dref = (struct btrfs_extent_data_ref *)(&eiref->offset);
-                       ret = __data_list_add_eb(&data_refs, eb, dref);
-               } else if (type == BTRFS_SHARED_DATA_REF_KEY) {
-                       logical = btrfs_extent_inline_ref_offset(eb, eiref);
-                       ret = __shared_list_add(&shared_refs, logical);
-               }
-       } while (!ret && !last);
+       if (ret)
+               goto out;
 
-       /* ... then we proceed to in-tree references and ... */
-       while (!ret) {
-               ++path->slots[0];
-               if (path->slots[0] > btrfs_header_nritems(eb)) {
-                       ret = btrfs_next_leaf(fs_info->extent_root, path);
-                       if (ret) {
-                               if (ret == 1)
-                                       ret = 0; /* we're done */
-                               break;
-                       }
-                       eb = path->nodes[0];
-               }
-               btrfs_item_key_to_cpu(eb, &key, path->slots[0]);
-               if (key.objectid != extent_item_objectid)
+       while (!ret && (ref_node = ulist_next(refs, ref_node))) {
+               ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, -1,
+                                               seq_elem.seq, &roots);
+               if (ret)
                        break;
-               if (key.type == BTRFS_EXTENT_DATA_REF_KEY) {
-                       dref = btrfs_item_ptr(eb, path->slots[0],
-                                               struct btrfs_extent_data_ref);
-                       ret = __data_list_add_eb(&data_refs, eb, dref);
-               } else if (key.type == BTRFS_SHARED_DATA_REF_KEY) {
-                       ret = __shared_list_add(&shared_refs, key.offset);
+               while (!ret && (root_node = ulist_next(roots, root_node))) {
+                       pr_debug("root %llu references leaf %llu\n",
+                                       root_node->val, ref_node->val);
+                       ret = iterate_leaf_refs(fs_info, path, ref_node->val,
+                                               extent_item_objectid,
+                                               extent_item_pos, root_node->val,
+                                               iterate, ctx);
                }
        }
 
-       btrfs_release_path(path);
-
-       /*
-        * ... only at the very end we can process the refs we found. this is
-        * because the iterator function we call is allowed to make tree lookups
-        * and we have to avoid deadlocks. additionally, we need more tree
-        * lookups ourselves for shared data refs.
-        */
-       while (!list_empty(&data_refs)) {
-               ref_d = list_first_entry(&data_refs, struct __data_ref, list);
-               list_del(&ref_d->list);
-               if (!ret)
-                       ret = iterate(ref_d->inum, extent_offset +
-                                       ref_d->extent_data_item_offset,
-                                       ref_d->root, ctx);
-               kfree(ref_d);
-       }
-
-       while (!list_empty(&shared_refs)) {
-               ref_s = list_first_entry(&shared_refs, struct __shared_ref,
-                                       list);
-               list_del(&ref_s->list);
-               if (!ret)
-                       ret = __iter_shared_inline_ref(fs_info,
-                                                       ref_s->disk_byte,
-                                                       extent_item_objectid,
-                                                       extent_offset, path,
-                                                       &data_refs,
-                                                       iterate, ctx);
-               kfree(ref_s);
-       }
-
+       ulist_free(refs);
+       ulist_free(roots);
+out:
+       btrfs_put_delayed_seq(delayed_refs, &seq_elem);
+       btrfs_end_transaction(trans, fs_info->extent_root);
        return ret;
 }
 
@@ -586,19 +1202,20 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
                                iterate_extent_inodes_t *iterate, void *ctx)
 {
        int ret;
-       u64 offset;
+       u64 extent_item_pos;
        struct btrfs_key found_key;
 
        ret = extent_from_logical(fs_info, logical, path,
                                        &found_key);
+       btrfs_release_path(path);
        if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
                ret = -EINVAL;
        if (ret < 0)
                return ret;
 
-       offset = logical - found_key.objectid;
+       extent_item_pos = logical - found_key.objectid;
        ret = iterate_extent_inodes(fs_info, path, found_key.objectid,
-                                       offset, iterate, ctx);
+                                       extent_item_pos, iterate, ctx);
 
        return ret;
 }
@@ -643,6 +1260,10 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
                for (cur = 0; cur < btrfs_item_size(eb, item); cur += len) {
                        name_len = btrfs_inode_ref_name_len(eb, iref);
                        /* path must be released before calling iterate()! */
+                       pr_debug("following ref at offset %u for inode %llu in "
+                                "tree %llu\n", cur,
+                                (unsigned long long)found_key.objectid,
+                                (unsigned long long)fs_root->objectid);
                        ret = iterate(parent, iref, eb, ctx);
                        if (ret) {
                                free_extent_buffer(eb);
@@ -683,10 +1304,14 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
                return PTR_ERR(fspath);
 
        if (fspath > fspath_min) {
+               pr_debug("path resolved: %s\n", fspath);
                ipath->fspath->val[i] = (u64)(unsigned long)fspath;
                ++ipath->fspath->elem_cnt;
                ipath->fspath->bytes_left = fspath - fspath_min;
        } else {
+               pr_debug("missed path, not enough space. missing bytes: %lu, "
+                        "constructed so far: %s\n",
+                        (unsigned long)(fspath_min - fspath), fspath_min);
                ++ipath->fspath->elem_missed;
                ipath->fspath->bytes_missing += fspath_min - fspath;
                ipath->fspath->bytes_left = 0;
index 92618837cb8f94a3a799ea3d08093d9b33aab336..d00dfa9ca9342c96f5057af09fb06418cd943cb6 100644 (file)
@@ -20,6 +20,7 @@
 #define __BTRFS_BACKREF__
 
 #include "ioctl.h"
+#include "ulist.h"
 
 struct inode_fs_paths {
        struct btrfs_path               *btrfs_path;
@@ -54,6 +55,10 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
 
 int paths_from_inode(u64 inum, struct inode_fs_paths *ipath);
 
+int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
+                               struct btrfs_fs_info *fs_info, u64 bytenr,
+                               u64 num_bytes, u64 seq, struct ulist **roots);
+
 struct btrfs_data_container *init_data_container(u32 total_bytes);
 struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
                                        struct btrfs_path *path);
index 634608d2a6d03b5d8741e573de0b142ff8cb6310..9b9b15fd5204347c5ef2931fb186af679cb0d369 100644 (file)
@@ -51,6 +51,9 @@ struct btrfs_inode {
        /* held while logging the inode in tree-log.c */
        struct mutex log_mutex;
 
+       /* held while doing delalloc reservations */
+       struct mutex delalloc_mutex;
+
        /* used to order data wrt metadata */
        struct btrfs_ordered_inode_tree ordered_tree;
 
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
new file mode 100644 (file)
index 0000000..b669a7d
--- /dev/null
@@ -0,0 +1,3069 @@
+/*
+ * Copyright (C) STRATO AG 2011.  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 v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+/*
+ * This module can be used to catch cases when the btrfs kernel
+ * code executes write requests to the disk that bring the file
+ * system in an inconsistent state. In such a state, a power-loss
+ * or kernel panic event would cause that the data on disk is
+ * lost or at least damaged.
+ *
+ * Code is added that examines all block write requests during
+ * runtime (including writes of the super block). Three rules
+ * are verified and an error is printed on violation of the
+ * rules:
+ * 1. It is not allowed to write a disk block which is
+ *    currently referenced by the super block (either directly
+ *    or indirectly).
+ * 2. When a super block is written, it is verified that all
+ *    referenced (directly or indirectly) blocks fulfill the
+ *    following requirements:
+ *    2a. All referenced blocks have either been present when
+ *        the file system was mounted, (i.e., they have been
+ *        referenced by the super block) or they have been
+ *        written since then and the write completion callback
+ *        was called and a FLUSH request to the device where
+ *        these blocks are located was received and completed.
+ *    2b. All referenced blocks need to have a generation
+ *        number which is equal to the parent's number.
+ *
+ * One issue that was found using this module was that the log
+ * tree on disk became temporarily corrupted because disk blocks
+ * that had been in use for the log tree had been freed and
+ * reused too early, while being referenced by the written super
+ * block.
+ *
+ * The search term in the kernel log that can be used to filter
+ * on the existence of detected integrity issues is
+ * "btrfs: attempt".
+ *
+ * The integrity check is enabled via mount options. These
+ * mount options are only supported if the integrity check
+ * tool is compiled by defining BTRFS_FS_CHECK_INTEGRITY.
+ *
+ * Example #1, apply integrity checks to all metadata:
+ * mount /dev/sdb1 /mnt -o check_int
+ *
+ * Example #2, apply integrity checks to all metadata and
+ * to data extents:
+ * mount /dev/sdb1 /mnt -o check_int_data
+ *
+ * Example #3, apply integrity checks to all metadata and dump
+ * the tree that the super block references to kernel messages
+ * each time after a super block was written:
+ * mount /dev/sdb1 /mnt -o check_int,check_int_print_mask=263
+ *
+ * If the integrity check tool is included and activated in
+ * the mount options, plenty of kernel memory is used, and
+ * plenty of additional CPU cycles are spent. Enabling this
+ * functionality is not intended for normal use. In most
+ * cases, unless you are a btrfs developer who needs to verify
+ * the integrity of (super)-block write requests, do not
+ * enable the config option BTRFS_FS_CHECK_INTEGRITY to
+ * include and compile the integrity check tool.
+ */
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+#include <linux/mutex.h>
+#include <linux/crc32c.h>
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include "ctree.h"
+#include "disk-io.h"
+#include "transaction.h"
+#include "extent_io.h"
+#include "disk-io.h"
+#include "volumes.h"
+#include "print-tree.h"
+#include "locking.h"
+#include "check-integrity.h"
+
+#define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000
+#define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000
+#define BTRFSIC_DEV2STATE_HASHTABLE_SIZE 0x100
+#define BTRFSIC_BLOCK_MAGIC_NUMBER 0x14491051
+#define BTRFSIC_BLOCK_LINK_MAGIC_NUMBER 0x11070807
+#define BTRFSIC_DEV2STATE_MAGIC_NUMBER 0x20111530
+#define BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER 20111300
+#define BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL (200 - 6)   /* in characters,
+                                                        * excluding " [...]" */
+#define BTRFSIC_BLOCK_SIZE PAGE_SIZE
+
+#define BTRFSIC_GENERATION_UNKNOWN ((u64)-1)
+
+/*
+ * The definition of the bitmask fields for the print_mask.
+ * They are specified with the mount option check_integrity_print_mask.
+ */
+#define BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE                    0x00000001
+#define BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION                0x00000002
+#define BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE                 0x00000004
+#define BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE                        0x00000008
+#define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH                       0x00000010
+#define BTRFSIC_PRINT_MASK_END_IO_BIO_BH                       0x00000020
+#define BTRFSIC_PRINT_MASK_VERBOSE                             0x00000040
+#define BTRFSIC_PRINT_MASK_VERY_VERBOSE                                0x00000080
+#define BTRFSIC_PRINT_MASK_INITIAL_TREE                                0x00000100
+#define BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES                   0x00000200
+#define BTRFSIC_PRINT_MASK_INITIAL_DATABASE                    0x00000400
+#define BTRFSIC_PRINT_MASK_NUM_COPIES                          0x00000800
+#define BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS               0x00001000
+
+struct btrfsic_dev_state;
+struct btrfsic_state;
+
+struct btrfsic_block {
+       u32 magic_num;          /* only used for debug purposes */
+       unsigned int is_metadata:1;     /* if it is meta-data, not data-data */
+       unsigned int is_superblock:1;   /* if it is one of the superblocks */
+       unsigned int is_iodone:1;       /* if is done by lower subsystem */
+       unsigned int iodone_w_error:1;  /* error was indicated to endio */
+       unsigned int never_written:1;   /* block was added because it was
+                                        * referenced, not because it was
+                                        * written */
+       unsigned int mirror_num:2;      /* large enough to hold
+                                        * BTRFS_SUPER_MIRROR_MAX */
+       struct btrfsic_dev_state *dev_state;
+       u64 dev_bytenr;         /* key, physical byte num on disk */
+       u64 logical_bytenr;     /* logical byte num on disk */
+       u64 generation;
+       struct btrfs_disk_key disk_key; /* extra info to print in case of
+                                        * issues, will not always be correct */
+       struct list_head collision_resolving_node;      /* list node */
+       struct list_head all_blocks_node;       /* list node */
+
+       /* the following two lists contain block_link items */
+       struct list_head ref_to_list;   /* list */
+       struct list_head ref_from_list; /* list */
+       struct btrfsic_block *next_in_same_bio;
+       void *orig_bio_bh_private;
+       union {
+               bio_end_io_t *bio;
+               bh_end_io_t *bh;
+       } orig_bio_bh_end_io;
+       int submit_bio_bh_rw;
+       u64 flush_gen; /* only valid if !never_written */
+};
+
+/*
+ * Elements of this type are allocated dynamically and required because
+ * each block object can refer to and can be ref from multiple blocks.
+ * The key to lookup them in the hashtable is the dev_bytenr of
+ * the block ref to plus the one from the block refered from.
+ * The fact that they are searchable via a hashtable and that a
+ * ref_cnt is maintained is not required for the btrfs integrity
+ * check algorithm itself, it is only used to make the output more
+ * beautiful in case that an error is detected (an error is defined
+ * as a write operation to a block while that block is still referenced).
+ */
+struct btrfsic_block_link {
+       u32 magic_num;          /* only used for debug purposes */
+       u32 ref_cnt;
+       struct list_head node_ref_to;   /* list node */
+       struct list_head node_ref_from; /* list node */
+       struct list_head collision_resolving_node;      /* list node */
+       struct btrfsic_block *block_ref_to;
+       struct btrfsic_block *block_ref_from;
+       u64 parent_generation;
+};
+
+struct btrfsic_dev_state {
+       u32 magic_num;          /* only used for debug purposes */
+       struct block_device *bdev;
+       struct btrfsic_state *state;
+       struct list_head collision_resolving_node;      /* list node */
+       struct btrfsic_block dummy_block_for_bio_bh_flush;
+       u64 last_flush_gen;
+       char name[BDEVNAME_SIZE];
+};
+
+struct btrfsic_block_hashtable {
+       struct list_head table[BTRFSIC_BLOCK_HASHTABLE_SIZE];
+};
+
+struct btrfsic_block_link_hashtable {
+       struct list_head table[BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE];
+};
+
+struct btrfsic_dev_state_hashtable {
+       struct list_head table[BTRFSIC_DEV2STATE_HASHTABLE_SIZE];
+};
+
+struct btrfsic_block_data_ctx {
+       u64 start;              /* virtual bytenr */
+       u64 dev_bytenr;         /* physical bytenr on device */
+       u32 len;
+       struct btrfsic_dev_state *dev;
+       char *data;
+       struct buffer_head *bh; /* do not use if set to NULL */
+};
+
+/* This structure is used to implement recursion without occupying
+ * any stack space, refer to btrfsic_process_metablock() */
+struct btrfsic_stack_frame {
+       u32 magic;
+       u32 nr;
+       int error;
+       int i;
+       int limit_nesting;
+       int num_copies;
+       int mirror_num;
+       struct btrfsic_block *block;
+       struct btrfsic_block_data_ctx *block_ctx;
+       struct btrfsic_block *next_block;
+       struct btrfsic_block_data_ctx next_block_ctx;
+       struct btrfs_header *hdr;
+       struct btrfsic_stack_frame *prev;
+};
+
+/* Some state per mounted filesystem */
+struct btrfsic_state {
+       u32 print_mask;
+       int include_extent_data;
+       int csum_size;
+       struct list_head all_blocks_list;
+       struct btrfsic_block_hashtable block_hashtable;
+       struct btrfsic_block_link_hashtable block_link_hashtable;
+       struct btrfs_root *root;
+       u64 max_superblock_generation;
+       struct btrfsic_block *latest_superblock;
+};
+
+static void btrfsic_block_init(struct btrfsic_block *b);
+static struct btrfsic_block *btrfsic_block_alloc(void);
+static void btrfsic_block_free(struct btrfsic_block *b);
+static void btrfsic_block_link_init(struct btrfsic_block_link *n);
+static struct btrfsic_block_link *btrfsic_block_link_alloc(void);
+static void btrfsic_block_link_free(struct btrfsic_block_link *n);
+static void btrfsic_dev_state_init(struct btrfsic_dev_state *ds);
+static struct btrfsic_dev_state *btrfsic_dev_state_alloc(void);
+static void btrfsic_dev_state_free(struct btrfsic_dev_state *ds);
+static void btrfsic_block_hashtable_init(struct btrfsic_block_hashtable *h);
+static void btrfsic_block_hashtable_add(struct btrfsic_block *b,
+                                       struct btrfsic_block_hashtable *h);
+static void btrfsic_block_hashtable_remove(struct btrfsic_block *b);
+static struct btrfsic_block *btrfsic_block_hashtable_lookup(
+               struct block_device *bdev,
+               u64 dev_bytenr,
+               struct btrfsic_block_hashtable *h);
+static void btrfsic_block_link_hashtable_init(
+               struct btrfsic_block_link_hashtable *h);
+static void btrfsic_block_link_hashtable_add(
+               struct btrfsic_block_link *l,
+               struct btrfsic_block_link_hashtable *h);
+static void btrfsic_block_link_hashtable_remove(struct btrfsic_block_link *l);
+static struct btrfsic_block_link *btrfsic_block_link_hashtable_lookup(
+               struct block_device *bdev_ref_to,
+               u64 dev_bytenr_ref_to,
+               struct block_device *bdev_ref_from,
+               u64 dev_bytenr_ref_from,
+               struct btrfsic_block_link_hashtable *h);
+static void btrfsic_dev_state_hashtable_init(
+               struct btrfsic_dev_state_hashtable *h);
+static void btrfsic_dev_state_hashtable_add(
+               struct btrfsic_dev_state *ds,
+               struct btrfsic_dev_state_hashtable *h);
+static void btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state *ds);
+static struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(
+               struct block_device *bdev,
+               struct btrfsic_dev_state_hashtable *h);
+static struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void);
+static void btrfsic_stack_frame_free(struct btrfsic_stack_frame *sf);
+static int btrfsic_process_superblock(struct btrfsic_state *state,
+                                     struct btrfs_fs_devices *fs_devices);
+static int btrfsic_process_metablock(struct btrfsic_state *state,
+                                    struct btrfsic_block *block,
+                                    struct btrfsic_block_data_ctx *block_ctx,
+                                    struct btrfs_header *hdr,
+                                    int limit_nesting, int force_iodone_flag);
+static int btrfsic_create_link_to_next_block(
+               struct btrfsic_state *state,
+               struct btrfsic_block *block,
+               struct btrfsic_block_data_ctx
+               *block_ctx, u64 next_bytenr,
+               int limit_nesting,
+               struct btrfsic_block_data_ctx *next_block_ctx,
+               struct btrfsic_block **next_blockp,
+               int force_iodone_flag,
+               int *num_copiesp, int *mirror_nump,
+               struct btrfs_disk_key *disk_key,
+               u64 parent_generation);
+static int btrfsic_handle_extent_data(struct btrfsic_state *state,
+                                     struct btrfsic_block *block,
+                                     struct btrfsic_block_data_ctx *block_ctx,
+                                     u32 item_offset, int force_iodone_flag);
+static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
+                            struct btrfsic_block_data_ctx *block_ctx_out,
+                            int mirror_num);
+static int btrfsic_map_superblock(struct btrfsic_state *state, u64 bytenr,
+                                 u32 len, struct block_device *bdev,
+                                 struct btrfsic_block_data_ctx *block_ctx_out);
+static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
+static int btrfsic_read_block(struct btrfsic_state *state,
+                             struct btrfsic_block_data_ctx *block_ctx);
+static void btrfsic_dump_database(struct btrfsic_state *state);
+static int btrfsic_test_for_metadata(struct btrfsic_state *state,
+                                    const u8 *data, unsigned int size);
+static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
+                                         u64 dev_bytenr, u8 *mapped_data,
+                                         unsigned int len, struct bio *bio,
+                                         int *bio_is_patched,
+                                         struct buffer_head *bh,
+                                         int submit_bio_bh_rw);
+static int btrfsic_process_written_superblock(
+               struct btrfsic_state *state,
+               struct btrfsic_block *const block,
+               struct btrfs_super_block *const super_hdr);
+static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status);
+static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate);
+static int btrfsic_is_block_ref_by_superblock(const struct btrfsic_state *state,
+                                             const struct btrfsic_block *block,
+                                             int recursion_level);
+static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
+                                       struct btrfsic_block *const block,
+                                       int recursion_level);
+static void btrfsic_print_add_link(const struct btrfsic_state *state,
+                                  const struct btrfsic_block_link *l);
+static void btrfsic_print_rem_link(const struct btrfsic_state *state,
+                                  const struct btrfsic_block_link *l);
+static char btrfsic_get_block_type(const struct btrfsic_state *state,
+                                  const struct btrfsic_block *block);
+static void btrfsic_dump_tree(const struct btrfsic_state *state);
+static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
+                                 const struct btrfsic_block *block,
+                                 int indent_level);
+static struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
+               struct btrfsic_state *state,
+               struct btrfsic_block_data_ctx *next_block_ctx,
+               struct btrfsic_block *next_block,
+               struct btrfsic_block *from_block,
+               u64 parent_generation);
+static struct btrfsic_block *btrfsic_block_lookup_or_add(
+               struct btrfsic_state *state,
+               struct btrfsic_block_data_ctx *block_ctx,
+               const char *additional_string,
+               int is_metadata,
+               int is_iodone,
+               int never_written,
+               int mirror_num,
+               int *was_created);
+static int btrfsic_process_superblock_dev_mirror(
+               struct btrfsic_state *state,
+               struct btrfsic_dev_state *dev_state,
+               struct btrfs_device *device,
+               int superblock_mirror_num,
+               struct btrfsic_dev_state **selected_dev_state,
+               struct btrfs_super_block *selected_super);
+static struct btrfsic_dev_state *btrfsic_dev_state_lookup(
+               struct block_device *bdev);
+static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
+                                          u64 bytenr,
+                                          struct btrfsic_dev_state *dev_state,
+                                          u64 dev_bytenr, char *data);
+
+static struct mutex btrfsic_mutex;
+static int btrfsic_is_initialized;
+static struct btrfsic_dev_state_hashtable btrfsic_dev_state_hashtable;
+
+
+static void btrfsic_block_init(struct btrfsic_block *b)
+{
+       b->magic_num = BTRFSIC_BLOCK_MAGIC_NUMBER;
+       b->dev_state = NULL;
+       b->dev_bytenr = 0;
+       b->logical_bytenr = 0;
+       b->generation = BTRFSIC_GENERATION_UNKNOWN;
+       b->disk_key.objectid = 0;
+       b->disk_key.type = 0;
+       b->disk_key.offset = 0;
+       b->is_metadata = 0;
+       b->is_superblock = 0;
+       b->is_iodone = 0;
+       b->iodone_w_error = 0;
+       b->never_written = 0;
+       b->mirror_num = 0;
+       b->next_in_same_bio = NULL;
+       b->orig_bio_bh_private = NULL;
+       b->orig_bio_bh_end_io.bio = NULL;
+       INIT_LIST_HEAD(&b->collision_resolving_node);
+       INIT_LIST_HEAD(&b->all_blocks_node);
+       INIT_LIST_HEAD(&b->ref_to_list);
+       INIT_LIST_HEAD(&b->ref_from_list);
+       b->submit_bio_bh_rw = 0;
+       b->flush_gen = 0;
+}
+
+static struct btrfsic_block *btrfsic_block_alloc(void)
+{
+       struct btrfsic_block *b;
+
+       b = kzalloc(sizeof(*b), GFP_NOFS);
+       if (NULL != b)
+               btrfsic_block_init(b);
+
+       return b;
+}
+
+static void btrfsic_block_free(struct btrfsic_block *b)
+{
+       BUG_ON(!(NULL == b || BTRFSIC_BLOCK_MAGIC_NUMBER == b->magic_num));
+       kfree(b);
+}
+
+static void btrfsic_block_link_init(struct btrfsic_block_link *l)
+{
+       l->magic_num = BTRFSIC_BLOCK_LINK_MAGIC_NUMBER;
+       l->ref_cnt = 1;
+       INIT_LIST_HEAD(&l->node_ref_to);
+       INIT_LIST_HEAD(&l->node_ref_from);
+       INIT_LIST_HEAD(&l->collision_resolving_node);
+       l->block_ref_to = NULL;
+       l->block_ref_from = NULL;
+}
+
+static struct btrfsic_block_link *btrfsic_block_link_alloc(void)
+{
+       struct btrfsic_block_link *l;
+
+       l = kzalloc(sizeof(*l), GFP_NOFS);
+       if (NULL != l)
+               btrfsic_block_link_init(l);
+
+       return l;
+}
+
+static void btrfsic_block_link_free(struct btrfsic_block_link *l)
+{
+       BUG_ON(!(NULL == l || BTRFSIC_BLOCK_LINK_MAGIC_NUMBER == l->magic_num));
+       kfree(l);
+}
+
+static void btrfsic_dev_state_init(struct btrfsic_dev_state *ds)
+{
+       ds->magic_num = BTRFSIC_DEV2STATE_MAGIC_NUMBER;
+       ds->bdev = NULL;
+       ds->state = NULL;
+       ds->name[0] = '\0';
+       INIT_LIST_HEAD(&ds->collision_resolving_node);
+       ds->last_flush_gen = 0;
+       btrfsic_block_init(&ds->dummy_block_for_bio_bh_flush);
+       ds->dummy_block_for_bio_bh_flush.is_iodone = 1;
+       ds->dummy_block_for_bio_bh_flush.dev_state = ds;
+}
+
+static struct btrfsic_dev_state *btrfsic_dev_state_alloc(void)
+{
+       struct btrfsic_dev_state *ds;
+
+       ds = kzalloc(sizeof(*ds), GFP_NOFS);
+       if (NULL != ds)
+               btrfsic_dev_state_init(ds);
+
+       return ds;
+}
+
+static void btrfsic_dev_state_free(struct btrfsic_dev_state *ds)
+{
+       BUG_ON(!(NULL == ds ||
+                BTRFSIC_DEV2STATE_MAGIC_NUMBER == ds->magic_num));
+       kfree(ds);
+}
+
+static void btrfsic_block_hashtable_init(struct btrfsic_block_hashtable *h)
+{
+       int i;
+
+       for (i = 0; i < BTRFSIC_BLOCK_HASHTABLE_SIZE; i++)
+               INIT_LIST_HEAD(h->table + i);
+}
+
+static void btrfsic_block_hashtable_add(struct btrfsic_block *b,
+                                       struct btrfsic_block_hashtable *h)
+{
+       const unsigned int hashval =
+           (((unsigned int)(b->dev_bytenr >> 16)) ^
+            ((unsigned int)((uintptr_t)b->dev_state->bdev))) &
+            (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1);
+
+       list_add(&b->collision_resolving_node, h->table + hashval);
+}
+
+static void btrfsic_block_hashtable_remove(struct btrfsic_block *b)
+{
+       list_del(&b->collision_resolving_node);
+}
+
+static struct btrfsic_block *btrfsic_block_hashtable_lookup(
+               struct block_device *bdev,
+               u64 dev_bytenr,
+               struct btrfsic_block_hashtable *h)
+{
+       const unsigned int hashval =
+           (((unsigned int)(dev_bytenr >> 16)) ^
+            ((unsigned int)((uintptr_t)bdev))) &
+            (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1);
+       struct list_head *elem;
+
+       list_for_each(elem, h->table + hashval) {
+               struct btrfsic_block *const b =
+                   list_entry(elem, struct btrfsic_block,
+                              collision_resolving_node);
+
+               if (b->dev_state->bdev == bdev && b->dev_bytenr == dev_bytenr)
+                       return b;
+       }
+
+       return NULL;
+}
+
+static void btrfsic_block_link_hashtable_init(
+               struct btrfsic_block_link_hashtable *h)
+{
+       int i;
+
+       for (i = 0; i < BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE; i++)
+               INIT_LIST_HEAD(h->table + i);
+}
+
+static void btrfsic_block_link_hashtable_add(
+               struct btrfsic_block_link *l,
+               struct btrfsic_block_link_hashtable *h)
+{
+       const unsigned int hashval =
+           (((unsigned int)(l->block_ref_to->dev_bytenr >> 16)) ^
+            ((unsigned int)(l->block_ref_from->dev_bytenr >> 16)) ^
+            ((unsigned int)((uintptr_t)l->block_ref_to->dev_state->bdev)) ^
+            ((unsigned int)((uintptr_t)l->block_ref_from->dev_state->bdev)))
+            & (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1);
+
+       BUG_ON(NULL == l->block_ref_to);
+       BUG_ON(NULL == l->block_ref_from);
+       list_add(&l->collision_resolving_node, h->table + hashval);
+}
+
+static void btrfsic_block_link_hashtable_remove(struct btrfsic_block_link *l)
+{
+       list_del(&l->collision_resolving_node);
+}
+
+static struct btrfsic_block_link *btrfsic_block_link_hashtable_lookup(
+               struct block_device *bdev_ref_to,
+               u64 dev_bytenr_ref_to,
+               struct block_device *bdev_ref_from,
+               u64 dev_bytenr_ref_from,
+               struct btrfsic_block_link_hashtable *h)
+{
+       const unsigned int hashval =
+           (((unsigned int)(dev_bytenr_ref_to >> 16)) ^
+            ((unsigned int)(dev_bytenr_ref_from >> 16)) ^
+            ((unsigned int)((uintptr_t)bdev_ref_to)) ^
+            ((unsigned int)((uintptr_t)bdev_ref_from))) &
+            (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1);
+       struct list_head *elem;
+
+       list_for_each(elem, h->table + hashval) {
+               struct btrfsic_block_link *const l =
+                   list_entry(elem, struct btrfsic_block_link,
+                              collision_resolving_node);
+
+               BUG_ON(NULL == l->block_ref_to);
+               BUG_ON(NULL == l->block_ref_from);
+               if (l->block_ref_to->dev_state->bdev == bdev_ref_to &&
+                   l->block_ref_to->dev_bytenr == dev_bytenr_ref_to &&
+                   l->block_ref_from->dev_state->bdev == bdev_ref_from &&
+                   l->block_ref_from->dev_bytenr == dev_bytenr_ref_from)
+                       return l;
+       }
+
+       return NULL;
+}
+
+static void btrfsic_dev_state_hashtable_init(
+               struct btrfsic_dev_state_hashtable *h)
+{
+       int i;
+
+       for (i = 0; i < BTRFSIC_DEV2STATE_HASHTABLE_SIZE; i++)
+               INIT_LIST_HEAD(h->table + i);
+}
+
+static void btrfsic_dev_state_hashtable_add(
+               struct btrfsic_dev_state *ds,
+               struct btrfsic_dev_state_hashtable *h)
+{
+       const unsigned int hashval =
+           (((unsigned int)((uintptr_t)ds->bdev)) &
+            (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1));
+
+       list_add(&ds->collision_resolving_node, h->table + hashval);
+}
+
+static void btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state *ds)
+{
+       list_del(&ds->collision_resolving_node);
+}
+
+static struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(
+               struct block_device *bdev,
+               struct btrfsic_dev_state_hashtable *h)
+{
+       const unsigned int hashval =
+           (((unsigned int)((uintptr_t)bdev)) &
+            (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1));
+       struct list_head *elem;
+
+       list_for_each(elem, h->table + hashval) {
+               struct btrfsic_dev_state *const ds =
+                   list_entry(elem, struct btrfsic_dev_state,
+                              collision_resolving_node);
+
+               if (ds->bdev == bdev)
+                       return ds;
+       }
+
+       return NULL;
+}
+
+static int btrfsic_process_superblock(struct btrfsic_state *state,
+                                     struct btrfs_fs_devices *fs_devices)
+{
+       int ret;
+       struct btrfs_super_block *selected_super;
+       struct list_head *dev_head = &fs_devices->devices;
+       struct btrfs_device *device;
+       struct btrfsic_dev_state *selected_dev_state = NULL;
+       int pass;
+
+       BUG_ON(NULL == state);
+       selected_super = kmalloc(sizeof(*selected_super), GFP_NOFS);
+       if (NULL == selected_super) {
+               printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+               return -1;
+       }
+
+       list_for_each_entry(device, dev_head, dev_list) {
+               int i;
+               struct btrfsic_dev_state *dev_state;
+
+               if (!device->bdev || !device->name)
+                       continue;
+
+               dev_state = btrfsic_dev_state_lookup(device->bdev);
+               BUG_ON(NULL == dev_state);
+               for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+                       ret = btrfsic_process_superblock_dev_mirror(
+                                       state, dev_state, device, i,
+                                       &selected_dev_state, selected_super);
+                       if (0 != ret && 0 == i) {
+                               kfree(selected_super);
+                               return ret;
+                       }
+               }
+       }
+
+       if (NULL == state->latest_superblock) {
+               printk(KERN_INFO "btrfsic: no superblock found!\n");
+               kfree(selected_super);
+               return -1;
+       }
+
+       state->csum_size = btrfs_super_csum_size(selected_super);
+
+       for (pass = 0; pass < 3; pass++) {
+               int num_copies;
+               int mirror_num;
+               u64 next_bytenr;
+
+               switch (pass) {
+               case 0:
+                       next_bytenr = btrfs_super_root(selected_super);
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
+                               printk(KERN_INFO "root@%llu\n",
+                                      (unsigned long long)next_bytenr);
+                       break;
+               case 1:
+                       next_bytenr = btrfs_super_chunk_root(selected_super);
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
+                               printk(KERN_INFO "chunk@%llu\n",
+                                      (unsigned long long)next_bytenr);
+                       break;
+               case 2:
+                       next_bytenr = btrfs_super_log_root(selected_super);
+                       if (0 == next_bytenr)
+                               continue;
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
+                               printk(KERN_INFO "log@%llu\n",
+                                      (unsigned long long)next_bytenr);
+                       break;
+               }
+
+               num_copies =
+                   btrfs_num_copies(&state->root->fs_info->mapping_tree,
+                                    next_bytenr, PAGE_SIZE);
+               if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
+                       printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+                              (unsigned long long)next_bytenr, num_copies);
+
+               for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
+                       struct btrfsic_block *next_block;
+                       struct btrfsic_block_data_ctx tmp_next_block_ctx;
+                       struct btrfsic_block_link *l;
+                       struct btrfs_header *hdr;
+
+                       ret = btrfsic_map_block(state, next_bytenr, PAGE_SIZE,
+                                               &tmp_next_block_ctx,
+                                               mirror_num);
+                       if (ret) {
+                               printk(KERN_INFO "btrfsic:"
+                                      " btrfsic_map_block(root @%llu,"
+                                      " mirror %d) failed!\n",
+                                      (unsigned long long)next_bytenr,
+                                      mirror_num);
+                               kfree(selected_super);
+                               return -1;
+                       }
+
+                       next_block = btrfsic_block_hashtable_lookup(
+                                       tmp_next_block_ctx.dev->bdev,
+                                       tmp_next_block_ctx.dev_bytenr,
+                                       &state->block_hashtable);
+                       BUG_ON(NULL == next_block);
+
+                       l = btrfsic_block_link_hashtable_lookup(
+                                       tmp_next_block_ctx.dev->bdev,
+                                       tmp_next_block_ctx.dev_bytenr,
+                                       state->latest_superblock->dev_state->
+                                       bdev,
+                                       state->latest_superblock->dev_bytenr,
+                                       &state->block_link_hashtable);
+                       BUG_ON(NULL == l);
+
+                       ret = btrfsic_read_block(state, &tmp_next_block_ctx);
+                       if (ret < (int)BTRFSIC_BLOCK_SIZE) {
+                               printk(KERN_INFO
+                                      "btrfsic: read @logical %llu failed!\n",
+                                      (unsigned long long)
+                                      tmp_next_block_ctx.start);
+                               btrfsic_release_block_ctx(&tmp_next_block_ctx);
+                               kfree(selected_super);
+                               return -1;
+                       }
+
+                       hdr = (struct btrfs_header *)tmp_next_block_ctx.data;
+                       ret = btrfsic_process_metablock(state,
+                                                       next_block,
+                                                       &tmp_next_block_ctx,
+                                                       hdr,
+                                                       BTRFS_MAX_LEVEL + 3, 1);
+                       btrfsic_release_block_ctx(&tmp_next_block_ctx);
+               }
+       }
+
+       kfree(selected_super);
+       return ret;
+}
+
+static int btrfsic_process_superblock_dev_mirror(
+               struct btrfsic_state *state,
+               struct btrfsic_dev_state *dev_state,
+               struct btrfs_device *device,
+               int superblock_mirror_num,
+               struct btrfsic_dev_state **selected_dev_state,
+               struct btrfs_super_block *selected_super)
+{
+       struct btrfs_super_block *super_tmp;
+       u64 dev_bytenr;
+       struct buffer_head *bh;
+       struct btrfsic_block *superblock_tmp;
+       int pass;
+       struct block_device *const superblock_bdev = device->bdev;
+
+       /* super block bytenr is always the unmapped device bytenr */
+       dev_bytenr = btrfs_sb_offset(superblock_mirror_num);
+       bh = __bread(superblock_bdev, dev_bytenr / 4096, 4096);
+       if (NULL == bh)
+               return -1;
+       super_tmp = (struct btrfs_super_block *)
+           (bh->b_data + (dev_bytenr & 4095));
+
+       if (btrfs_super_bytenr(super_tmp) != dev_bytenr ||
+           strncmp((char *)(&(super_tmp->magic)), BTRFS_MAGIC,
+                   sizeof(super_tmp->magic)) ||
+           memcmp(device->uuid, super_tmp->dev_item.uuid, BTRFS_UUID_SIZE)) {
+               brelse(bh);
+               return 0;
+       }
+
+       superblock_tmp =
+           btrfsic_block_hashtable_lookup(superblock_bdev,
+                                          dev_bytenr,
+                                          &state->block_hashtable);
+       if (NULL == superblock_tmp) {
+               superblock_tmp = btrfsic_block_alloc();
+               if (NULL == superblock_tmp) {
+                       printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+                       brelse(bh);
+                       return -1;
+               }
+               /* for superblock, only the dev_bytenr makes sense */
+               superblock_tmp->dev_bytenr = dev_bytenr;
+               superblock_tmp->dev_state = dev_state;
+               superblock_tmp->logical_bytenr = dev_bytenr;
+               superblock_tmp->generation = btrfs_super_generation(super_tmp);
+               superblock_tmp->is_metadata = 1;
+               superblock_tmp->is_superblock = 1;
+               superblock_tmp->is_iodone = 1;
+               superblock_tmp->never_written = 0;
+               superblock_tmp->mirror_num = 1 + superblock_mirror_num;
+               if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
+                       printk(KERN_INFO "New initial S-block (bdev %p, %s)"
+                              " @%llu (%s/%llu/%d)\n",
+                              superblock_bdev, device->name,
+                              (unsigned long long)dev_bytenr,
+                              dev_state->name,
+                              (unsigned long long)dev_bytenr,
+                              superblock_mirror_num);
+               list_add(&superblock_tmp->all_blocks_node,
+                        &state->all_blocks_list);
+               btrfsic_block_hashtable_add(superblock_tmp,
+                                           &state->block_hashtable);
+       }
+
+       /* select the one with the highest generation field */
+       if (btrfs_super_generation(super_tmp) >
+           state->max_superblock_generation ||
+           0 == state->max_superblock_generation) {
+               memcpy(selected_super, super_tmp, sizeof(*selected_super));
+               *selected_dev_state = dev_state;
+               state->max_superblock_generation =
+                   btrfs_super_generation(super_tmp);
+               state->latest_superblock = superblock_tmp;
+       }
+
+       for (pass = 0; pass < 3; pass++) {
+               u64 next_bytenr;
+               int num_copies;
+               int mirror_num;
+               const char *additional_string = NULL;
+               struct btrfs_disk_key tmp_disk_key;
+
+               tmp_disk_key.type = BTRFS_ROOT_ITEM_KEY;
+               tmp_disk_key.offset = 0;
+               switch (pass) {
+               case 0:
+                       tmp_disk_key.objectid =
+                           cpu_to_le64(BTRFS_ROOT_TREE_OBJECTID);
+                       additional_string = "initial root ";
+                       next_bytenr = btrfs_super_root(super_tmp);
+                       break;
+               case 1:
+                       tmp_disk_key.objectid =
+                           cpu_to_le64(BTRFS_CHUNK_TREE_OBJECTID);
+                       additional_string = "initial chunk ";
+                       next_bytenr = btrfs_super_chunk_root(super_tmp);
+                       break;
+               case 2:
+                       tmp_disk_key.objectid =
+                           cpu_to_le64(BTRFS_TREE_LOG_OBJECTID);
+                       additional_string = "initial log ";
+                       next_bytenr = btrfs_super_log_root(super_tmp);
+                       if (0 == next_bytenr)
+                               continue;
+                       break;
+               }
+
+               num_copies =
+                   btrfs_num_copies(&state->root->fs_info->mapping_tree,
+                                    next_bytenr, PAGE_SIZE);
+               if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
+                       printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+                              (unsigned long long)next_bytenr, num_copies);
+               for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
+                       struct btrfsic_block *next_block;
+                       struct btrfsic_block_data_ctx tmp_next_block_ctx;
+                       struct btrfsic_block_link *l;
+
+                       if (btrfsic_map_block(state, next_bytenr, PAGE_SIZE,
+                                             &tmp_next_block_ctx,
+                                             mirror_num)) {
+                               printk(KERN_INFO "btrfsic: btrfsic_map_block("
+                                      "bytenr @%llu, mirror %d) failed!\n",
+                                      (unsigned long long)next_bytenr,
+                                      mirror_num);
+                               brelse(bh);
+                               return -1;
+                       }
+
+                       next_block = btrfsic_block_lookup_or_add(
+                                       state, &tmp_next_block_ctx,
+                                       additional_string, 1, 1, 0,
+                                       mirror_num, NULL);
+                       if (NULL == next_block) {
+                               btrfsic_release_block_ctx(&tmp_next_block_ctx);
+                               brelse(bh);
+                               return -1;
+                       }
+
+                       next_block->disk_key = tmp_disk_key;
+                       next_block->generation = BTRFSIC_GENERATION_UNKNOWN;
+                       l = btrfsic_block_link_lookup_or_add(
+                                       state, &tmp_next_block_ctx,
+                                       next_block, superblock_tmp,
+                                       BTRFSIC_GENERATION_UNKNOWN);
+                       btrfsic_release_block_ctx(&tmp_next_block_ctx);
+                       if (NULL == l) {
+                               brelse(bh);
+                               return -1;
+                       }
+               }
+       }
+       if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES)
+               btrfsic_dump_tree_sub(state, superblock_tmp, 0);
+
+       brelse(bh);
+       return 0;
+}
+
+static struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void)
+{
+       struct btrfsic_stack_frame *sf;
+
+       sf = kzalloc(sizeof(*sf), GFP_NOFS);
+       if (NULL == sf)
+               printk(KERN_INFO "btrfsic: alloc memory failed!\n");
+       else
+               sf->magic = BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER;
+       return sf;
+}
+
+static void btrfsic_stack_frame_free(struct btrfsic_stack_frame *sf)
+{
+       BUG_ON(!(NULL == sf ||
+                BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER == sf->magic));
+       kfree(sf);
+}
+
+static int btrfsic_process_metablock(
+               struct btrfsic_state *state,
+               struct btrfsic_block *const first_block,
+               struct btrfsic_block_data_ctx *const first_block_ctx,
+               struct btrfs_header *const first_hdr,
+               int first_limit_nesting, int force_iodone_flag)
+{
+       struct btrfsic_stack_frame initial_stack_frame = { 0 };
+       struct btrfsic_stack_frame *sf;
+       struct btrfsic_stack_frame *next_stack;
+
+       sf = &initial_stack_frame;
+       sf->error = 0;
+       sf->i = -1;
+       sf->limit_nesting = first_limit_nesting;
+       sf->block = first_block;
+       sf->block_ctx = first_block_ctx;
+       sf->next_block = NULL;
+       sf->hdr = first_hdr;
+       sf->prev = NULL;
+
+continue_with_new_stack_frame:
+       sf->block->generation = le64_to_cpu(sf->hdr->generation);
+       if (0 == sf->hdr->level) {
+               struct btrfs_leaf *const leafhdr =
+                   (struct btrfs_leaf *)sf->hdr;
+
+               if (-1 == sf->i) {
+                       sf->nr = le32_to_cpu(leafhdr->header.nritems);
+
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO
+                                      "leaf %llu items %d generation %llu"
+                                      " owner %llu\n",
+                                      (unsigned long long)
+                                      sf->block_ctx->start,
+                                      sf->nr,
+                                      (unsigned long long)
+                                      le64_to_cpu(leafhdr->header.generation),
+                                      (unsigned long long)
+                                      le64_to_cpu(leafhdr->header.owner));
+               }
+
+continue_with_current_leaf_stack_frame:
+               if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) {
+                       sf->i++;
+                       sf->num_copies = 0;
+               }
+
+               if (sf->i < sf->nr) {
+                       struct btrfs_item *disk_item = leafhdr->items + sf->i;
+                       struct btrfs_disk_key *disk_key = &disk_item->key;
+                       u8 type;
+                       const u32 item_offset = le32_to_cpu(disk_item->offset);
+
+                       type = disk_key->type;
+
+                       if (BTRFS_ROOT_ITEM_KEY == type) {
+                               const struct btrfs_root_item *const root_item =
+                                   (struct btrfs_root_item *)
+                                   (sf->block_ctx->data +
+                                    offsetof(struct btrfs_leaf, items) +
+                                    item_offset);
+                               const u64 next_bytenr =
+                                   le64_to_cpu(root_item->bytenr);
+
+                               sf->error =
+                                   btrfsic_create_link_to_next_block(
+                                               state,
+                                               sf->block,
+                                               sf->block_ctx,
+                                               next_bytenr,
+                                               sf->limit_nesting,
+                                               &sf->next_block_ctx,
+                                               &sf->next_block,
+                                               force_iodone_flag,
+                                               &sf->num_copies,
+                                               &sf->mirror_num,
+                                               disk_key,
+                                               le64_to_cpu(root_item->
+                                               generation));
+                               if (sf->error)
+                                       goto one_stack_frame_backwards;
+
+                               if (NULL != sf->next_block) {
+                                       struct btrfs_header *const next_hdr =
+                                           (struct btrfs_header *)
+                                           sf->next_block_ctx.data;
+
+                                       next_stack =
+                                           btrfsic_stack_frame_alloc();
+                                       if (NULL == next_stack) {
+                                               btrfsic_release_block_ctx(
+                                                               &sf->
+                                                               next_block_ctx);
+                                               goto one_stack_frame_backwards;
+                                       }
+
+                                       next_stack->i = -1;
+                                       next_stack->block = sf->next_block;
+                                       next_stack->block_ctx =
+                                           &sf->next_block_ctx;
+                                       next_stack->next_block = NULL;
+                                       next_stack->hdr = next_hdr;
+                                       next_stack->limit_nesting =
+                                           sf->limit_nesting - 1;
+                                       next_stack->prev = sf;
+                                       sf = next_stack;
+                                       goto continue_with_new_stack_frame;
+                               }
+                       } else if (BTRFS_EXTENT_DATA_KEY == type &&
+                                  state->include_extent_data) {
+                               sf->error = btrfsic_handle_extent_data(
+                                               state,
+                                               sf->block,
+                                               sf->block_ctx,
+                                               item_offset,
+                                               force_iodone_flag);
+                               if (sf->error)
+                                       goto one_stack_frame_backwards;
+                       }
+
+                       goto continue_with_current_leaf_stack_frame;
+               }
+       } else {
+               struct btrfs_node *const nodehdr = (struct btrfs_node *)sf->hdr;
+
+               if (-1 == sf->i) {
+                       sf->nr = le32_to_cpu(nodehdr->header.nritems);
+
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO "node %llu level %d items %d"
+                                      " generation %llu owner %llu\n",
+                                      (unsigned long long)
+                                      sf->block_ctx->start,
+                                      nodehdr->header.level, sf->nr,
+                                      (unsigned long long)
+                                      le64_to_cpu(nodehdr->header.generation),
+                                      (unsigned long long)
+                                      le64_to_cpu(nodehdr->header.owner));
+               }
+
+continue_with_current_node_stack_frame:
+               if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) {
+                       sf->i++;
+                       sf->num_copies = 0;
+               }
+
+               if (sf->i < sf->nr) {
+                       struct btrfs_key_ptr *disk_key_ptr =
+                           nodehdr->ptrs + sf->i;
+                       const u64 next_bytenr =
+                           le64_to_cpu(disk_key_ptr->blockptr);
+
+                       sf->error = btrfsic_create_link_to_next_block(
+                                       state,
+                                       sf->block,
+                                       sf->block_ctx,
+                                       next_bytenr,
+                                       sf->limit_nesting,
+                                       &sf->next_block_ctx,
+                                       &sf->next_block,
+                                       force_iodone_flag,
+                                       &sf->num_copies,
+                                       &sf->mirror_num,
+                                       &disk_key_ptr->key,
+                                       le64_to_cpu(disk_key_ptr->generation));
+                       if (sf->error)
+                               goto one_stack_frame_backwards;
+
+                       if (NULL != sf->next_block) {
+                               struct btrfs_header *const next_hdr =
+                                   (struct btrfs_header *)
+                                   sf->next_block_ctx.data;
+
+                               next_stack = btrfsic_stack_frame_alloc();
+                               if (NULL == next_stack)
+                                       goto one_stack_frame_backwards;
+
+                               next_stack->i = -1;
+                               next_stack->block = sf->next_block;
+                               next_stack->block_ctx = &sf->next_block_ctx;
+                               next_stack->next_block = NULL;
+                               next_stack->hdr = next_hdr;
+                               next_stack->limit_nesting =
+                                   sf->limit_nesting - 1;
+                               next_stack->prev = sf;
+                               sf = next_stack;
+                               goto continue_with_new_stack_frame;
+                       }
+
+                       goto continue_with_current_node_stack_frame;
+               }
+       }
+
+one_stack_frame_backwards:
+       if (NULL != sf->prev) {
+               struct btrfsic_stack_frame *const prev = sf->prev;
+
+               /* the one for the initial block is freed in the caller */
+               btrfsic_release_block_ctx(sf->block_ctx);
+
+               if (sf->error) {
+                       prev->error = sf->error;
+                       btrfsic_stack_frame_free(sf);
+                       sf = prev;
+                       goto one_stack_frame_backwards;
+               }
+
+               btrfsic_stack_frame_free(sf);
+               sf = prev;
+               goto continue_with_new_stack_frame;
+       } else {
+               BUG_ON(&initial_stack_frame != sf);
+       }
+
+       return sf->error;
+}
+
+static int btrfsic_create_link_to_next_block(
+               struct btrfsic_state *state,
+               struct btrfsic_block *block,
+               struct btrfsic_block_data_ctx *block_ctx,
+               u64 next_bytenr,
+               int limit_nesting,
+               struct btrfsic_block_data_ctx *next_block_ctx,
+               struct btrfsic_block **next_blockp,
+               int force_iodone_flag,
+               int *num_copiesp, int *mirror_nump,
+               struct btrfs_disk_key *disk_key,
+               u64 parent_generation)
+{
+       struct btrfsic_block *next_block = NULL;
+       int ret;
+       struct btrfsic_block_link *l;
+       int did_alloc_block_link;
+       int block_was_created;
+
+       *next_blockp = NULL;
+       if (0 == *num_copiesp) {
+               *num_copiesp =
+                   btrfs_num_copies(&state->root->fs_info->mapping_tree,
+                                    next_bytenr, PAGE_SIZE);
+               if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
+                       printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+                              (unsigned long long)next_bytenr, *num_copiesp);
+               *mirror_nump = 1;
+       }
+
+       if (*mirror_nump > *num_copiesp)
+               return 0;
+
+       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+               printk(KERN_INFO
+                      "btrfsic_create_link_to_next_block(mirror_num=%d)\n",
+                      *mirror_nump);
+       ret = btrfsic_map_block(state, next_bytenr,
+                               BTRFSIC_BLOCK_SIZE,
+                               next_block_ctx, *mirror_nump);
+       if (ret) {
+               printk(KERN_INFO
+                      "btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
+                      (unsigned long long)next_bytenr, *mirror_nump);
+               btrfsic_release_block_ctx(next_block_ctx);
+               *next_blockp = NULL;
+               return -1;
+       }
+
+       next_block = btrfsic_block_lookup_or_add(state,
+                                                next_block_ctx, "referenced ",
+                                                1, force_iodone_flag,
+                                                !force_iodone_flag,
+                                                *mirror_nump,
+                                                &block_was_created);
+       if (NULL == next_block) {
+               btrfsic_release_block_ctx(next_block_ctx);
+               *next_blockp = NULL;
+               return -1;
+       }
+       if (block_was_created) {
+               l = NULL;
+               next_block->generation = BTRFSIC_GENERATION_UNKNOWN;
+       } else {
+               if (next_block->logical_bytenr != next_bytenr &&
+                   !(!next_block->is_metadata &&
+                     0 == next_block->logical_bytenr)) {
+                       printk(KERN_INFO
+                              "Referenced block @%llu (%s/%llu/%d)"
+                              " found in hash table, %c,"
+                              " bytenr mismatch (!= stored %llu).\n",
+                              (unsigned long long)next_bytenr,
+                              next_block_ctx->dev->name,
+                              (unsigned long long)next_block_ctx->dev_bytenr,
+                              *mirror_nump,
+                              btrfsic_get_block_type(state, next_block),
+                              (unsigned long long)next_block->logical_bytenr);
+               } else if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "Referenced block @%llu (%s/%llu/%d)"
+                              " found in hash table, %c.\n",
+                              (unsigned long long)next_bytenr,
+                              next_block_ctx->dev->name,
+                              (unsigned long long)next_block_ctx->dev_bytenr,
+                              *mirror_nump,
+                              btrfsic_get_block_type(state, next_block));
+               next_block->logical_bytenr = next_bytenr;
+
+               next_block->mirror_num = *mirror_nump;
+               l = btrfsic_block_link_hashtable_lookup(
+                               next_block_ctx->dev->bdev,
+                               next_block_ctx->dev_bytenr,
+                               block_ctx->dev->bdev,
+                               block_ctx->dev_bytenr,
+                               &state->block_link_hashtable);
+       }
+
+       next_block->disk_key = *disk_key;
+       if (NULL == l) {
+               l = btrfsic_block_link_alloc();
+               if (NULL == l) {
+                       printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+                       btrfsic_release_block_ctx(next_block_ctx);
+                       *next_blockp = NULL;
+                       return -1;
+               }
+
+               did_alloc_block_link = 1;
+               l->block_ref_to = next_block;
+               l->block_ref_from = block;
+               l->ref_cnt = 1;
+               l->parent_generation = parent_generation;
+
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       btrfsic_print_add_link(state, l);
+
+               list_add(&l->node_ref_to, &block->ref_to_list);
+               list_add(&l->node_ref_from, &next_block->ref_from_list);
+
+               btrfsic_block_link_hashtable_add(l,
+                                                &state->block_link_hashtable);
+       } else {
+               did_alloc_block_link = 0;
+               if (0 == limit_nesting) {
+                       l->ref_cnt++;
+                       l->parent_generation = parent_generation;
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               btrfsic_print_add_link(state, l);
+               }
+       }
+
+       if (limit_nesting > 0 && did_alloc_block_link) {
+               ret = btrfsic_read_block(state, next_block_ctx);
+               if (ret < (int)BTRFSIC_BLOCK_SIZE) {
+                       printk(KERN_INFO
+                              "btrfsic: read block @logical %llu failed!\n",
+                              (unsigned long long)next_bytenr);
+                       btrfsic_release_block_ctx(next_block_ctx);
+                       *next_blockp = NULL;
+                       return -1;
+               }
+
+               *next_blockp = next_block;
+       } else {
+               *next_blockp = NULL;
+       }
+       (*mirror_nump)++;
+
+       return 0;
+}
+
+static int btrfsic_handle_extent_data(
+               struct btrfsic_state *state,
+               struct btrfsic_block *block,
+               struct btrfsic_block_data_ctx *block_ctx,
+               u32 item_offset, int force_iodone_flag)
+{
+       int ret;
+       struct btrfs_file_extent_item *file_extent_item =
+           (struct btrfs_file_extent_item *)(block_ctx->data +
+                                             offsetof(struct btrfs_leaf,
+                                                      items) + item_offset);
+       u64 next_bytenr =
+           le64_to_cpu(file_extent_item->disk_bytenr) +
+           le64_to_cpu(file_extent_item->offset);
+       u64 num_bytes = le64_to_cpu(file_extent_item->num_bytes);
+       u64 generation = le64_to_cpu(file_extent_item->generation);
+       struct btrfsic_block_link *l;
+
+       if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
+               printk(KERN_INFO "extent_data: type %u, disk_bytenr = %llu,"
+                      " offset = %llu, num_bytes = %llu\n",
+                      file_extent_item->type,
+                      (unsigned long long)
+                      le64_to_cpu(file_extent_item->disk_bytenr),
+                      (unsigned long long)
+                      le64_to_cpu(file_extent_item->offset),
+                      (unsigned long long)
+                      le64_to_cpu(file_extent_item->num_bytes));
+       if (BTRFS_FILE_EXTENT_REG != file_extent_item->type ||
+           ((u64)0) == le64_to_cpu(file_extent_item->disk_bytenr))
+               return 0;
+       while (num_bytes > 0) {
+               u32 chunk_len;
+               int num_copies;
+               int mirror_num;
+
+               if (num_bytes > BTRFSIC_BLOCK_SIZE)
+                       chunk_len = BTRFSIC_BLOCK_SIZE;
+               else
+                       chunk_len = num_bytes;
+
+               num_copies =
+                   btrfs_num_copies(&state->root->fs_info->mapping_tree,
+                                    next_bytenr, PAGE_SIZE);
+               if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
+                       printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+                              (unsigned long long)next_bytenr, num_copies);
+               for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
+                       struct btrfsic_block_data_ctx next_block_ctx;
+                       struct btrfsic_block *next_block;
+                       int block_was_created;
+
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO "btrfsic_handle_extent_data("
+                                      "mirror_num=%d)\n", mirror_num);
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
+                               printk(KERN_INFO
+                                      "\tdisk_bytenr = %llu, num_bytes %u\n",
+                                      (unsigned long long)next_bytenr,
+                                      chunk_len);
+                       ret = btrfsic_map_block(state, next_bytenr,
+                                               chunk_len, &next_block_ctx,
+                                               mirror_num);
+                       if (ret) {
+                               printk(KERN_INFO
+                                      "btrfsic: btrfsic_map_block(@%llu,"
+                                      " mirror=%d) failed!\n",
+                                      (unsigned long long)next_bytenr,
+                                      mirror_num);
+                               return -1;
+                       }
+
+                       next_block = btrfsic_block_lookup_or_add(
+                                       state,
+                                       &next_block_ctx,
+                                       "referenced ",
+                                       0,
+                                       force_iodone_flag,
+                                       !force_iodone_flag,
+                                       mirror_num,
+                                       &block_was_created);
+                       if (NULL == next_block) {
+                               printk(KERN_INFO
+                                      "btrfsic: error, kmalloc failed!\n");
+                               btrfsic_release_block_ctx(&next_block_ctx);
+                               return -1;
+                       }
+                       if (!block_was_created) {
+                               if (next_block->logical_bytenr != next_bytenr &&
+                                   !(!next_block->is_metadata &&
+                                     0 == next_block->logical_bytenr)) {
+                                       printk(KERN_INFO
+                                              "Referenced block"
+                                              " @%llu (%s/%llu/%d)"
+                                              " found in hash table, D,"
+                                              " bytenr mismatch"
+                                              " (!= stored %llu).\n",
+                                              (unsigned long long)next_bytenr,
+                                              next_block_ctx.dev->name,
+                                              (unsigned long long)
+                                              next_block_ctx.dev_bytenr,
+                                              mirror_num,
+                                              (unsigned long long)
+                                              next_block->logical_bytenr);
+                               }
+                               next_block->logical_bytenr = next_bytenr;
+                               next_block->mirror_num = mirror_num;
+                       }
+
+                       l = btrfsic_block_link_lookup_or_add(state,
+                                                            &next_block_ctx,
+                                                            next_block, block,
+                                                            generation);
+                       btrfsic_release_block_ctx(&next_block_ctx);
+                       if (NULL == l)
+                               return -1;
+               }
+
+               next_bytenr += chunk_len;
+               num_bytes -= chunk_len;
+       }
+
+       return 0;
+}
+
+static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
+                            struct btrfsic_block_data_ctx *block_ctx_out,
+                            int mirror_num)
+{
+       int ret;
+       u64 length;
+       struct btrfs_bio *multi = NULL;
+       struct btrfs_device *device;
+
+       length = len;
+       ret = btrfs_map_block(&state->root->fs_info->mapping_tree, READ,
+                             bytenr, &length, &multi, mirror_num);
+
+       device = multi->stripes[0].dev;
+       block_ctx_out->dev = btrfsic_dev_state_lookup(device->bdev);
+       block_ctx_out->dev_bytenr = multi->stripes[0].physical;
+       block_ctx_out->start = bytenr;
+       block_ctx_out->len = len;
+       block_ctx_out->data = NULL;
+       block_ctx_out->bh = NULL;
+
+       if (0 == ret)
+               kfree(multi);
+       if (NULL == block_ctx_out->dev) {
+               ret = -ENXIO;
+               printk(KERN_INFO "btrfsic: error, cannot lookup dev (#1)!\n");
+       }
+
+       return ret;
+}
+
+static int btrfsic_map_superblock(struct btrfsic_state *state, u64 bytenr,
+                                 u32 len, struct block_device *bdev,
+                                 struct btrfsic_block_data_ctx *block_ctx_out)
+{
+       block_ctx_out->dev = btrfsic_dev_state_lookup(bdev);
+       block_ctx_out->dev_bytenr = bytenr;
+       block_ctx_out->start = bytenr;
+       block_ctx_out->len = len;
+       block_ctx_out->data = NULL;
+       block_ctx_out->bh = NULL;
+       if (NULL != block_ctx_out->dev) {
+               return 0;
+       } else {
+               printk(KERN_INFO "btrfsic: error, cannot lookup dev (#2)!\n");
+               return -ENXIO;
+       }
+}
+
+static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx)
+{
+       if (NULL != block_ctx->bh) {
+               brelse(block_ctx->bh);
+               block_ctx->bh = NULL;
+       }
+}
+
+static int btrfsic_read_block(struct btrfsic_state *state,
+                             struct btrfsic_block_data_ctx *block_ctx)
+{
+       block_ctx->bh = NULL;
+       if (block_ctx->dev_bytenr & 4095) {
+               printk(KERN_INFO
+                      "btrfsic: read_block() with unaligned bytenr %llu\n",
+                      (unsigned long long)block_ctx->dev_bytenr);
+               return -1;
+       }
+       if (block_ctx->len > 4096) {
+               printk(KERN_INFO
+                      "btrfsic: read_block() with too huge size %d\n",
+                      block_ctx->len);
+               return -1;
+       }
+
+       block_ctx->bh = __bread(block_ctx->dev->bdev,
+                               block_ctx->dev_bytenr >> 12, 4096);
+       if (NULL == block_ctx->bh)
+               return -1;
+       block_ctx->data = block_ctx->bh->b_data;
+
+       return block_ctx->len;
+}
+
+static void btrfsic_dump_database(struct btrfsic_state *state)
+{
+       struct list_head *elem_all;
+
+       BUG_ON(NULL == state);
+
+       printk(KERN_INFO "all_blocks_list:\n");
+       list_for_each(elem_all, &state->all_blocks_list) {
+               const struct btrfsic_block *const b_all =
+                   list_entry(elem_all, struct btrfsic_block,
+                              all_blocks_node);
+               struct list_head *elem_ref_to;
+               struct list_head *elem_ref_from;
+
+               printk(KERN_INFO "%c-block @%llu (%s/%llu/%d)\n",
+                      btrfsic_get_block_type(state, b_all),
+                      (unsigned long long)b_all->logical_bytenr,
+                      b_all->dev_state->name,
+                      (unsigned long long)b_all->dev_bytenr,
+                      b_all->mirror_num);
+
+               list_for_each(elem_ref_to, &b_all->ref_to_list) {
+                       const struct btrfsic_block_link *const l =
+                           list_entry(elem_ref_to,
+                                      struct btrfsic_block_link,
+                                      node_ref_to);
+
+                       printk(KERN_INFO " %c @%llu (%s/%llu/%d)"
+                              " refers %u* to"
+                              " %c @%llu (%s/%llu/%d)\n",
+                              btrfsic_get_block_type(state, b_all),
+                              (unsigned long long)b_all->logical_bytenr,
+                              b_all->dev_state->name,
+                              (unsigned long long)b_all->dev_bytenr,
+                              b_all->mirror_num,
+                              l->ref_cnt,
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num);
+               }
+
+               list_for_each(elem_ref_from, &b_all->ref_from_list) {
+                       const struct btrfsic_block_link *const l =
+                           list_entry(elem_ref_from,
+                                      struct btrfsic_block_link,
+                                      node_ref_from);
+
+                       printk(KERN_INFO " %c @%llu (%s/%llu/%d)"
+                              " is ref %u* from"
+                              " %c @%llu (%s/%llu/%d)\n",
+                              btrfsic_get_block_type(state, b_all),
+                              (unsigned long long)b_all->logical_bytenr,
+                              b_all->dev_state->name,
+                              (unsigned long long)b_all->dev_bytenr,
+                              b_all->mirror_num,
+                              l->ref_cnt,
+                              btrfsic_get_block_type(state, l->block_ref_from),
+                              (unsigned long long)
+                              l->block_ref_from->logical_bytenr,
+                              l->block_ref_from->dev_state->name,
+                              (unsigned long long)
+                              l->block_ref_from->dev_bytenr,
+                              l->block_ref_from->mirror_num);
+               }
+
+               printk(KERN_INFO "\n");
+       }
+}
+
+/*
+ * Test whether the disk block contains a tree block (leaf or node)
+ * (note that this test fails for the super block)
+ */
+static int btrfsic_test_for_metadata(struct btrfsic_state *state,
+                                    const u8 *data, unsigned int size)
+{
+       struct btrfs_header *h;
+       u8 csum[BTRFS_CSUM_SIZE];
+       u32 crc = ~(u32)0;
+       int fail = 0;
+       int crc_fail = 0;
+
+       h = (struct btrfs_header *)data;
+
+       if (memcmp(h->fsid, state->root->fs_info->fsid, BTRFS_UUID_SIZE))
+               fail++;
+
+       crc = crc32c(crc, data + BTRFS_CSUM_SIZE, PAGE_SIZE - BTRFS_CSUM_SIZE);
+       btrfs_csum_final(crc, csum);
+       if (memcmp(csum, h->csum, state->csum_size))
+               crc_fail++;
+
+       return fail || crc_fail;
+}
+
+static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
+                                         u64 dev_bytenr,
+                                         u8 *mapped_data, unsigned int len,
+                                         struct bio *bio,
+                                         int *bio_is_patched,
+                                         struct buffer_head *bh,
+                                         int submit_bio_bh_rw)
+{
+       int is_metadata;
+       struct btrfsic_block *block;
+       struct btrfsic_block_data_ctx block_ctx;
+       int ret;
+       struct btrfsic_state *state = dev_state->state;
+       struct block_device *bdev = dev_state->bdev;
+
+       WARN_ON(len > PAGE_SIZE);
+       is_metadata = (0 == btrfsic_test_for_metadata(state, mapped_data, len));
+       if (NULL != bio_is_patched)
+               *bio_is_patched = 0;
+
+       block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr,
+                                              &state->block_hashtable);
+       if (NULL != block) {
+               u64 bytenr = 0;
+               struct list_head *elem_ref_to;
+               struct list_head *tmp_ref_to;
+
+               if (block->is_superblock) {
+                       bytenr = le64_to_cpu(((struct btrfs_super_block *)
+                                             mapped_data)->bytenr);
+                       is_metadata = 1;
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE) {
+                               printk(KERN_INFO
+                                      "[before new superblock is written]:\n");
+                               btrfsic_dump_tree_sub(state, block, 0);
+                       }
+               }
+               if (is_metadata) {
+                       if (!block->is_superblock) {
+                               bytenr = le64_to_cpu(((struct btrfs_header *)
+                                                     mapped_data)->bytenr);
+                               btrfsic_cmp_log_and_dev_bytenr(state, bytenr,
+                                                              dev_state,
+                                                              dev_bytenr,
+                                                              mapped_data);
+                       }
+                       if (block->logical_bytenr != bytenr) {
+                               printk(KERN_INFO
+                                      "Written block @%llu (%s/%llu/%d)"
+                                      " found in hash table, %c,"
+                                      " bytenr mismatch"
+                                      " (!= stored %llu).\n",
+                                      (unsigned long long)bytenr,
+                                      dev_state->name,
+                                      (unsigned long long)dev_bytenr,
+                                      block->mirror_num,
+                                      btrfsic_get_block_type(state, block),
+                                      (unsigned long long)
+                                      block->logical_bytenr);
+                               block->logical_bytenr = bytenr;
+                       } else if (state->print_mask &
+                                  BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO
+                                      "Written block @%llu (%s/%llu/%d)"
+                                      " found in hash table, %c.\n",
+                                      (unsigned long long)bytenr,
+                                      dev_state->name,
+                                      (unsigned long long)dev_bytenr,
+                                      block->mirror_num,
+                                      btrfsic_get_block_type(state, block));
+               } else {
+                       bytenr = block->logical_bytenr;
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO
+                                      "Written block @%llu (%s/%llu/%d)"
+                                      " found in hash table, %c.\n",
+                                      (unsigned long long)bytenr,
+                                      dev_state->name,
+                                      (unsigned long long)dev_bytenr,
+                                      block->mirror_num,
+                                      btrfsic_get_block_type(state, block));
+               }
+
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "ref_to_list: %cE, ref_from_list: %cE\n",
+                              list_empty(&block->ref_to_list) ? ' ' : '!',
+                              list_empty(&block->ref_from_list) ? ' ' : '!');
+               if (btrfsic_is_block_ref_by_superblock(state, block, 0)) {
+                       printk(KERN_INFO "btrfs: attempt to overwrite %c-block"
+                              " @%llu (%s/%llu/%d), old(gen=%llu,"
+                              " objectid=%llu, type=%d, offset=%llu),"
+                              " new(gen=%llu),"
+                              " which is referenced by most recent superblock"
+                              " (superblockgen=%llu)!\n",
+                              btrfsic_get_block_type(state, block),
+                              (unsigned long long)bytenr,
+                              dev_state->name,
+                              (unsigned long long)dev_bytenr,
+                              block->mirror_num,
+                              (unsigned long long)block->generation,
+                              (unsigned long long)
+                              le64_to_cpu(block->disk_key.objectid),
+                              block->disk_key.type,
+                              (unsigned long long)
+                              le64_to_cpu(block->disk_key.offset),
+                              (unsigned long long)
+                              le64_to_cpu(((struct btrfs_header *)
+                                           mapped_data)->generation),
+                              (unsigned long long)
+                              state->max_superblock_generation);
+                       btrfsic_dump_tree(state);
+               }
+
+               if (!block->is_iodone && !block->never_written) {
+                       printk(KERN_INFO "btrfs: attempt to overwrite %c-block"
+                              " @%llu (%s/%llu/%d), oldgen=%llu, newgen=%llu,"
+                              " which is not yet iodone!\n",
+                              btrfsic_get_block_type(state, block),
+                              (unsigned long long)bytenr,
+                              dev_state->name,
+                              (unsigned long long)dev_bytenr,
+                              block->mirror_num,
+                              (unsigned long long)block->generation,
+                              (unsigned long long)
+                              le64_to_cpu(((struct btrfs_header *)
+                                           mapped_data)->generation));
+                       /* it would not be safe to go on */
+                       btrfsic_dump_tree(state);
+                       return;
+               }
+
+               /*
+                * Clear all references of this block. Do not free
+                * the block itself even if is not referenced anymore
+                * because it still carries valueable information
+                * like whether it was ever written and IO completed.
+                */
+               list_for_each_safe(elem_ref_to, tmp_ref_to,
+                                  &block->ref_to_list) {
+                       struct btrfsic_block_link *const l =
+                           list_entry(elem_ref_to,
+                                      struct btrfsic_block_link,
+                                      node_ref_to);
+
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               btrfsic_print_rem_link(state, l);
+                       l->ref_cnt--;
+                       if (0 == l->ref_cnt) {
+                               list_del(&l->node_ref_to);
+                               list_del(&l->node_ref_from);
+                               btrfsic_block_link_hashtable_remove(l);
+                               btrfsic_block_link_free(l);
+                       }
+               }
+
+               if (block->is_superblock)
+                       ret = btrfsic_map_superblock(state, bytenr, len,
+                                                    bdev, &block_ctx);
+               else
+                       ret = btrfsic_map_block(state, bytenr, len,
+                                               &block_ctx, 0);
+               if (ret) {
+                       printk(KERN_INFO
+                              "btrfsic: btrfsic_map_block(root @%llu)"
+                              " failed!\n", (unsigned long long)bytenr);
+                       return;
+               }
+               block_ctx.data = mapped_data;
+               /* the following is required in case of writes to mirrors,
+                * use the same that was used for the lookup */
+               block_ctx.dev = dev_state;
+               block_ctx.dev_bytenr = dev_bytenr;
+
+               if (is_metadata || state->include_extent_data) {
+                       block->never_written = 0;
+                       block->iodone_w_error = 0;
+                       if (NULL != bio) {
+                               block->is_iodone = 0;
+                               BUG_ON(NULL == bio_is_patched);
+                               if (!*bio_is_patched) {
+                                       block->orig_bio_bh_private =
+                                           bio->bi_private;
+                                       block->orig_bio_bh_end_io.bio =
+                                           bio->bi_end_io;
+                                       block->next_in_same_bio = NULL;
+                                       bio->bi_private = block;
+                                       bio->bi_end_io = btrfsic_bio_end_io;
+                                       *bio_is_patched = 1;
+                               } else {
+                                       struct btrfsic_block *chained_block =
+                                           (struct btrfsic_block *)
+                                           bio->bi_private;
+
+                                       BUG_ON(NULL == chained_block);
+                                       block->orig_bio_bh_private =
+                                           chained_block->orig_bio_bh_private;
+                                       block->orig_bio_bh_end_io.bio =
+                                           chained_block->orig_bio_bh_end_io.
+                                           bio;
+                                       block->next_in_same_bio = chained_block;
+                                       bio->bi_private = block;
+                               }
+                       } else if (NULL != bh) {
+                               block->is_iodone = 0;
+                               block->orig_bio_bh_private = bh->b_private;
+                               block->orig_bio_bh_end_io.bh = bh->b_end_io;
+                               block->next_in_same_bio = NULL;
+                               bh->b_private = block;
+                               bh->b_end_io = btrfsic_bh_end_io;
+                       } else {
+                               block->is_iodone = 1;
+                               block->orig_bio_bh_private = NULL;
+                               block->orig_bio_bh_end_io.bio = NULL;
+                               block->next_in_same_bio = NULL;
+                       }
+               }
+
+               block->flush_gen = dev_state->last_flush_gen + 1;
+               block->submit_bio_bh_rw = submit_bio_bh_rw;
+               if (is_metadata) {
+                       block->logical_bytenr = bytenr;
+                       block->is_metadata = 1;
+                       if (block->is_superblock) {
+                               ret = btrfsic_process_written_superblock(
+                                               state,
+                                               block,
+                                               (struct btrfs_super_block *)
+                                               mapped_data);
+                               if (state->print_mask &
+                                   BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE) {
+                                       printk(KERN_INFO
+                                       "[after new superblock is written]:\n");
+                                       btrfsic_dump_tree_sub(state, block, 0);
+                               }
+                       } else {
+                               block->mirror_num = 0;  /* unknown */
+                               ret = btrfsic_process_metablock(
+                                               state,
+                                               block,
+                                               &block_ctx,
+                                               (struct btrfs_header *)
+                                               block_ctx.data,
+                                               0, 0);
+                       }
+                       if (ret)
+                               printk(KERN_INFO
+                                      "btrfsic: btrfsic_process_metablock"
+                                      "(root @%llu) failed!\n",
+                                      (unsigned long long)dev_bytenr);
+               } else {
+                       block->is_metadata = 0;
+                       block->mirror_num = 0;  /* unknown */
+                       block->generation = BTRFSIC_GENERATION_UNKNOWN;
+                       if (!state->include_extent_data
+                           && list_empty(&block->ref_from_list)) {
+                               /*
+                                * disk block is overwritten with extent
+                                * data (not meta data) and we are configured
+                                * to not include extent data: take the
+                                * chance and free the block's memory
+                                */
+                               btrfsic_block_hashtable_remove(block);
+                               list_del(&block->all_blocks_node);
+                               btrfsic_block_free(block);
+                       }
+               }
+               btrfsic_release_block_ctx(&block_ctx);
+       } else {
+               /* block has not been found in hash table */
+               u64 bytenr;
+
+               if (!is_metadata) {
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO "Written block (%s/%llu/?)"
+                                      " !found in hash table, D.\n",
+                                      dev_state->name,
+                                      (unsigned long long)dev_bytenr);
+                       if (!state->include_extent_data)
+                               return; /* ignore that written D block */
+
+                       /* this is getting ugly for the
+                        * include_extent_data case... */
+                       bytenr = 0;     /* unknown */
+                       block_ctx.start = bytenr;
+                       block_ctx.len = len;
+                       block_ctx.bh = NULL;
+               } else {
+                       bytenr = le64_to_cpu(((struct btrfs_header *)
+                                             mapped_data)->bytenr);
+                       btrfsic_cmp_log_and_dev_bytenr(state, bytenr, dev_state,
+                                                      dev_bytenr,
+                                                      mapped_data);
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO
+                                      "Written block @%llu (%s/%llu/?)"
+                                      " !found in hash table, M.\n",
+                                      (unsigned long long)bytenr,
+                                      dev_state->name,
+                                      (unsigned long long)dev_bytenr);
+
+                       ret = btrfsic_map_block(state, bytenr, len, &block_ctx,
+                                               0);
+                       if (ret) {
+                               printk(KERN_INFO
+                                      "btrfsic: btrfsic_map_block(root @%llu)"
+                                      " failed!\n",
+                                      (unsigned long long)dev_bytenr);
+                               return;
+                       }
+               }
+               block_ctx.data = mapped_data;
+               /* the following is required in case of writes to mirrors,
+                * use the same that was used for the lookup */
+               block_ctx.dev = dev_state;
+               block_ctx.dev_bytenr = dev_bytenr;
+
+               block = btrfsic_block_alloc();
+               if (NULL == block) {
+                       printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+                       btrfsic_release_block_ctx(&block_ctx);
+                       return;
+               }
+               block->dev_state = dev_state;
+               block->dev_bytenr = dev_bytenr;
+               block->logical_bytenr = bytenr;
+               block->is_metadata = is_metadata;
+               block->never_written = 0;
+               block->iodone_w_error = 0;
+               block->mirror_num = 0;  /* unknown */
+               block->flush_gen = dev_state->last_flush_gen + 1;
+               block->submit_bio_bh_rw = submit_bio_bh_rw;
+               if (NULL != bio) {
+                       block->is_iodone = 0;
+                       BUG_ON(NULL == bio_is_patched);
+                       if (!*bio_is_patched) {
+                               block->orig_bio_bh_private = bio->bi_private;
+                               block->orig_bio_bh_end_io.bio = bio->bi_end_io;
+                               block->next_in_same_bio = NULL;
+                               bio->bi_private = block;
+                               bio->bi_end_io = btrfsic_bio_end_io;
+                               *bio_is_patched = 1;
+                       } else {
+                               struct btrfsic_block *chained_block =
+                                   (struct btrfsic_block *)
+                                   bio->bi_private;
+
+                               BUG_ON(NULL == chained_block);
+                               block->orig_bio_bh_private =
+                                   chained_block->orig_bio_bh_private;
+                               block->orig_bio_bh_end_io.bio =
+                                   chained_block->orig_bio_bh_end_io.bio;
+                               block->next_in_same_bio = chained_block;
+                               bio->bi_private = block;
+                       }
+               } else if (NULL != bh) {
+                       block->is_iodone = 0;
+                       block->orig_bio_bh_private = bh->b_private;
+                       block->orig_bio_bh_end_io.bh = bh->b_end_io;
+                       block->next_in_same_bio = NULL;
+                       bh->b_private = block;
+                       bh->b_end_io = btrfsic_bh_end_io;
+               } else {
+                       block->is_iodone = 1;
+                       block->orig_bio_bh_private = NULL;
+                       block->orig_bio_bh_end_io.bio = NULL;
+                       block->next_in_same_bio = NULL;
+               }
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "New written %c-block @%llu (%s/%llu/%d)\n",
+                              is_metadata ? 'M' : 'D',
+                              (unsigned long long)block->logical_bytenr,
+                              block->dev_state->name,
+                              (unsigned long long)block->dev_bytenr,
+                              block->mirror_num);
+               list_add(&block->all_blocks_node, &state->all_blocks_list);
+               btrfsic_block_hashtable_add(block, &state->block_hashtable);
+
+               if (is_metadata) {
+                       ret = btrfsic_process_metablock(state, block,
+                                                       &block_ctx,
+                                                       (struct btrfs_header *)
+                                                       block_ctx.data, 0, 0);
+                       if (ret)
+                               printk(KERN_INFO
+                                      "btrfsic: process_metablock(root @%llu)"
+                                      " failed!\n",
+                                      (unsigned long long)dev_bytenr);
+               }
+               btrfsic_release_block_ctx(&block_ctx);
+       }
+}
+
+static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status)
+{
+       struct btrfsic_block *block = (struct btrfsic_block *)bp->bi_private;
+       int iodone_w_error;
+
+       /* mutex is not held! This is not save if IO is not yet completed
+        * on umount */
+       iodone_w_error = 0;
+       if (bio_error_status)
+               iodone_w_error = 1;
+
+       BUG_ON(NULL == block);
+       bp->bi_private = block->orig_bio_bh_private;
+       bp->bi_end_io = block->orig_bio_bh_end_io.bio;
+
+       do {
+               struct btrfsic_block *next_block;
+               struct btrfsic_dev_state *const dev_state = block->dev_state;
+
+               if ((dev_state->state->print_mask &
+                    BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
+                       printk(KERN_INFO
+                              "bio_end_io(err=%d) for %c @%llu (%s/%llu/%d)\n",
+                              bio_error_status,
+                              btrfsic_get_block_type(dev_state->state, block),
+                              (unsigned long long)block->logical_bytenr,
+                              dev_state->name,
+                              (unsigned long long)block->dev_bytenr,
+                              block->mirror_num);
+               next_block = block->next_in_same_bio;
+               block->iodone_w_error = iodone_w_error;
+               if (block->submit_bio_bh_rw & REQ_FLUSH) {
+                       dev_state->last_flush_gen++;
+                       if ((dev_state->state->print_mask &
+                            BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
+                               printk(KERN_INFO
+                                      "bio_end_io() new %s flush_gen=%llu\n",
+                                      dev_state->name,
+                                      (unsigned long long)
+                                      dev_state->last_flush_gen);
+               }
+               if (block->submit_bio_bh_rw & REQ_FUA)
+                       block->flush_gen = 0; /* FUA completed means block is
+                                              * on disk */
+               block->is_iodone = 1; /* for FLUSH, this releases the block */
+               block = next_block;
+       } while (NULL != block);
+
+       bp->bi_end_io(bp, bio_error_status);
+}
+
+static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate)
+{
+       struct btrfsic_block *block = (struct btrfsic_block *)bh->b_private;
+       int iodone_w_error = !uptodate;
+       struct btrfsic_dev_state *dev_state;
+
+       BUG_ON(NULL == block);
+       dev_state = block->dev_state;
+       if ((dev_state->state->print_mask & BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
+               printk(KERN_INFO
+                      "bh_end_io(error=%d) for %c @%llu (%s/%llu/%d)\n",
+                      iodone_w_error,
+                      btrfsic_get_block_type(dev_state->state, block),
+                      (unsigned long long)block->logical_bytenr,
+                      block->dev_state->name,
+                      (unsigned long long)block->dev_bytenr,
+                      block->mirror_num);
+
+       block->iodone_w_error = iodone_w_error;
+       if (block->submit_bio_bh_rw & REQ_FLUSH) {
+               dev_state->last_flush_gen++;
+               if ((dev_state->state->print_mask &
+                    BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
+                       printk(KERN_INFO
+                              "bh_end_io() new %s flush_gen=%llu\n",
+                              dev_state->name,
+                              (unsigned long long)dev_state->last_flush_gen);
+       }
+       if (block->submit_bio_bh_rw & REQ_FUA)
+               block->flush_gen = 0; /* FUA completed means block is on disk */
+
+       bh->b_private = block->orig_bio_bh_private;
+       bh->b_end_io = block->orig_bio_bh_end_io.bh;
+       block->is_iodone = 1; /* for FLUSH, this releases the block */
+       bh->b_end_io(bh, uptodate);
+}
+
+static int btrfsic_process_written_superblock(
+               struct btrfsic_state *state,
+               struct btrfsic_block *const superblock,
+               struct btrfs_super_block *const super_hdr)
+{
+       int pass;
+
+       superblock->generation = btrfs_super_generation(super_hdr);
+       if (!(superblock->generation > state->max_superblock_generation ||
+             0 == state->max_superblock_generation)) {
+               if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
+                       printk(KERN_INFO
+                              "btrfsic: superblock @%llu (%s/%llu/%d)"
+                              " with old gen %llu <= %llu\n",
+                              (unsigned long long)superblock->logical_bytenr,
+                              superblock->dev_state->name,
+                              (unsigned long long)superblock->dev_bytenr,
+                              superblock->mirror_num,
+                              (unsigned long long)
+                              btrfs_super_generation(super_hdr),
+                              (unsigned long long)
+                              state->max_superblock_generation);
+       } else {
+               if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
+                       printk(KERN_INFO
+                              "btrfsic: got new superblock @%llu (%s/%llu/%d)"
+                              " with new gen %llu > %llu\n",
+                              (unsigned long long)superblock->logical_bytenr,
+                              superblock->dev_state->name,
+                              (unsigned long long)superblock->dev_bytenr,
+                              superblock->mirror_num,
+                              (unsigned long long)
+                              btrfs_super_generation(super_hdr),
+                              (unsigned long long)
+                              state->max_superblock_generation);
+
+               state->max_superblock_generation =
+                   btrfs_super_generation(super_hdr);
+               state->latest_superblock = superblock;
+       }
+
+       for (pass = 0; pass < 3; pass++) {
+               int ret;
+               u64 next_bytenr;
+               struct btrfsic_block *next_block;
+               struct btrfsic_block_data_ctx tmp_next_block_ctx;
+               struct btrfsic_block_link *l;
+               int num_copies;
+               int mirror_num;
+               const char *additional_string = NULL;
+               struct btrfs_disk_key tmp_disk_key;
+
+               tmp_disk_key.type = BTRFS_ROOT_ITEM_KEY;
+               tmp_disk_key.offset = 0;
+
+               switch (pass) {
+               case 0:
+                       tmp_disk_key.objectid =
+                           cpu_to_le64(BTRFS_ROOT_TREE_OBJECTID);
+                       additional_string = "root ";
+                       next_bytenr = btrfs_super_root(super_hdr);
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
+                               printk(KERN_INFO "root@%llu\n",
+                                      (unsigned long long)next_bytenr);
+                       break;
+               case 1:
+                       tmp_disk_key.objectid =
+                           cpu_to_le64(BTRFS_CHUNK_TREE_OBJECTID);
+                       additional_string = "chunk ";
+                       next_bytenr = btrfs_super_chunk_root(super_hdr);
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
+                               printk(KERN_INFO "chunk@%llu\n",
+                                      (unsigned long long)next_bytenr);
+                       break;
+               case 2:
+                       tmp_disk_key.objectid =
+                           cpu_to_le64(BTRFS_TREE_LOG_OBJECTID);
+                       additional_string = "log ";
+                       next_bytenr = btrfs_super_log_root(super_hdr);
+                       if (0 == next_bytenr)
+                               continue;
+                       if (state->print_mask &
+                           BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
+                               printk(KERN_INFO "log@%llu\n",
+                                      (unsigned long long)next_bytenr);
+                       break;
+               }
+
+               num_copies =
+                   btrfs_num_copies(&state->root->fs_info->mapping_tree,
+                                    next_bytenr, PAGE_SIZE);
+               if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
+                       printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+                              (unsigned long long)next_bytenr, num_copies);
+               for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
+                       int was_created;
+
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               printk(KERN_INFO
+                                      "btrfsic_process_written_superblock("
+                                      "mirror_num=%d)\n", mirror_num);
+                       ret = btrfsic_map_block(state, next_bytenr, PAGE_SIZE,
+                                               &tmp_next_block_ctx,
+                                               mirror_num);
+                       if (ret) {
+                               printk(KERN_INFO
+                                      "btrfsic: btrfsic_map_block(@%llu,"
+                                      " mirror=%d) failed!\n",
+                                      (unsigned long long)next_bytenr,
+                                      mirror_num);
+                               return -1;
+                       }
+
+                       next_block = btrfsic_block_lookup_or_add(
+                                       state,
+                                       &tmp_next_block_ctx,
+                                       additional_string,
+                                       1, 0, 1,
+                                       mirror_num,
+                                       &was_created);
+                       if (NULL == next_block) {
+                               printk(KERN_INFO
+                                      "btrfsic: error, kmalloc failed!\n");
+                               btrfsic_release_block_ctx(&tmp_next_block_ctx);
+                               return -1;
+                       }
+
+                       next_block->disk_key = tmp_disk_key;
+                       if (was_created)
+                               next_block->generation =
+                                   BTRFSIC_GENERATION_UNKNOWN;
+                       l = btrfsic_block_link_lookup_or_add(
+                                       state,
+                                       &tmp_next_block_ctx,
+                                       next_block,
+                                       superblock,
+                                       BTRFSIC_GENERATION_UNKNOWN);
+                       btrfsic_release_block_ctx(&tmp_next_block_ctx);
+                       if (NULL == l)
+                               return -1;
+               }
+       }
+
+       if (-1 == btrfsic_check_all_ref_blocks(state, superblock, 0)) {
+               WARN_ON(1);
+               btrfsic_dump_tree(state);
+       }
+
+       return 0;
+}
+
+static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
+                                       struct btrfsic_block *const block,
+                                       int recursion_level)
+{
+       struct list_head *elem_ref_to;
+       int ret = 0;
+
+       if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
+               /*
+                * Note that this situation can happen and does not
+                * indicate an error in regular cases. It happens
+                * when disk blocks are freed and later reused.
+                * The check-integrity module is not aware of any
+                * block free operations, it just recognizes block
+                * write operations. Therefore it keeps the linkage
+                * information for a block until a block is
+                * rewritten. This can temporarily cause incorrect
+                * and even circular linkage informations. This
+                * causes no harm unless such blocks are referenced
+                * by the most recent super block.
+                */
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "btrfsic: abort cyclic linkage (case 1).\n");
+
+               return ret;
+       }
+
+       /*
+        * This algorithm is recursive because the amount of used stack
+        * space is very small and the max recursion depth is limited.
+        */
+       list_for_each(elem_ref_to, &block->ref_to_list) {
+               const struct btrfsic_block_link *const l =
+                   list_entry(elem_ref_to, struct btrfsic_block_link,
+                              node_ref_to);
+
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "rl=%d, %c @%llu (%s/%llu/%d)"
+                              " %u* refers to %c @%llu (%s/%llu/%d)\n",
+                              recursion_level,
+                              btrfsic_get_block_type(state, block),
+                              (unsigned long long)block->logical_bytenr,
+                              block->dev_state->name,
+                              (unsigned long long)block->dev_bytenr,
+                              block->mirror_num,
+                              l->ref_cnt,
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num);
+               if (l->block_ref_to->never_written) {
+                       printk(KERN_INFO "btrfs: attempt to write superblock"
+                              " which references block %c @%llu (%s/%llu/%d)"
+                              " which is never written!\n",
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num);
+                       ret = -1;
+               } else if (!l->block_ref_to->is_iodone) {
+                       printk(KERN_INFO "btrfs: attempt to write superblock"
+                              " which references block %c @%llu (%s/%llu/%d)"
+                              " which is not yet iodone!\n",
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num);
+                       ret = -1;
+               } else if (l->parent_generation !=
+                          l->block_ref_to->generation &&
+                          BTRFSIC_GENERATION_UNKNOWN !=
+                          l->parent_generation &&
+                          BTRFSIC_GENERATION_UNKNOWN !=
+                          l->block_ref_to->generation) {
+                       printk(KERN_INFO "btrfs: attempt to write superblock"
+                              " which references block %c @%llu (%s/%llu/%d)"
+                              " with generation %llu !="
+                              " parent generation %llu!\n",
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num,
+                              (unsigned long long)l->block_ref_to->generation,
+                              (unsigned long long)l->parent_generation);
+                       ret = -1;
+               } else if (l->block_ref_to->flush_gen >
+                          l->block_ref_to->dev_state->last_flush_gen) {
+                       printk(KERN_INFO "btrfs: attempt to write superblock"
+                              " which references block %c @%llu (%s/%llu/%d)"
+                              " which is not flushed out of disk's write cache"
+                              " (block flush_gen=%llu,"
+                              " dev->flush_gen=%llu)!\n",
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num,
+                              (unsigned long long)block->flush_gen,
+                              (unsigned long long)
+                              l->block_ref_to->dev_state->last_flush_gen);
+                       ret = -1;
+               } else if (-1 == btrfsic_check_all_ref_blocks(state,
+                                                             l->block_ref_to,
+                                                             recursion_level +
+                                                             1)) {
+                       ret = -1;
+               }
+       }
+
+       return ret;
+}
+
+static int btrfsic_is_block_ref_by_superblock(
+               const struct btrfsic_state *state,
+               const struct btrfsic_block *block,
+               int recursion_level)
+{
+       struct list_head *elem_ref_from;
+
+       if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
+               /* refer to comment at "abort cyclic linkage (case 1)" */
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "btrfsic: abort cyclic linkage (case 2).\n");
+
+               return 0;
+       }
+
+       /*
+        * This algorithm is recursive because the amount of used stack space
+        * is very small and the max recursion depth is limited.
+        */
+       list_for_each(elem_ref_from, &block->ref_from_list) {
+               const struct btrfsic_block_link *const l =
+                   list_entry(elem_ref_from, struct btrfsic_block_link,
+                              node_ref_from);
+
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "rl=%d, %c @%llu (%s/%llu/%d)"
+                              " is ref %u* from %c @%llu (%s/%llu/%d)\n",
+                              recursion_level,
+                              btrfsic_get_block_type(state, block),
+                              (unsigned long long)block->logical_bytenr,
+                              block->dev_state->name,
+                              (unsigned long long)block->dev_bytenr,
+                              block->mirror_num,
+                              l->ref_cnt,
+                              btrfsic_get_block_type(state, l->block_ref_from),
+                              (unsigned long long)
+                              l->block_ref_from->logical_bytenr,
+                              l->block_ref_from->dev_state->name,
+                              (unsigned long long)
+                              l->block_ref_from->dev_bytenr,
+                              l->block_ref_from->mirror_num);
+               if (l->block_ref_from->is_superblock &&
+                   state->latest_superblock->dev_bytenr ==
+                   l->block_ref_from->dev_bytenr &&
+                   state->latest_superblock->dev_state->bdev ==
+                   l->block_ref_from->dev_state->bdev)
+                       return 1;
+               else if (btrfsic_is_block_ref_by_superblock(state,
+                                                           l->block_ref_from,
+                                                           recursion_level +
+                                                           1))
+                       return 1;
+       }
+
+       return 0;
+}
+
+static void btrfsic_print_add_link(const struct btrfsic_state *state,
+                                  const struct btrfsic_block_link *l)
+{
+       printk(KERN_INFO
+              "Add %u* link from %c @%llu (%s/%llu/%d)"
+              " to %c @%llu (%s/%llu/%d).\n",
+              l->ref_cnt,
+              btrfsic_get_block_type(state, l->block_ref_from),
+              (unsigned long long)l->block_ref_from->logical_bytenr,
+              l->block_ref_from->dev_state->name,
+              (unsigned long long)l->block_ref_from->dev_bytenr,
+              l->block_ref_from->mirror_num,
+              btrfsic_get_block_type(state, l->block_ref_to),
+              (unsigned long long)l->block_ref_to->logical_bytenr,
+              l->block_ref_to->dev_state->name,
+              (unsigned long long)l->block_ref_to->dev_bytenr,
+              l->block_ref_to->mirror_num);
+}
+
+static void btrfsic_print_rem_link(const struct btrfsic_state *state,
+                                  const struct btrfsic_block_link *l)
+{
+       printk(KERN_INFO
+              "Rem %u* link from %c @%llu (%s/%llu/%d)"
+              " to %c @%llu (%s/%llu/%d).\n",
+              l->ref_cnt,
+              btrfsic_get_block_type(state, l->block_ref_from),
+              (unsigned long long)l->block_ref_from->logical_bytenr,
+              l->block_ref_from->dev_state->name,
+              (unsigned long long)l->block_ref_from->dev_bytenr,
+              l->block_ref_from->mirror_num,
+              btrfsic_get_block_type(state, l->block_ref_to),
+              (unsigned long long)l->block_ref_to->logical_bytenr,
+              l->block_ref_to->dev_state->name,
+              (unsigned long long)l->block_ref_to->dev_bytenr,
+              l->block_ref_to->mirror_num);
+}
+
+static char btrfsic_get_block_type(const struct btrfsic_state *state,
+                                  const struct btrfsic_block *block)
+{
+       if (block->is_superblock &&
+           state->latest_superblock->dev_bytenr == block->dev_bytenr &&
+           state->latest_superblock->dev_state->bdev == block->dev_state->bdev)
+               return 'S';
+       else if (block->is_superblock)
+               return 's';
+       else if (block->is_metadata)
+               return 'M';
+       else
+               return 'D';
+}
+
+static void btrfsic_dump_tree(const struct btrfsic_state *state)
+{
+       btrfsic_dump_tree_sub(state, state->latest_superblock, 0);
+}
+
+static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
+                                 const struct btrfsic_block *block,
+                                 int indent_level)
+{
+       struct list_head *elem_ref_to;
+       int indent_add;
+       static char buf[80];
+       int cursor_position;
+
+       /*
+        * Should better fill an on-stack buffer with a complete line and
+        * dump it at once when it is time to print a newline character.
+        */
+
+       /*
+        * This algorithm is recursive because the amount of used stack space
+        * is very small and the max recursion depth is limited.
+        */
+       indent_add = sprintf(buf, "%c-%llu(%s/%llu/%d)",
+                            btrfsic_get_block_type(state, block),
+                            (unsigned long long)block->logical_bytenr,
+                            block->dev_state->name,
+                            (unsigned long long)block->dev_bytenr,
+                            block->mirror_num);
+       if (indent_level + indent_add > BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) {
+               printk("[...]\n");
+               return;
+       }
+       printk(buf);
+       indent_level += indent_add;
+       if (list_empty(&block->ref_to_list)) {
+               printk("\n");
+               return;
+       }
+       if (block->mirror_num > 1 &&
+           !(state->print_mask & BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS)) {
+               printk(" [...]\n");
+               return;
+       }
+
+       cursor_position = indent_level;
+       list_for_each(elem_ref_to, &block->ref_to_list) {
+               const struct btrfsic_block_link *const l =
+                   list_entry(elem_ref_to, struct btrfsic_block_link,
+                              node_ref_to);
+
+               while (cursor_position < indent_level) {
+                       printk(" ");
+                       cursor_position++;
+               }
+               if (l->ref_cnt > 1)
+                       indent_add = sprintf(buf, " %d*--> ", l->ref_cnt);
+               else
+                       indent_add = sprintf(buf, " --> ");
+               if (indent_level + indent_add >
+                   BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) {
+                       printk("[...]\n");
+                       cursor_position = 0;
+                       continue;
+               }
+
+               printk(buf);
+
+               btrfsic_dump_tree_sub(state, l->block_ref_to,
+                                     indent_level + indent_add);
+               cursor_position = 0;
+       }
+}
+
+static struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
+               struct btrfsic_state *state,
+               struct btrfsic_block_data_ctx *next_block_ctx,
+               struct btrfsic_block *next_block,
+               struct btrfsic_block *from_block,
+               u64 parent_generation)
+{
+       struct btrfsic_block_link *l;
+
+       l = btrfsic_block_link_hashtable_lookup(next_block_ctx->dev->bdev,
+                                               next_block_ctx->dev_bytenr,
+                                               from_block->dev_state->bdev,
+                                               from_block->dev_bytenr,
+                                               &state->block_link_hashtable);
+       if (NULL == l) {
+               l = btrfsic_block_link_alloc();
+               if (NULL == l) {
+                       printk(KERN_INFO
+                              "btrfsic: error, kmalloc" " failed!\n");
+                       return NULL;
+               }
+
+               l->block_ref_to = next_block;
+               l->block_ref_from = from_block;
+               l->ref_cnt = 1;
+               l->parent_generation = parent_generation;
+
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       btrfsic_print_add_link(state, l);
+
+               list_add(&l->node_ref_to, &from_block->ref_to_list);
+               list_add(&l->node_ref_from, &next_block->ref_from_list);
+
+               btrfsic_block_link_hashtable_add(l,
+                                                &state->block_link_hashtable);
+       } else {
+               l->ref_cnt++;
+               l->parent_generation = parent_generation;
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       btrfsic_print_add_link(state, l);
+       }
+
+       return l;
+}
+
+static struct btrfsic_block *btrfsic_block_lookup_or_add(
+               struct btrfsic_state *state,
+               struct btrfsic_block_data_ctx *block_ctx,
+               const char *additional_string,
+               int is_metadata,
+               int is_iodone,
+               int never_written,
+               int mirror_num,
+               int *was_created)
+{
+       struct btrfsic_block *block;
+
+       block = btrfsic_block_hashtable_lookup(block_ctx->dev->bdev,
+                                              block_ctx->dev_bytenr,
+                                              &state->block_hashtable);
+       if (NULL == block) {
+               struct btrfsic_dev_state *dev_state;
+
+               block = btrfsic_block_alloc();
+               if (NULL == block) {
+                       printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+                       return NULL;
+               }
+               dev_state = btrfsic_dev_state_lookup(block_ctx->dev->bdev);
+               if (NULL == dev_state) {
+                       printk(KERN_INFO
+                              "btrfsic: error, lookup dev_state failed!\n");
+                       btrfsic_block_free(block);
+                       return NULL;
+               }
+               block->dev_state = dev_state;
+               block->dev_bytenr = block_ctx->dev_bytenr;
+               block->logical_bytenr = block_ctx->start;
+               block->is_metadata = is_metadata;
+               block->is_iodone = is_iodone;
+               block->never_written = never_written;
+               block->mirror_num = mirror_num;
+               if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                       printk(KERN_INFO
+                              "New %s%c-block @%llu (%s/%llu/%d)\n",
+                              additional_string,
+                              btrfsic_get_block_type(state, block),
+                              (unsigned long long)block->logical_bytenr,
+                              dev_state->name,
+                              (unsigned long long)block->dev_bytenr,
+                              mirror_num);
+               list_add(&block->all_blocks_node, &state->all_blocks_list);
+               btrfsic_block_hashtable_add(block, &state->block_hashtable);
+               if (NULL != was_created)
+                       *was_created = 1;
+       } else {
+               if (NULL != was_created)
+                       *was_created = 0;
+       }
+
+       return block;
+}
+
+static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
+                                          u64 bytenr,
+                                          struct btrfsic_dev_state *dev_state,
+                                          u64 dev_bytenr, char *data)
+{
+       int num_copies;
+       int mirror_num;
+       int ret;
+       struct btrfsic_block_data_ctx block_ctx;
+       int match = 0;
+
+       num_copies = btrfs_num_copies(&state->root->fs_info->mapping_tree,
+                                     bytenr, PAGE_SIZE);
+
+       for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
+               ret = btrfsic_map_block(state, bytenr, PAGE_SIZE,
+                                       &block_ctx, mirror_num);
+               if (ret) {
+                       printk(KERN_INFO "btrfsic:"
+                              " btrfsic_map_block(logical @%llu,"
+                              " mirror %d) failed!\n",
+                              (unsigned long long)bytenr, mirror_num);
+                       continue;
+               }
+
+               if (dev_state->bdev == block_ctx.dev->bdev &&
+                   dev_bytenr == block_ctx.dev_bytenr) {
+                       match++;
+                       btrfsic_release_block_ctx(&block_ctx);
+                       break;
+               }
+               btrfsic_release_block_ctx(&block_ctx);
+       }
+
+       if (!match) {
+               printk(KERN_INFO "btrfs: attempt to write M-block which contains logical bytenr that doesn't map to dev+physical bytenr of submit_bio,"
+                      " buffer->log_bytenr=%llu, submit_bio(bdev=%s,"
+                      " phys_bytenr=%llu)!\n",
+                      (unsigned long long)bytenr, dev_state->name,
+                      (unsigned long long)dev_bytenr);
+               for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
+                       ret = btrfsic_map_block(state, bytenr, PAGE_SIZE,
+                                               &block_ctx, mirror_num);
+                       if (ret)
+                               continue;
+
+                       printk(KERN_INFO "Read logical bytenr @%llu maps to"
+                              " (%s/%llu/%d)\n",
+                              (unsigned long long)bytenr,
+                              block_ctx.dev->name,
+                              (unsigned long long)block_ctx.dev_bytenr,
+                              mirror_num);
+               }
+               WARN_ON(1);
+       }
+}
+
+static struct btrfsic_dev_state *btrfsic_dev_state_lookup(
+               struct block_device *bdev)
+{
+       struct btrfsic_dev_state *ds;
+
+       ds = btrfsic_dev_state_hashtable_lookup(bdev,
+                                               &btrfsic_dev_state_hashtable);
+       return ds;
+}
+
+int btrfsic_submit_bh(int rw, struct buffer_head *bh)
+{
+       struct btrfsic_dev_state *dev_state;
+
+       if (!btrfsic_is_initialized)
+               return submit_bh(rw, bh);
+
+       mutex_lock(&btrfsic_mutex);
+       /* since btrfsic_submit_bh() might also be called before
+        * btrfsic_mount(), this might return NULL */
+       dev_state = btrfsic_dev_state_lookup(bh->b_bdev);
+
+       /* Only called to write the superblock (incl. FLUSH/FUA) */
+       if (NULL != dev_state &&
+           (rw & WRITE) && bh->b_size > 0) {
+               u64 dev_bytenr;
+
+               dev_bytenr = 4096 * bh->b_blocknr;
+               if (dev_state->state->print_mask &
+                   BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
+                       printk(KERN_INFO
+                              "submit_bh(rw=0x%x, blocknr=%lu (bytenr %llu),"
+                              " size=%lu, data=%p, bdev=%p)\n",
+                              rw, (unsigned long)bh->b_blocknr,
+                              (unsigned long long)dev_bytenr,
+                              (unsigned long)bh->b_size, bh->b_data,
+                              bh->b_bdev);
+               btrfsic_process_written_block(dev_state, dev_bytenr,
+                                             bh->b_data, bh->b_size, NULL,
+                                             NULL, bh, rw);
+       } else if (NULL != dev_state && (rw & REQ_FLUSH)) {
+               if (dev_state->state->print_mask &
+                   BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
+                       printk(KERN_INFO
+                              "submit_bh(rw=0x%x) FLUSH, bdev=%p)\n",
+                              rw, bh->b_bdev);
+               if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
+                       if ((dev_state->state->print_mask &
+                            (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
+                             BTRFSIC_PRINT_MASK_VERBOSE)))
+                               printk(KERN_INFO
+                                      "btrfsic_submit_bh(%s) with FLUSH"
+                                      " but dummy block already in use"
+                                      " (ignored)!\n",
+                                      dev_state->name);
+               } else {
+                       struct btrfsic_block *const block =
+                               &dev_state->dummy_block_for_bio_bh_flush;
+
+                       block->is_iodone = 0;
+                       block->never_written = 0;
+                       block->iodone_w_error = 0;
+                       block->flush_gen = dev_state->last_flush_gen + 1;
+                       block->submit_bio_bh_rw = rw;
+                       block->orig_bio_bh_private = bh->b_private;
+                       block->orig_bio_bh_end_io.bh = bh->b_end_io;
+                       block->next_in_same_bio = NULL;
+                       bh->b_private = block;
+                       bh->b_end_io = btrfsic_bh_end_io;
+               }
+       }
+       mutex_unlock(&btrfsic_mutex);
+       return submit_bh(rw, bh);
+}
+
+void btrfsic_submit_bio(int rw, struct bio *bio)
+{
+       struct btrfsic_dev_state *dev_state;
+
+       if (!btrfsic_is_initialized) {
+               submit_bio(rw, bio);
+               return;
+       }
+
+       mutex_lock(&btrfsic_mutex);
+       /* since btrfsic_submit_bio() is also called before
+        * btrfsic_mount(), this might return NULL */
+       dev_state = btrfsic_dev_state_lookup(bio->bi_bdev);
+       if (NULL != dev_state &&
+           (rw & WRITE) && NULL != bio->bi_io_vec) {
+               unsigned int i;
+               u64 dev_bytenr;
+               int bio_is_patched;
+
+               dev_bytenr = 512 * bio->bi_sector;
+               bio_is_patched = 0;
+               if (dev_state->state->print_mask &
+                   BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
+                       printk(KERN_INFO
+                              "submit_bio(rw=0x%x, bi_vcnt=%u,"
+                              " bi_sector=%lu (bytenr %llu), bi_bdev=%p)\n",
+                              rw, bio->bi_vcnt, (unsigned long)bio->bi_sector,
+                              (unsigned long long)dev_bytenr,
+                              bio->bi_bdev);
+
+               for (i = 0; i < bio->bi_vcnt; i++) {
+                       u8 *mapped_data;
+
+                       mapped_data = kmap(bio->bi_io_vec[i].bv_page);
+                       if ((BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
+                            BTRFSIC_PRINT_MASK_VERBOSE) ==
+                           (dev_state->state->print_mask &
+                            (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
+                             BTRFSIC_PRINT_MASK_VERBOSE)))
+                               printk(KERN_INFO
+                                      "#%u: page=%p, mapped=%p, len=%u,"
+                                      " offset=%u\n",
+                                      i, bio->bi_io_vec[i].bv_page,
+                                      mapped_data,
+                                      bio->bi_io_vec[i].bv_len,
+                                      bio->bi_io_vec[i].bv_offset);
+                       btrfsic_process_written_block(dev_state, dev_bytenr,
+                                                     mapped_data,
+                                                     bio->bi_io_vec[i].bv_len,
+                                                     bio, &bio_is_patched,
+                                                     NULL, rw);
+                       kunmap(bio->bi_io_vec[i].bv_page);
+                       dev_bytenr += bio->bi_io_vec[i].bv_len;
+               }
+       } else if (NULL != dev_state && (rw & REQ_FLUSH)) {
+               if (dev_state->state->print_mask &
+                   BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
+                       printk(KERN_INFO
+                              "submit_bio(rw=0x%x) FLUSH, bdev=%p)\n",
+                              rw, bio->bi_bdev);
+               if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
+                       if ((dev_state->state->print_mask &
+                            (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
+                             BTRFSIC_PRINT_MASK_VERBOSE)))
+                               printk(KERN_INFO
+                                      "btrfsic_submit_bio(%s) with FLUSH"
+                                      " but dummy block already in use"
+                                      " (ignored)!\n",
+                                      dev_state->name);
+               } else {
+                       struct btrfsic_block *const block =
+                               &dev_state->dummy_block_for_bio_bh_flush;
+
+                       block->is_iodone = 0;
+                       block->never_written = 0;
+                       block->iodone_w_error = 0;
+                       block->flush_gen = dev_state->last_flush_gen + 1;
+                       block->submit_bio_bh_rw = rw;
+                       block->orig_bio_bh_private = bio->bi_private;
+                       block->orig_bio_bh_end_io.bio = bio->bi_end_io;
+                       block->next_in_same_bio = NULL;
+                       bio->bi_private = block;
+                       bio->bi_end_io = btrfsic_bio_end_io;
+               }
+       }
+       mutex_unlock(&btrfsic_mutex);
+
+       submit_bio(rw, bio);
+}
+
+int btrfsic_mount(struct btrfs_root *root,
+                 struct btrfs_fs_devices *fs_devices,
+                 int including_extent_data, u32 print_mask)
+{
+       int ret;
+       struct btrfsic_state *state;
+       struct list_head *dev_head = &fs_devices->devices;
+       struct btrfs_device *device;
+
+       state = kzalloc(sizeof(*state), GFP_NOFS);
+       if (NULL == state) {
+               printk(KERN_INFO "btrfs check-integrity: kmalloc() failed!\n");
+               return -1;
+       }
+
+       if (!btrfsic_is_initialized) {
+               mutex_init(&btrfsic_mutex);
+               btrfsic_dev_state_hashtable_init(&btrfsic_dev_state_hashtable);
+               btrfsic_is_initialized = 1;
+       }
+       mutex_lock(&btrfsic_mutex);
+       state->root = root;
+       state->print_mask = print_mask;
+       state->include_extent_data = including_extent_data;
+       state->csum_size = 0;
+       INIT_LIST_HEAD(&state->all_blocks_list);
+       btrfsic_block_hashtable_init(&state->block_hashtable);
+       btrfsic_block_link_hashtable_init(&state->block_link_hashtable);
+       state->max_superblock_generation = 0;
+       state->latest_superblock = NULL;
+
+       list_for_each_entry(device, dev_head, dev_list) {
+               struct btrfsic_dev_state *ds;
+               char *p;
+
+               if (!device->bdev || !device->name)
+                       continue;
+
+               ds = btrfsic_dev_state_alloc();
+               if (NULL == ds) {
+                       printk(KERN_INFO
+                              "btrfs check-integrity: kmalloc() failed!\n");
+                       mutex_unlock(&btrfsic_mutex);
+                       return -1;
+               }
+               ds->bdev = device->bdev;
+               ds->state = state;
+               bdevname(ds->bdev, ds->name);
+               ds->name[BDEVNAME_SIZE - 1] = '\0';
+               for (p = ds->name; *p != '\0'; p++);
+               while (p > ds->name && *p != '/')
+                       p--;
+               if (*p == '/')
+                       p++;
+               strlcpy(ds->name, p, sizeof(ds->name));
+               btrfsic_dev_state_hashtable_add(ds,
+                                               &btrfsic_dev_state_hashtable);
+       }
+
+       ret = btrfsic_process_superblock(state, fs_devices);
+       if (0 != ret) {
+               mutex_unlock(&btrfsic_mutex);
+               btrfsic_unmount(root, fs_devices);
+               return ret;
+       }
+
+       if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_DATABASE)
+               btrfsic_dump_database(state);
+       if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_TREE)
+               btrfsic_dump_tree(state);
+
+       mutex_unlock(&btrfsic_mutex);
+       return 0;
+}
+
+void btrfsic_unmount(struct btrfs_root *root,
+                    struct btrfs_fs_devices *fs_devices)
+{
+       struct list_head *elem_all;
+       struct list_head *tmp_all;
+       struct btrfsic_state *state;
+       struct list_head *dev_head = &fs_devices->devices;
+       struct btrfs_device *device;
+
+       if (!btrfsic_is_initialized)
+               return;
+
+       mutex_lock(&btrfsic_mutex);
+
+       state = NULL;
+       list_for_each_entry(device, dev_head, dev_list) {
+               struct btrfsic_dev_state *ds;
+
+               if (!device->bdev || !device->name)
+                       continue;
+
+               ds = btrfsic_dev_state_hashtable_lookup(
+                               device->bdev,
+                               &btrfsic_dev_state_hashtable);
+               if (NULL != ds) {
+                       state = ds->state;
+                       btrfsic_dev_state_hashtable_remove(ds);
+                       btrfsic_dev_state_free(ds);
+               }
+       }
+
+       if (NULL == state) {
+               printk(KERN_INFO
+                      "btrfsic: error, cannot find state information"
+                      " on umount!\n");
+               mutex_unlock(&btrfsic_mutex);
+               return;
+       }
+
+       /*
+        * Don't care about keeping the lists' state up to date,
+        * just free all memory that was allocated dynamically.
+        * Free the blocks and the block_links.
+        */
+       list_for_each_safe(elem_all, tmp_all, &state->all_blocks_list) {
+               struct btrfsic_block *const b_all =
+                   list_entry(elem_all, struct btrfsic_block,
+                              all_blocks_node);
+               struct list_head *elem_ref_to;
+               struct list_head *tmp_ref_to;
+
+               list_for_each_safe(elem_ref_to, tmp_ref_to,
+                                  &b_all->ref_to_list) {
+                       struct btrfsic_block_link *const l =
+                           list_entry(elem_ref_to,
+                                      struct btrfsic_block_link,
+                                      node_ref_to);
+
+                       if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
+                               btrfsic_print_rem_link(state, l);
+
+                       l->ref_cnt--;
+                       if (0 == l->ref_cnt)
+                               btrfsic_block_link_free(l);
+               }
+
+               if (b_all->is_iodone)
+                       btrfsic_block_free(b_all);
+               else
+                       printk(KERN_INFO "btrfs: attempt to free %c-block"
+                              " @%llu (%s/%llu/%d) on umount which is"
+                              " not yet iodone!\n",
+                              btrfsic_get_block_type(state, b_all),
+                              (unsigned long long)b_all->logical_bytenr,
+                              b_all->dev_state->name,
+                              (unsigned long long)b_all->dev_bytenr,
+                              b_all->mirror_num);
+       }
+
+       mutex_unlock(&btrfsic_mutex);
+
+       kfree(state);
+}
diff --git a/fs/btrfs/check-integrity.h b/fs/btrfs/check-integrity.h
new file mode 100644 (file)
index 0000000..8b59175
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) STRATO AG 2011.  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 v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#if !defined(__BTRFS_CHECK_INTEGRITY__)
+#define __BTRFS_CHECK_INTEGRITY__
+
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+int btrfsic_submit_bh(int rw, struct buffer_head *bh);
+void btrfsic_submit_bio(int rw, struct bio *bio);
+#else
+#define btrfsic_submit_bh submit_bh
+#define btrfsic_submit_bio submit_bio
+#endif
+
+int btrfsic_mount(struct btrfs_root *root,
+                 struct btrfs_fs_devices *fs_devices,
+                 int including_extent_data, u32 print_mask);
+void btrfsic_unmount(struct btrfs_root *root,
+                    struct btrfs_fs_devices *fs_devices);
+
+#endif
index dede441bdeee2678225187bece170710abe1a9b4..0639a555e16ed1975702ed5509dc9bc1c4dbf490 100644 (file)
@@ -240,7 +240,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 
        cow = btrfs_alloc_free_block(trans, root, buf->len, 0,
                                     new_root_objectid, &disk_key, level,
-                                    buf->start, 0);
+                                    buf->start, 0, 1);
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
@@ -261,9 +261,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 
        WARN_ON(btrfs_header_generation(buf) > trans->transid);
        if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID)
-               ret = btrfs_inc_ref(trans, root, cow, 1);
+               ret = btrfs_inc_ref(trans, root, cow, 1, 1);
        else
-               ret = btrfs_inc_ref(trans, root, cow, 0);
+               ret = btrfs_inc_ref(trans, root, cow, 0, 1);
 
        if (ret)
                return ret;
@@ -350,14 +350,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                if ((owner == root->root_key.objectid ||
                     root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
                    !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
-                       ret = btrfs_inc_ref(trans, root, buf, 1);
+                       ret = btrfs_inc_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret);
 
                        if (root->root_key.objectid ==
                            BTRFS_TREE_RELOC_OBJECTID) {
-                               ret = btrfs_dec_ref(trans, root, buf, 0);
+                               ret = btrfs_dec_ref(trans, root, buf, 0, 1);
                                BUG_ON(ret);
-                               ret = btrfs_inc_ref(trans, root, cow, 1);
+                               ret = btrfs_inc_ref(trans, root, cow, 1, 1);
                                BUG_ON(ret);
                        }
                        new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
@@ -365,9 +365,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
 
                        if (root->root_key.objectid ==
                            BTRFS_TREE_RELOC_OBJECTID)
-                               ret = btrfs_inc_ref(trans, root, cow, 1);
+                               ret = btrfs_inc_ref(trans, root, cow, 1, 1);
                        else
-                               ret = btrfs_inc_ref(trans, root, cow, 0);
+                               ret = btrfs_inc_ref(trans, root, cow, 0, 1);
                        BUG_ON(ret);
                }
                if (new_flags != 0) {
@@ -381,11 +381,11 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
                        if (root->root_key.objectid ==
                            BTRFS_TREE_RELOC_OBJECTID)
-                               ret = btrfs_inc_ref(trans, root, cow, 1);
+                               ret = btrfs_inc_ref(trans, root, cow, 1, 1);
                        else
-                               ret = btrfs_inc_ref(trans, root, cow, 0);
+                               ret = btrfs_inc_ref(trans, root, cow, 0, 1);
                        BUG_ON(ret);
-                       ret = btrfs_dec_ref(trans, root, buf, 1);
+                       ret = btrfs_dec_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret);
                }
                clean_tree_block(trans, root, buf);
@@ -446,7 +446,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
 
        cow = btrfs_alloc_free_block(trans, root, buf->len, parent_start,
                                     root->root_key.objectid, &disk_key,
-                                    level, search_start, empty_size);
+                                    level, search_start, empty_size, 1);
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
@@ -484,7 +484,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                rcu_assign_pointer(root->node, cow);
 
                btrfs_free_tree_block(trans, root, buf, parent_start,
-                                     last_ref);
+                                     last_ref, 1);
                free_extent_buffer(buf);
                add_root_to_dirty_list(root);
        } else {
@@ -500,7 +500,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                                              trans->transid);
                btrfs_mark_buffer_dirty(parent);
                btrfs_free_tree_block(trans, root, buf, parent_start,
-                                     last_ref);
+                                     last_ref, 1);
        }
        if (unlock_orig)
                btrfs_tree_unlock(buf);
@@ -957,7 +957,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                free_extent_buffer(mid);
 
                root_sub_used(root, mid->len);
-               btrfs_free_tree_block(trans, root, mid, 0, 1);
+               btrfs_free_tree_block(trans, root, mid, 0, 1, 0);
                /* once for the root ptr */
                free_extent_buffer(mid);
                return 0;
@@ -1015,7 +1015,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        if (wret)
                                ret = wret;
                        root_sub_used(root, right->len);
-                       btrfs_free_tree_block(trans, root, right, 0, 1);
+                       btrfs_free_tree_block(trans, root, right, 0, 1, 0);
                        free_extent_buffer(right);
                        right = NULL;
                } else {
@@ -1055,7 +1055,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                if (wret)
                        ret = wret;
                root_sub_used(root, mid->len);
-               btrfs_free_tree_block(trans, root, mid, 0, 1);
+               btrfs_free_tree_block(trans, root, mid, 0, 1, 0);
                free_extent_buffer(mid);
                mid = NULL;
        } else {
@@ -2089,7 +2089,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
 
        c = btrfs_alloc_free_block(trans, root, root->nodesize, 0,
                                   root->root_key.objectid, &lower_key,
-                                  level, root->node->start, 0);
+                                  level, root->node->start, 0, 0);
        if (IS_ERR(c))
                return PTR_ERR(c);
 
@@ -2216,7 +2216,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
 
        split = btrfs_alloc_free_block(trans, root, root->nodesize, 0,
                                        root->root_key.objectid,
-                                       &disk_key, level, c->start, 0);
+                                       &disk_key, level, c->start, 0, 0);
        if (IS_ERR(split))
                return PTR_ERR(split);
 
@@ -2970,7 +2970,7 @@ again:
 
        right = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
                                        root->root_key.objectid,
-                                       &disk_key, 0, l->start, 0);
+                                       &disk_key, 0, l->start, 0, 0);
        if (IS_ERR(right))
                return PTR_ERR(right);
 
@@ -3781,7 +3781,7 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 
        root_sub_used(root, leaf->len);
 
-       btrfs_free_tree_block(trans, root, leaf, 0, 1);
+       btrfs_free_tree_block(trans, root, leaf, 0, 1, 0);
        return 0;
 }
 /*
index 67385033323d6e49817398a1df9b1596df07e839..27ebe61d3cccd0233518d743216dce4b7b8c933f 100644 (file)
@@ -86,6 +86,9 @@ struct btrfs_ordered_sum;
 /* holds checksums of all the data extents */
 #define BTRFS_CSUM_TREE_OBJECTID 7ULL
 
+/* for storing balance parameters in the root tree */
+#define BTRFS_BALANCE_OBJECTID -4ULL
+
 /* orhpan objectid for tracking unlinked/truncated files */
 #define BTRFS_ORPHAN_OBJECTID -5ULL
 
@@ -692,6 +695,54 @@ struct btrfs_root_ref {
        __le16 name_len;
 } __attribute__ ((__packed__));
 
+struct btrfs_disk_balance_args {
+       /*
+        * profiles to operate on, single is denoted by
+        * BTRFS_AVAIL_ALLOC_BIT_SINGLE
+        */
+       __le64 profiles;
+
+       /* usage filter */
+       __le64 usage;
+
+       /* devid filter */
+       __le64 devid;
+
+       /* devid subset filter [pstart..pend) */
+       __le64 pstart;
+       __le64 pend;
+
+       /* btrfs virtual address space subset filter [vstart..vend) */
+       __le64 vstart;
+       __le64 vend;
+
+       /*
+        * profile to convert to, single is denoted by
+        * BTRFS_AVAIL_ALLOC_BIT_SINGLE
+        */
+       __le64 target;
+
+       /* BTRFS_BALANCE_ARGS_* */
+       __le64 flags;
+
+       __le64 unused[8];
+} __attribute__ ((__packed__));
+
+/*
+ * store balance parameters to disk so that balance can be properly
+ * resumed after crash or unmount
+ */
+struct btrfs_balance_item {
+       /* BTRFS_BALANCE_* */
+       __le64 flags;
+
+       struct btrfs_disk_balance_args data;
+       struct btrfs_disk_balance_args meta;
+       struct btrfs_disk_balance_args sys;
+
+       __le64 unused[4];
+} __attribute__ ((__packed__));
+
 #define BTRFS_FILE_EXTENT_INLINE 0
 #define BTRFS_FILE_EXTENT_REG 1
 #define BTRFS_FILE_EXTENT_PREALLOC 2
@@ -751,14 +802,32 @@ struct btrfs_csum_item {
 } __attribute__ ((__packed__));
 
 /* different types of block groups (and chunks) */
-#define BTRFS_BLOCK_GROUP_DATA     (1 << 0)
-#define BTRFS_BLOCK_GROUP_SYSTEM   (1 << 1)
-#define BTRFS_BLOCK_GROUP_METADATA (1 << 2)
-#define BTRFS_BLOCK_GROUP_RAID0    (1 << 3)
-#define BTRFS_BLOCK_GROUP_RAID1    (1 << 4)
-#define BTRFS_BLOCK_GROUP_DUP     (1 << 5)
-#define BTRFS_BLOCK_GROUP_RAID10   (1 << 6)
-#define BTRFS_NR_RAID_TYPES       5
+#define BTRFS_BLOCK_GROUP_DATA         (1ULL << 0)
+#define BTRFS_BLOCK_GROUP_SYSTEM       (1ULL << 1)
+#define BTRFS_BLOCK_GROUP_METADATA     (1ULL << 2)
+#define BTRFS_BLOCK_GROUP_RAID0                (1ULL << 3)
+#define BTRFS_BLOCK_GROUP_RAID1                (1ULL << 4)
+#define BTRFS_BLOCK_GROUP_DUP          (1ULL << 5)
+#define BTRFS_BLOCK_GROUP_RAID10       (1ULL << 6)
+#define BTRFS_BLOCK_GROUP_RESERVED     BTRFS_AVAIL_ALLOC_BIT_SINGLE
+#define BTRFS_NR_RAID_TYPES            5
+
+#define BTRFS_BLOCK_GROUP_TYPE_MASK    (BTRFS_BLOCK_GROUP_DATA |    \
+                                        BTRFS_BLOCK_GROUP_SYSTEM |  \
+                                        BTRFS_BLOCK_GROUP_METADATA)
+
+#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 |   \
+                                        BTRFS_BLOCK_GROUP_RAID1 |   \
+                                        BTRFS_BLOCK_GROUP_DUP |     \
+                                        BTRFS_BLOCK_GROUP_RAID10)
+/*
+ * We need a bit for restriper to be able to tell when chunks of type
+ * SINGLE are available.  This "extended" profile format is used in
+ * fs_info->avail_*_alloc_bits (in-memory) and balance item fields
+ * (on-disk).  The corresponding on-disk bit in chunk.type is reserved
+ * to avoid remappings between two formats in future.
+ */
+#define BTRFS_AVAIL_ALLOC_BIT_SINGLE   (1ULL << 48)
 
 struct btrfs_block_group_item {
        __le64 used;
@@ -916,6 +985,7 @@ struct btrfs_block_group_cache {
 struct reloc_control;
 struct btrfs_device;
 struct btrfs_fs_devices;
+struct btrfs_balance_control;
 struct btrfs_delayed_root;
 struct btrfs_fs_info {
        u8 fsid[BTRFS_FSID_SIZE];
@@ -971,7 +1041,7 @@ struct btrfs_fs_info {
         * is required instead of the faster short fsync log commits
         */
        u64 last_trans_log_full_commit;
-       unsigned long mount_opt:20;
+       unsigned long mount_opt:21;
        unsigned long compress_type:4;
        u64 max_inline;
        u64 alloc_start;
@@ -1132,12 +1202,23 @@ struct btrfs_fs_info {
        spinlock_t ref_cache_lock;
        u64 total_ref_cache_size;
 
+       /*
+        * these three are in extended format (availability of single
+        * chunks is denoted by BTRFS_AVAIL_ALLOC_BIT_SINGLE bit, other
+        * types are denoted by corresponding BTRFS_BLOCK_GROUP_* bits)
+        */
        u64 avail_data_alloc_bits;
        u64 avail_metadata_alloc_bits;
        u64 avail_system_alloc_bits;
-       u64 data_alloc_profile;
-       u64 metadata_alloc_profile;
-       u64 system_alloc_profile;
+
+       /* restriper state */
+       spinlock_t balance_lock;
+       struct mutex balance_mutex;
+       atomic_t balance_running;
+       atomic_t balance_pause_req;
+       atomic_t balance_cancel_req;
+       struct btrfs_balance_control *balance_ctl;
+       wait_queue_head_t balance_wait_q;
 
        unsigned data_chunk_allocations;
        unsigned metadata_ratio;
@@ -1155,6 +1236,10 @@ struct btrfs_fs_info {
        int scrub_workers_refcnt;
        struct btrfs_workers scrub_workers;
 
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+       u32 check_integrity_print_mask;
+#endif
+
        /* filesystem state */
        u64 fs_state;
 
@@ -1383,6 +1468,8 @@ struct btrfs_ioctl_defrag_range_args {
 #define BTRFS_DEV_ITEM_KEY     216
 #define BTRFS_CHUNK_ITEM_KEY   228
 
+#define BTRFS_BALANCE_ITEM_KEY 248
+
 /*
  * string items are for debugging.  They just store a short string of
  * data in the FS
@@ -1413,6 +1500,9 @@ struct btrfs_ioctl_defrag_range_args {
 #define BTRFS_MOUNT_AUTO_DEFRAG                (1 << 16)
 #define BTRFS_MOUNT_INODE_MAP_CACHE    (1 << 17)
 #define BTRFS_MOUNT_RECOVERY           (1 << 18)
+#define BTRFS_MOUNT_SKIP_BALANCE       (1 << 19)
+#define BTRFS_MOUNT_CHECK_INTEGRITY    (1 << 20)
+#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)
 
 #define btrfs_clear_opt(o, opt)                ((o) &= ~BTRFS_MOUNT_##opt)
 #define btrfs_set_opt(o, opt)          ((o) |= BTRFS_MOUNT_##opt)
@@ -2077,8 +2167,86 @@ BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup,
 BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup,
                   num_devices, 64);
 
-/* struct btrfs_super_block */
+/* struct btrfs_balance_item */
+BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
 
+static inline void btrfs_balance_data(struct extent_buffer *eb,
+                                     struct btrfs_balance_item *bi,
+                                     struct btrfs_disk_balance_args *ba)
+{
+       read_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
+}
+
+static inline void btrfs_set_balance_data(struct extent_buffer *eb,
+                                         struct btrfs_balance_item *bi,
+                                         struct btrfs_disk_balance_args *ba)
+{
+       write_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
+}
+
+static inline void btrfs_balance_meta(struct extent_buffer *eb,
+                                     struct btrfs_balance_item *bi,
+                                     struct btrfs_disk_balance_args *ba)
+{
+       read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
+}
+
+static inline void btrfs_set_balance_meta(struct extent_buffer *eb,
+                                         struct btrfs_balance_item *bi,
+                                         struct btrfs_disk_balance_args *ba)
+{
+       write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
+}
+
+static inline void btrfs_balance_sys(struct extent_buffer *eb,
+                                    struct btrfs_balance_item *bi,
+                                    struct btrfs_disk_balance_args *ba)
+{
+       read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
+}
+
+static inline void btrfs_set_balance_sys(struct extent_buffer *eb,
+                                        struct btrfs_balance_item *bi,
+                                        struct btrfs_disk_balance_args *ba)
+{
+       write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
+}
+
+static inline void
+btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
+                              struct btrfs_disk_balance_args *disk)
+{
+       memset(cpu, 0, sizeof(*cpu));
+
+       cpu->profiles = le64_to_cpu(disk->profiles);
+       cpu->usage = le64_to_cpu(disk->usage);
+       cpu->devid = le64_to_cpu(disk->devid);
+       cpu->pstart = le64_to_cpu(disk->pstart);
+       cpu->pend = le64_to_cpu(disk->pend);
+       cpu->vstart = le64_to_cpu(disk->vstart);
+       cpu->vend = le64_to_cpu(disk->vend);
+       cpu->target = le64_to_cpu(disk->target);
+       cpu->flags = le64_to_cpu(disk->flags);
+}
+
+static inline void
+btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
+                              struct btrfs_balance_args *cpu)
+{
+       memset(disk, 0, sizeof(*disk));
+
+       disk->profiles = cpu_to_le64(cpu->profiles);
+       disk->usage = cpu_to_le64(cpu->usage);
+       disk->devid = cpu_to_le64(cpu->devid);
+       disk->pstart = cpu_to_le64(cpu->pstart);
+       disk->pend = cpu_to_le64(cpu->pend);
+       disk->vstart = cpu_to_le64(cpu->vstart);
+       disk->vend = cpu_to_le64(cpu->vend);
+       disk->target = cpu_to_le64(cpu->target);
+       disk->flags = cpu_to_le64(cpu->flags);
+}
+
+/* struct btrfs_super_block */
 BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
 BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64);
 BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
@@ -2196,7 +2364,7 @@ static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
        return btrfs_item_size(eb, e) - offset;
 }
 
-static inline struct btrfs_root *btrfs_sb(struct super_block *sb)
+static inline struct btrfs_fs_info *btrfs_sb(struct super_block *sb)
 {
        return sb->s_fs_info;
 }
@@ -2277,11 +2445,11 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root, u32 blocksize,
                                        u64 parent, u64 root_objectid,
                                        struct btrfs_disk_key *key, int level,
-                                       u64 hint, u64 empty_size);
+                                       u64 hint, u64 empty_size, int for_cow);
 void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           struct extent_buffer *buf,
-                          u64 parent, int last_ref);
+                          u64 parent, int last_ref, int for_cow);
 struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
                                            struct btrfs_root *root,
                                            u64 bytenr, u32 blocksize,
@@ -2301,17 +2469,17 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
                                  u64 search_end, struct btrfs_key *ins,
                                  u64 data);
 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                 struct extent_buffer *buf, int full_backref);
+                 struct extent_buffer *buf, int full_backref, int for_cow);
 int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                 struct extent_buffer *buf, int full_backref);
+                 struct extent_buffer *buf, int full_backref, int for_cow);
 int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                u64 bytenr, u64 num_bytes, u64 flags,
                                int is_data);
 int btrfs_free_extent(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root,
-                     u64 bytenr, u64 num_bytes, u64 parent,
-                     u64 root_objectid, u64 owner, u64 offset);
+                     u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
+                     u64 owner, u64 offset, int for_cow);
 
 int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len);
 int btrfs_free_and_pin_reserved_extent(struct btrfs_root *root,
@@ -2323,7 +2491,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root,
                         u64 bytenr, u64 num_bytes, u64 parent,
-                        u64 root_objectid, u64 owner, u64 offset);
+                        u64 root_objectid, u64 owner, u64 offset, int for_cow);
 
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                                    struct btrfs_root *root);
@@ -2482,10 +2650,18 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 }
 
 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
+static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
+{
+       ++p->slots[0];
+       if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
+               return btrfs_next_leaf(root, p);
+       return 0;
+}
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
 void btrfs_drop_snapshot(struct btrfs_root *root,
-                        struct btrfs_block_rsv *block_rsv, int update_ref);
+                        struct btrfs_block_rsv *block_rsv, int update_ref,
+                        int for_reloc);
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
@@ -2500,6 +2676,7 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
 }
 static inline void free_fs_info(struct btrfs_fs_info *fs_info)
 {
+       kfree(fs_info->balance_ctl);
        kfree(fs_info->delayed_root);
        kfree(fs_info->extent_root);
        kfree(fs_info->tree_root);
@@ -2510,6 +2687,24 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
        kfree(fs_info->super_for_commit);
        kfree(fs_info);
 }
+/**
+ * profile_is_valid - tests whether a given profile is valid and reduced
+ * @flags: profile to validate
+ * @extended: if true @flags is treated as an extended profile
+ */
+static inline int profile_is_valid(u64 flags, int extended)
+{
+       u64 mask = ~BTRFS_BLOCK_GROUP_PROFILE_MASK;
+
+       flags &= ~BTRFS_BLOCK_GROUP_TYPE_MASK;
+       if (extended)
+               mask &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+
+       if (flags & mask)
+               return 0;
+       /* true if zero or exactly one bit set */
+       return (flags & (~flags + 1)) == flags;
+}
 
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,
index 9c1eccc2c503e5eec8bd20d3dfc057a417eef89a..fe4cd0f1cef188b8cf584c67c8ab0f58ffb62cbb 100644 (file)
@@ -595,8 +595,12 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
 
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
        ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
-       if (!ret)
+       if (!ret) {
+               trace_btrfs_space_reservation(root->fs_info, "delayed_item",
+                                             item->key.objectid,
+                                             num_bytes, 1);
                item->bytes_reserved = num_bytes;
+       }
 
        return ret;
 }
@@ -610,6 +614,9 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
                return;
 
        rsv = &root->fs_info->delayed_block_rsv;
+       trace_btrfs_space_reservation(root->fs_info, "delayed_item",
+                                     item->key.objectid, item->bytes_reserved,
+                                     0);
        btrfs_block_rsv_release(root, rsv,
                                item->bytes_reserved);
 }
@@ -624,7 +631,7 @@ static int btrfs_delayed_inode_reserve_metadata(
        struct btrfs_block_rsv *dst_rsv;
        u64 num_bytes;
        int ret;
-       int release = false;
+       bool release = false;
 
        src_rsv = trans->block_rsv;
        dst_rsv = &root->fs_info->delayed_block_rsv;
@@ -651,8 +658,13 @@ static int btrfs_delayed_inode_reserve_metadata(
                 */
                if (ret == -EAGAIN)
                        ret = -ENOSPC;
-               if (!ret)
+               if (!ret) {
                        node->bytes_reserved = num_bytes;
+                       trace_btrfs_space_reservation(root->fs_info,
+                                                     "delayed_inode",
+                                                     btrfs_ino(inode),
+                                                     num_bytes, 1);
+               }
                return ret;
        } else if (src_rsv == &root->fs_info->delalloc_block_rsv) {
                spin_lock(&BTRFS_I(inode)->lock);
@@ -707,11 +719,17 @@ out:
         * reservation here.  I think it may be time for a documentation page on
         * how block rsvs. work.
         */
-       if (!ret)
+       if (!ret) {
+               trace_btrfs_space_reservation(root->fs_info, "delayed_inode",
+                                             btrfs_ino(inode), num_bytes, 1);
                node->bytes_reserved = num_bytes;
+       }
 
-       if (release)
+       if (release) {
+               trace_btrfs_space_reservation(root->fs_info, "delalloc",
+                                             btrfs_ino(inode), num_bytes, 0);
                btrfs_block_rsv_release(root, src_rsv, num_bytes);
+       }
 
        return ret;
 }
@@ -725,6 +743,8 @@ static void btrfs_delayed_inode_release_metadata(struct btrfs_root *root,
                return;
 
        rsv = &root->fs_info->delayed_block_rsv;
+       trace_btrfs_space_reservation(root->fs_info, "delayed_inode",
+                                     node->inode_id, node->bytes_reserved, 0);
        btrfs_block_rsv_release(root, rsv,
                                node->bytes_reserved);
        node->bytes_reserved = 0;
@@ -1372,13 +1392,6 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
                goto release_node;
        }
 
-       ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item);
-       /*
-        * we have reserved enough space when we start a new transaction,
-        * so reserving metadata failure is impossible
-        */
-       BUG_ON(ret);
-
        delayed_item->key.objectid = btrfs_ino(dir);
        btrfs_set_key_type(&delayed_item->key, BTRFS_DIR_INDEX_KEY);
        delayed_item->key.offset = index;
@@ -1391,6 +1404,14 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
        dir_item->type = type;
        memcpy((char *)(dir_item + 1), name, name_len);
 
+       ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item);
+       /*
+        * we have reserved enough space when we start a new transaction,
+        * so reserving metadata failure is impossible
+        */
+       BUG_ON(ret);
+
+
        mutex_lock(&delayed_node->mutex);
        ret = __btrfs_add_delayed_insertion_item(delayed_node, delayed_item);
        if (unlikely(ret)) {
index 125cf76fcd086803d35bd257bdb54168486e0e0b..66e4f29505a33dbecd45b5d6a80e878c87818bc0 100644 (file)
@@ -101,6 +101,11 @@ static int comp_entry(struct btrfs_delayed_ref_node *ref2,
                return -1;
        if (ref1->type > ref2->type)
                return 1;
+       /* merging of sequenced refs is not allowed */
+       if (ref1->seq < ref2->seq)
+               return -1;
+       if (ref1->seq > ref2->seq)
+               return 1;
        if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
            ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) {
                return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2),
@@ -150,16 +155,22 @@ static struct btrfs_delayed_ref_node *tree_insert(struct rb_root *root,
 
 /*
  * find an head entry based on bytenr. This returns the delayed ref
- * head if it was able to find one, or NULL if nothing was in that spot
+ * head if it was able to find one, or NULL if nothing was in that spot.
+ * If return_bigger is given, the next bigger entry is returned if no exact
+ * match is found.
  */
 static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root,
                                  u64 bytenr,
-                                 struct btrfs_delayed_ref_node **last)
+                                 struct btrfs_delayed_ref_node **last,
+                                 int return_bigger)
 {
-       struct rb_node *n = root->rb_node;
+       struct rb_node *n;
        struct btrfs_delayed_ref_node *entry;
-       int cmp;
+       int cmp = 0;
 
+again:
+       n = root->rb_node;
+       entry = NULL;
        while (n) {
                entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node);
                WARN_ON(!entry->in_tree);
@@ -182,6 +193,19 @@ static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root,
                else
                        return entry;
        }
+       if (entry && return_bigger) {
+               if (cmp > 0) {
+                       n = rb_next(&entry->rb_node);
+                       if (!n)
+                               n = rb_first(root);
+                       entry = rb_entry(n, struct btrfs_delayed_ref_node,
+                                        rb_node);
+                       bytenr = entry->bytenr;
+                       return_bigger = 0;
+                       goto again;
+               }
+               return entry;
+       }
        return NULL;
 }
 
@@ -209,6 +233,24 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
+                           u64 seq)
+{
+       struct seq_list *elem;
+
+       assert_spin_locked(&delayed_refs->lock);
+       if (list_empty(&delayed_refs->seq_head))
+               return 0;
+
+       elem = list_first_entry(&delayed_refs->seq_head, struct seq_list, list);
+       if (seq >= elem->seq) {
+               pr_debug("holding back delayed_ref %llu, lowest is %llu (%p)\n",
+                        seq, elem->seq, delayed_refs);
+               return 1;
+       }
+       return 0;
+}
+
 int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,
                           struct list_head *cluster, u64 start)
 {
@@ -223,20 +265,8 @@ int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,
                node = rb_first(&delayed_refs->root);
        } else {
                ref = NULL;
-               find_ref_head(&delayed_refs->root, start, &ref);
+               find_ref_head(&delayed_refs->root, start + 1, &ref, 1);
                if (ref) {
-                       struct btrfs_delayed_ref_node *tmp;
-
-                       node = rb_prev(&ref->rb_node);
-                       while (node) {
-                               tmp = rb_entry(node,
-                                              struct btrfs_delayed_ref_node,
-                                              rb_node);
-                               if (tmp->bytenr < start)
-                                       break;
-                               ref = tmp;
-                               node = rb_prev(&ref->rb_node);
-                       }
                        node = &ref->rb_node;
                } else
                        node = rb_first(&delayed_refs->root);
@@ -390,7 +420,8 @@ update_existing_head_ref(struct btrfs_delayed_ref_node *existing,
  * this does all the dirty work in terms of maintaining the correct
  * overall modification count.
  */
-static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
+static noinline int add_delayed_ref_head(struct btrfs_fs_info *fs_info,
+                                       struct btrfs_trans_handle *trans,
                                        struct btrfs_delayed_ref_node *ref,
                                        u64 bytenr, u64 num_bytes,
                                        int action, int is_data)
@@ -437,6 +468,7 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
        ref->action  = 0;
        ref->is_head = 1;
        ref->in_tree = 1;
+       ref->seq = 0;
 
        head_ref = btrfs_delayed_node_to_head(ref);
        head_ref->must_insert_reserved = must_insert_reserved;
@@ -468,14 +500,17 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
 /*
  * helper to insert a delayed tree ref into the rbtree.
  */
-static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
+static noinline int add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
+                                        struct btrfs_trans_handle *trans,
                                         struct btrfs_delayed_ref_node *ref,
                                         u64 bytenr, u64 num_bytes, u64 parent,
-                                        u64 ref_root, int level, int action)
+                                        u64 ref_root, int level, int action,
+                                        int for_cow)
 {
        struct btrfs_delayed_ref_node *existing;
        struct btrfs_delayed_tree_ref *full_ref;
        struct btrfs_delayed_ref_root *delayed_refs;
+       u64 seq = 0;
 
        if (action == BTRFS_ADD_DELAYED_EXTENT)
                action = BTRFS_ADD_DELAYED_REF;
@@ -491,14 +526,17 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
        ref->is_head = 0;
        ref->in_tree = 1;
 
+       if (need_ref_seq(for_cow, ref_root))
+               seq = inc_delayed_seq(delayed_refs);
+       ref->seq = seq;
+
        full_ref = btrfs_delayed_node_to_tree_ref(ref);
-       if (parent) {
-               full_ref->parent = parent;
+       full_ref->parent = parent;
+       full_ref->root = ref_root;
+       if (parent)
                ref->type = BTRFS_SHARED_BLOCK_REF_KEY;
-       } else {
-               full_ref->root = ref_root;
+       else
                ref->type = BTRFS_TREE_BLOCK_REF_KEY;
-       }
        full_ref->level = level;
 
        trace_btrfs_delayed_tree_ref(ref, full_ref, action);
@@ -522,15 +560,17 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 /*
  * helper to insert a delayed data ref into the rbtree.
  */
-static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
+static noinline int add_delayed_data_ref(struct btrfs_fs_info *fs_info,
+                                        struct btrfs_trans_handle *trans,
                                         struct btrfs_delayed_ref_node *ref,
                                         u64 bytenr, u64 num_bytes, u64 parent,
                                         u64 ref_root, u64 owner, u64 offset,
-                                        int action)
+                                        int action, int for_cow)
 {
        struct btrfs_delayed_ref_node *existing;
        struct btrfs_delayed_data_ref *full_ref;
        struct btrfs_delayed_ref_root *delayed_refs;
+       u64 seq = 0;
 
        if (action == BTRFS_ADD_DELAYED_EXTENT)
                action = BTRFS_ADD_DELAYED_REF;
@@ -546,14 +586,18 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
        ref->is_head = 0;
        ref->in_tree = 1;
 
+       if (need_ref_seq(for_cow, ref_root))
+               seq = inc_delayed_seq(delayed_refs);
+       ref->seq = seq;
+
        full_ref = btrfs_delayed_node_to_data_ref(ref);
-       if (parent) {
-               full_ref->parent = parent;
+       full_ref->parent = parent;
+       full_ref->root = ref_root;
+       if (parent)
                ref->type = BTRFS_SHARED_DATA_REF_KEY;
-       } else {
-               full_ref->root = ref_root;
+       else
                ref->type = BTRFS_EXTENT_DATA_REF_KEY;
-       }
+
        full_ref->objectid = owner;
        full_ref->offset = offset;
 
@@ -580,10 +624,12 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
  * to make sure the delayed ref is eventually processed before this
  * transaction commits.
  */
-int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
+int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
+                              struct btrfs_trans_handle *trans,
                               u64 bytenr, u64 num_bytes, u64 parent,
                               u64 ref_root,  int level, int action,
-                              struct btrfs_delayed_extent_op *extent_op)
+                              struct btrfs_delayed_extent_op *extent_op,
+                              int for_cow)
 {
        struct btrfs_delayed_tree_ref *ref;
        struct btrfs_delayed_ref_head *head_ref;
@@ -610,13 +656,17 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
         * insert both the head node and the new ref without dropping
         * the spin lock
         */
-       ret = add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
-                                  action, 0);
+       ret = add_delayed_ref_head(fs_info, trans, &head_ref->node, bytenr,
+                                  num_bytes, action, 0);
        BUG_ON(ret);
 
-       ret = add_delayed_tree_ref(trans, &ref->node, bytenr, num_bytes,
-                                  parent, ref_root, level, action);
+       ret = add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr,
+                                  num_bytes, parent, ref_root, level, action,
+                                  for_cow);
        BUG_ON(ret);
+       if (!need_ref_seq(for_cow, ref_root) &&
+           waitqueue_active(&delayed_refs->seq_wait))
+               wake_up(&delayed_refs->seq_wait);
        spin_unlock(&delayed_refs->lock);
        return 0;
 }
@@ -624,11 +674,13 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 /*
  * add a delayed data ref. it's similar to btrfs_add_delayed_tree_ref.
  */
-int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
+int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
+                              struct btrfs_trans_handle *trans,
                               u64 bytenr, u64 num_bytes,
                               u64 parent, u64 ref_root,
                               u64 owner, u64 offset, int action,
-                              struct btrfs_delayed_extent_op *extent_op)
+                              struct btrfs_delayed_extent_op *extent_op,
+                              int for_cow)
 {
        struct btrfs_delayed_data_ref *ref;
        struct btrfs_delayed_ref_head *head_ref;
@@ -655,18 +707,23 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
         * insert both the head node and the new ref without dropping
         * the spin lock
         */
-       ret = add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
-                                  action, 1);
+       ret = add_delayed_ref_head(fs_info, trans, &head_ref->node, bytenr,
+                                  num_bytes, action, 1);
        BUG_ON(ret);
 
-       ret = add_delayed_data_ref(trans, &ref->node, bytenr, num_bytes,
-                                  parent, ref_root, owner, offset, action);
+       ret = add_delayed_data_ref(fs_info, trans, &ref->node, bytenr,
+                                  num_bytes, parent, ref_root, owner, offset,
+                                  action, for_cow);
        BUG_ON(ret);
+       if (!need_ref_seq(for_cow, ref_root) &&
+           waitqueue_active(&delayed_refs->seq_wait))
+               wake_up(&delayed_refs->seq_wait);
        spin_unlock(&delayed_refs->lock);
        return 0;
 }
 
-int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
+int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
+                               struct btrfs_trans_handle *trans,
                                u64 bytenr, u64 num_bytes,
                                struct btrfs_delayed_extent_op *extent_op)
 {
@@ -683,11 +740,13 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
        delayed_refs = &trans->transaction->delayed_refs;
        spin_lock(&delayed_refs->lock);
 
-       ret = add_delayed_ref_head(trans, &head_ref->node, bytenr,
+       ret = add_delayed_ref_head(fs_info, trans, &head_ref->node, bytenr,
                                   num_bytes, BTRFS_UPDATE_DELAYED_HEAD,
                                   extent_op->is_data);
        BUG_ON(ret);
 
+       if (waitqueue_active(&delayed_refs->seq_wait))
+               wake_up(&delayed_refs->seq_wait);
        spin_unlock(&delayed_refs->lock);
        return 0;
 }
@@ -704,7 +763,7 @@ btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr)
        struct btrfs_delayed_ref_root *delayed_refs;
 
        delayed_refs = &trans->transaction->delayed_refs;
-       ref = find_ref_head(&delayed_refs->root, bytenr, NULL);
+       ref = find_ref_head(&delayed_refs->root, bytenr, NULL, 0);
        if (ref)
                return btrfs_delayed_node_to_head(ref);
        return NULL;
index e287e3b0eab0d970d37f0f4c70fd688b22f276ac..d8f244d9492511e3b108b26bcf4da1bc9fbf6826 100644 (file)
@@ -33,6 +33,9 @@ struct btrfs_delayed_ref_node {
        /* the size of the extent */
        u64 num_bytes;
 
+       /* seq number to keep track of insertion order */
+       u64 seq;
+
        /* ref count on this data structure */
        atomic_t refs;
 
@@ -98,19 +101,15 @@ struct btrfs_delayed_ref_head {
 
 struct btrfs_delayed_tree_ref {
        struct btrfs_delayed_ref_node node;
-       union {
-               u64 root;
-               u64 parent;
-       };
+       u64 root;
+       u64 parent;
        int level;
 };
 
 struct btrfs_delayed_data_ref {
        struct btrfs_delayed_ref_node node;
-       union {
-               u64 root;
-               u64 parent;
-       };
+       u64 root;
+       u64 parent;
        u64 objectid;
        u64 offset;
 };
@@ -140,6 +139,26 @@ struct btrfs_delayed_ref_root {
        int flushing;
 
        u64 run_delayed_start;
+
+       /*
+        * seq number of delayed refs. We need to know if a backref was being
+        * added before the currently processed ref or afterwards.
+        */
+       u64 seq;
+
+       /*
+        * seq_list holds a list of all seq numbers that are currently being
+        * added to the list. While walking backrefs (btrfs_find_all_roots,
+        * qgroups), which might take some time, no newer ref must be processed,
+        * as it might influence the outcome of the walk.
+        */
+       struct list_head seq_head;
+
+       /*
+        * when the only refs we have in the list must not be processed, we want
+        * to wait for more refs to show up or for the end of backref walking.
+        */
+       wait_queue_head_t seq_wait;
 };
 
 static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
@@ -151,16 +170,21 @@ static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
        }
 }
 
-int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
+int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
+                              struct btrfs_trans_handle *trans,
                               u64 bytenr, u64 num_bytes, u64 parent,
                               u64 ref_root, int level, int action,
-                              struct btrfs_delayed_extent_op *extent_op);
-int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
+                              struct btrfs_delayed_extent_op *extent_op,
+                              int for_cow);
+int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
+                              struct btrfs_trans_handle *trans,
                               u64 bytenr, u64 num_bytes,
                               u64 parent, u64 ref_root,
                               u64 owner, u64 offset, int action,
-                              struct btrfs_delayed_extent_op *extent_op);
-int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
+                              struct btrfs_delayed_extent_op *extent_op,
+                              int for_cow);
+int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
+                               struct btrfs_trans_handle *trans,
                                u64 bytenr, u64 num_bytes,
                                struct btrfs_delayed_extent_op *extent_op);
 
@@ -170,6 +194,60 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
                           struct btrfs_delayed_ref_head *head);
 int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,
                           struct list_head *cluster, u64 search_start);
+
+struct seq_list {
+       struct list_head list;
+       u64 seq;
+};
+
+static inline u64 inc_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs)
+{
+       assert_spin_locked(&delayed_refs->lock);
+       ++delayed_refs->seq;
+       return delayed_refs->seq;
+}
+
+static inline void
+btrfs_get_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
+                     struct seq_list *elem)
+{
+       assert_spin_locked(&delayed_refs->lock);
+       elem->seq = delayed_refs->seq;
+       list_add_tail(&elem->list, &delayed_refs->seq_head);
+}
+
+static inline void
+btrfs_put_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
+                     struct seq_list *elem)
+{
+       spin_lock(&delayed_refs->lock);
+       list_del(&elem->list);
+       wake_up(&delayed_refs->seq_wait);
+       spin_unlock(&delayed_refs->lock);
+}
+
+int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
+                           u64 seq);
+
+/*
+ * delayed refs with a ref_seq > 0 must be held back during backref walking.
+ * this only applies to items in one of the fs-trees. for_cow items never need
+ * to be held back, so they won't get a ref_seq number.
+ */
+static inline int need_ref_seq(int for_cow, u64 rootid)
+{
+       if (for_cow)
+               return 0;
+
+       if (rootid == BTRFS_FS_TREE_OBJECTID)
+               return 1;
+
+       if ((s64)rootid >= (s64)BTRFS_FIRST_FREE_OBJECTID)
+               return 1;
+
+       return 0;
+}
+
 /*
  * a node might live in a head or a regular ref, this lets you
  * test for the proper type to use.
index d8525662ca7a721b18e197191816ea16b095eb19..811d9f918b1c2923c1b35a5ae966808b0e3c2fe6 100644 (file)
@@ -43,6 +43,7 @@
 #include "tree-log.h"
 #include "free-space-cache.h"
 #include "inode-map.h"
+#include "check-integrity.h"
 
 static struct extent_io_ops btree_extent_io_ops;
 static void end_workqueue_fn(struct btrfs_work *work);
@@ -961,6 +962,13 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags)
        tree = &BTRFS_I(page->mapping->host)->io_tree;
        map = &BTRFS_I(page->mapping->host)->extent_tree;
 
+       /*
+        * We need to mask out eg. __GFP_HIGHMEM and __GFP_DMA32 as we're doing
+        * slab allocation from alloc_extent_state down the callchain where
+        * it'd hit a BUG_ON as those flags are not allowed.
+        */
+       gfp_flags &= ~GFP_SLAB_BUG_MASK;
+
        ret = try_release_extent_state(map, tree, page, gfp_flags);
        if (!ret)
                return 0;
@@ -1143,7 +1151,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->orphan_item_inserted = 0;
        root->orphan_cleanup_state = 0;
 
-       root->fs_info = fs_info;
        root->objectid = objectid;
        root->last_trans = 0;
        root->highest_objectid = 0;
@@ -1217,6 +1224,14 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
        return 0;
 }
 
+static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_root *root = kzalloc(sizeof(*root), GFP_NOFS);
+       if (root)
+               root->fs_info = fs_info;
+       return root;
+}
+
 static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
                                         struct btrfs_fs_info *fs_info)
 {
@@ -1224,7 +1239,7 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
        struct btrfs_root *tree_root = fs_info->tree_root;
        struct extent_buffer *leaf;
 
-       root = kzalloc(sizeof(*root), GFP_NOFS);
+       root = btrfs_alloc_root(fs_info);
        if (!root)
                return ERR_PTR(-ENOMEM);
 
@@ -1244,7 +1259,8 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
        root->ref_cows = 0;
 
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
-                                     BTRFS_TREE_LOG_OBJECTID, NULL, 0, 0, 0);
+                                     BTRFS_TREE_LOG_OBJECTID, NULL,
+                                     0, 0, 0, 0);
        if (IS_ERR(leaf)) {
                kfree(root);
                return ERR_CAST(leaf);
@@ -1318,7 +1334,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
        u32 blocksize;
        int ret = 0;
 
-       root = kzalloc(sizeof(*root), GFP_NOFS);
+       root = btrfs_alloc_root(fs_info);
        if (!root)
                return ERR_PTR(-ENOMEM);
        if (location->offset == (u64)-1) {
@@ -1874,9 +1890,9 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root)
 }
 
 
-struct btrfs_root *open_ctree(struct super_block *sb,
-                             struct btrfs_fs_devices *fs_devices,
-                             char *options)
+int open_ctree(struct super_block *sb,
+              struct btrfs_fs_devices *fs_devices,
+              char *options)
 {
        u32 sectorsize;
        u32 nodesize;
@@ -1888,8 +1904,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        struct btrfs_key location;
        struct buffer_head *bh;
        struct btrfs_super_block *disk_super;
-       struct btrfs_root *tree_root = btrfs_sb(sb);
-       struct btrfs_fs_info *fs_info = tree_root->fs_info;
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       struct btrfs_root *tree_root;
        struct btrfs_root *extent_root;
        struct btrfs_root *csum_root;
        struct btrfs_root *chunk_root;
@@ -1900,16 +1916,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        int num_backups_tried = 0;
        int backup_index = 0;
 
-       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);
+       tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info);
+       extent_root = fs_info->extent_root = btrfs_alloc_root(fs_info);
+       csum_root = fs_info->csum_root = btrfs_alloc_root(fs_info);
+       chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info);
+       dev_root = fs_info->dev_root = btrfs_alloc_root(fs_info);
 
-       if (!extent_root || !csum_root || !chunk_root || !dev_root) {
+       if (!tree_root || !extent_root || !csum_root ||
+           !chunk_root || !dev_root) {
                err = -ENOMEM;
                goto fail;
        }
@@ -1998,6 +2012,17 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        init_waitqueue_head(&fs_info->scrub_pause_wait);
        init_rwsem(&fs_info->scrub_super_lock);
        fs_info->scrub_workers_refcnt = 0;
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+       fs_info->check_integrity_print_mask = 0;
+#endif
+
+       spin_lock_init(&fs_info->balance_lock);
+       mutex_init(&fs_info->balance_mutex);
+       atomic_set(&fs_info->balance_running, 0);
+       atomic_set(&fs_info->balance_pause_req, 0);
+       atomic_set(&fs_info->balance_cancel_req, 0);
+       fs_info->balance_ctl = NULL;
+       init_waitqueue_head(&fs_info->balance_wait_q);
 
        sb->s_blocksize = 4096;
        sb->s_blocksize_bits = blksize_bits(4096);
@@ -2267,9 +2292,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
           (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node),
           BTRFS_UUID_SIZE);
 
-       mutex_lock(&fs_info->chunk_mutex);
        ret = btrfs_read_chunk_tree(chunk_root);
-       mutex_unlock(&fs_info->chunk_mutex);
        if (ret) {
                printk(KERN_WARNING "btrfs: failed to read chunk tree on %s\n",
                       sb->s_id);
@@ -2318,9 +2341,6 @@ retry_root_backup:
 
        fs_info->generation = generation;
        fs_info->last_trans_committed = generation;
-       fs_info->data_alloc_profile = (u64)-1;
-       fs_info->metadata_alloc_profile = (u64)-1;
-       fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
 
        ret = btrfs_init_space_info(fs_info);
        if (ret) {
@@ -2353,6 +2373,19 @@ retry_root_backup:
                btrfs_set_opt(fs_info->mount_opt, SSD);
        }
 
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+       if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
+               ret = btrfsic_mount(tree_root, fs_devices,
+                                   btrfs_test_opt(tree_root,
+                                       CHECK_INTEGRITY_INCLUDING_EXTENT_DATA) ?
+                                   1 : 0,
+                                   fs_info->check_integrity_print_mask);
+               if (ret)
+                       printk(KERN_WARNING "btrfs: failed to initialize"
+                              " integrity check module %s\n", sb->s_id);
+       }
+#endif
+
        /* do not make disk changes in broken FS */
        if (btrfs_super_log_root(disk_super) != 0 &&
            !(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) {
@@ -2368,7 +2401,7 @@ retry_root_backup:
                     btrfs_level_size(tree_root,
                                      btrfs_super_log_root_level(disk_super));
 
-               log_tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+               log_tree_root = btrfs_alloc_root(fs_info);
                if (!log_tree_root) {
                        err = -ENOMEM;
                        goto fail_trans_kthread;
@@ -2423,13 +2456,17 @@ retry_root_backup:
                if (!err)
                        err = btrfs_orphan_cleanup(fs_info->tree_root);
                up_read(&fs_info->cleanup_work_sem);
+
+               if (!err)
+                       err = btrfs_recover_balance(fs_info->tree_root);
+
                if (err) {
                        close_ctree(tree_root);
-                       return ERR_PTR(err);
+                       return err;
                }
        }
 
-       return tree_root;
+       return 0;
 
 fail_trans_kthread:
        kthread_stop(fs_info->transaction_kthread);
@@ -2475,8 +2512,7 @@ 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);
+       return err;
 
 recovery_tree_root:
        if (!btrfs_test_opt(tree_root, RECOVERY))
@@ -2631,7 +2667,7 @@ static int write_dev_supers(struct btrfs_device *device,
                 * we fua the first super.  The others we allow
                 * to go down lazy.
                 */
-               ret = submit_bh(WRITE_FUA, bh);
+               ret = btrfsic_submit_bh(WRITE_FUA, bh);
                if (ret)
                        errors++;
        }
@@ -2708,7 +2744,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
        device->flush_bio = bio;
 
        bio_get(bio);
-       submit_bio(WRITE_FLUSH, bio);
+       btrfsic_submit_bio(WRITE_FLUSH, bio);
 
        return 0;
 }
@@ -2972,6 +3008,9 @@ int close_ctree(struct btrfs_root *root)
        fs_info->closing = 1;
        smp_mb();
 
+       /* pause restriper - we want to resume on mount */
+       btrfs_pause_balance(root->fs_info);
+
        btrfs_scrub_cancel(root);
 
        /* wait for any defraggers to finish */
@@ -2979,7 +3018,7 @@ int close_ctree(struct btrfs_root *root)
                   (atomic_read(&fs_info->defrag_running) == 0));
 
        /* clear out the rbtree of defraggable inodes */
-       btrfs_run_defrag_inodes(root->fs_info);
+       btrfs_run_defrag_inodes(fs_info);
 
        /*
         * Here come 2 situations when btrfs is broken to flip readonly:
@@ -3008,8 +3047,8 @@ int close_ctree(struct btrfs_root *root)
 
        btrfs_put_block_group_cache(fs_info);
 
-       kthread_stop(root->fs_info->transaction_kthread);
-       kthread_stop(root->fs_info->cleaner_kthread);
+       kthread_stop(fs_info->transaction_kthread);
+       kthread_stop(fs_info->cleaner_kthread);
 
        fs_info->closing = 2;
        smp_mb();
@@ -3027,14 +3066,14 @@ int close_ctree(struct btrfs_root *root)
        free_extent_buffer(fs_info->extent_root->commit_root);
        free_extent_buffer(fs_info->tree_root->node);
        free_extent_buffer(fs_info->tree_root->commit_root);
-       free_extent_buffer(root->fs_info->chunk_root->node);
-       free_extent_buffer(root->fs_info->chunk_root->commit_root);
-       free_extent_buffer(root->fs_info->dev_root->node);
-       free_extent_buffer(root->fs_info->dev_root->commit_root);
-       free_extent_buffer(root->fs_info->csum_root->node);
-       free_extent_buffer(root->fs_info->csum_root->commit_root);
+       free_extent_buffer(fs_info->chunk_root->node);
+       free_extent_buffer(fs_info->chunk_root->commit_root);
+       free_extent_buffer(fs_info->dev_root->node);
+       free_extent_buffer(fs_info->dev_root->commit_root);
+       free_extent_buffer(fs_info->csum_root->node);
+       free_extent_buffer(fs_info->csum_root->commit_root);
 
-       btrfs_free_block_groups(root->fs_info);
+       btrfs_free_block_groups(fs_info);
 
        del_fs_roots(fs_info);
 
@@ -3054,14 +3093,17 @@ int close_ctree(struct btrfs_root *root)
        btrfs_stop_workers(&fs_info->caching_workers);
        btrfs_stop_workers(&fs_info->readahead_workers);
 
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+       if (btrfs_test_opt(root, CHECK_INTEGRITY))
+               btrfsic_unmount(root, fs_info->fs_devices);
+#endif
+
        btrfs_close_devices(fs_info->fs_devices);
        btrfs_mapping_tree_free(&fs_info->mapping_tree);
 
        bdi_destroy(&fs_info->bdi);
        cleanup_srcu_struct(&fs_info->subvol_srcu);
 
-       free_fs_info(fs_info);
-
        return 0;
 }
 
index c99d0a8f13fa2f38642f7826cb00c45070ac95ae..e4bc4741319bd3a1e094de03566feeb360d35e4d 100644 (file)
@@ -46,9 +46,9 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
                                                   u64 bytenr, u32 blocksize);
 int clean_tree_block(struct btrfs_trans_handle *trans,
                     struct btrfs_root *root, struct extent_buffer *buf);
-struct btrfs_root *open_ctree(struct super_block *sb,
-                             struct btrfs_fs_devices *fs_devices,
-                             char *options);
+int open_ctree(struct super_block *sb,
+              struct btrfs_fs_devices *fs_devices,
+              char *options);
 int close_ctree(struct btrfs_root *root);
 int write_ctree_super(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root, int max_mirrors);
index 1b8dc33778f9c411206cc6ad9467546412431947..5f77166fd01c7eb3d33cb78666e31822fc0a1083 100644 (file)
@@ -67,7 +67,7 @@ static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
                                       u64 root_objectid, u32 generation,
                                       int check_generation)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(sb)->fs_info;
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
        struct btrfs_root *root;
        struct inode *inode;
        struct btrfs_key key;
index f5fbe576d2baf48519a01bd449344b49edffa070..283af7a676a39b4c2f31d7d9b7caf81607eee4ea 100644 (file)
 #include "locking.h"
 #include "free-space-cache.h"
 
-/* control flags for do_chunk_alloc's force field
+/*
+ * control flags for do_chunk_alloc's force field
  * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
  * if we really need one.
  *
- * CHUNK_ALLOC_FORCE means it must try to allocate one
- *
  * CHUNK_ALLOC_LIMITED means to only try and allocate one
  * if we have very few chunks already allocated.  This is
  * used as part of the clustering code to help make sure
  * we have a good pool of storage to cluster in, without
  * filling the FS with empty chunks
  *
+ * CHUNK_ALLOC_FORCE means it must try to allocate one
+ *
  */
 enum {
        CHUNK_ALLOC_NO_FORCE = 0,
-       CHUNK_ALLOC_FORCE = 1,
-       CHUNK_ALLOC_LIMITED = 2,
+       CHUNK_ALLOC_LIMITED = 1,
+       CHUNK_ALLOC_FORCE = 2,
 };
 
 /*
@@ -618,8 +619,7 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
        struct list_head *head = &info->space_info;
        struct btrfs_space_info *found;
 
-       flags &= BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_SYSTEM |
-                BTRFS_BLOCK_GROUP_METADATA;
+       flags &= BTRFS_BLOCK_GROUP_TYPE_MASK;
 
        rcu_read_lock();
        list_for_each_entry_rcu(found, head, list) {
@@ -1872,20 +1872,24 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root,
                         u64 bytenr, u64 num_bytes, u64 parent,
-                        u64 root_objectid, u64 owner, u64 offset)
+                        u64 root_objectid, u64 owner, u64 offset, int for_cow)
 {
        int ret;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+
        BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID &&
               root_objectid == BTRFS_TREE_LOG_OBJECTID);
 
        if (owner < BTRFS_FIRST_FREE_OBJECTID) {
-               ret = btrfs_add_delayed_tree_ref(trans, bytenr, num_bytes,
+               ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
+                                       num_bytes,
                                        parent, root_objectid, (int)owner,
-                                       BTRFS_ADD_DELAYED_REF, NULL);
+                                       BTRFS_ADD_DELAYED_REF, NULL, for_cow);
        } else {
-               ret = btrfs_add_delayed_data_ref(trans, bytenr, num_bytes,
+               ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
+                                       num_bytes,
                                        parent, root_objectid, owner, offset,
-                                       BTRFS_ADD_DELAYED_REF, NULL);
+                                       BTRFS_ADD_DELAYED_REF, NULL, for_cow);
        }
        return ret;
 }
@@ -2232,6 +2236,28 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                        }
                }
 
+               /*
+                * locked_ref is the head node, so we have to go one
+                * node back for any delayed ref updates
+                */
+               ref = select_delayed_ref(locked_ref);
+
+               if (ref && ref->seq &&
+                   btrfs_check_delayed_seq(delayed_refs, ref->seq)) {
+                       /*
+                        * there are still refs with lower seq numbers in the
+                        * process of being added. Don't run this ref yet.
+                        */
+                       list_del_init(&locked_ref->cluster);
+                       mutex_unlock(&locked_ref->mutex);
+                       locked_ref = NULL;
+                       delayed_refs->num_heads_ready++;
+                       spin_unlock(&delayed_refs->lock);
+                       cond_resched();
+                       spin_lock(&delayed_refs->lock);
+                       continue;
+               }
+
                /*
                 * record the must insert reserved flag before we
                 * drop the spin lock.
@@ -2242,11 +2268,6 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                extent_op = locked_ref->extent_op;
                locked_ref->extent_op = NULL;
 
-               /*
-                * locked_ref is the head node, so we have to go one
-                * node back for any delayed ref updates
-                */
-               ref = select_delayed_ref(locked_ref);
                if (!ref) {
                        /* All delayed refs have been processed, Go ahead
                         * and send the head node to run_one_delayed_ref,
@@ -2267,9 +2288,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                                BUG_ON(ret);
                                kfree(extent_op);
 
-                               cond_resched();
-                               spin_lock(&delayed_refs->lock);
-                               continue;
+                               goto next;
                        }
 
                        list_del_init(&locked_ref->cluster);
@@ -2279,7 +2298,12 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                ref->in_tree = 0;
                rb_erase(&ref->rb_node, &delayed_refs->root);
                delayed_refs->num_entries--;
-
+               /*
+                * we modified num_entries, but as we're currently running
+                * delayed refs, skip
+                *     wake_up(&delayed_refs->seq_wait);
+                * here.
+                */
                spin_unlock(&delayed_refs->lock);
 
                ret = run_one_delayed_ref(trans, root, ref, extent_op,
@@ -2289,13 +2313,34 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                btrfs_put_delayed_ref(ref);
                kfree(extent_op);
                count++;
-
+next:
+               do_chunk_alloc(trans, root->fs_info->extent_root,
+                              2 * 1024 * 1024,
+                              btrfs_get_alloc_profile(root, 0),
+                              CHUNK_ALLOC_NO_FORCE);
                cond_resched();
                spin_lock(&delayed_refs->lock);
        }
        return count;
 }
 
+
+static void wait_for_more_refs(struct btrfs_delayed_ref_root *delayed_refs,
+                       unsigned long num_refs)
+{
+       struct list_head *first_seq = delayed_refs->seq_head.next;
+
+       spin_unlock(&delayed_refs->lock);
+       pr_debug("waiting for more refs (num %ld, first %p)\n",
+                num_refs, first_seq);
+       wait_event(delayed_refs->seq_wait,
+                  num_refs != delayed_refs->num_entries ||
+                  delayed_refs->seq_head.next != first_seq);
+       pr_debug("done waiting for more refs (num %ld, first %p)\n",
+                delayed_refs->num_entries, delayed_refs->seq_head.next);
+       spin_lock(&delayed_refs->lock);
+}
+
 /*
  * this starts processing the delayed reference count updates and
  * extent insertions we have queued up so far.  count can be
@@ -2311,15 +2356,23 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        struct btrfs_delayed_ref_node *ref;
        struct list_head cluster;
        int ret;
+       u64 delayed_start;
        int run_all = count == (unsigned long)-1;
        int run_most = 0;
+       unsigned long num_refs = 0;
+       int consider_waiting;
 
        if (root == root->fs_info->extent_root)
                root = root->fs_info->tree_root;
 
+       do_chunk_alloc(trans, root->fs_info->extent_root,
+                      2 * 1024 * 1024, btrfs_get_alloc_profile(root, 0),
+                      CHUNK_ALLOC_NO_FORCE);
+
        delayed_refs = &trans->transaction->delayed_refs;
        INIT_LIST_HEAD(&cluster);
 again:
+       consider_waiting = 0;
        spin_lock(&delayed_refs->lock);
        if (count == 0) {
                count = delayed_refs->num_entries * 2;
@@ -2336,11 +2389,35 @@ again:
                 * of refs to process starting at the first one we are able to
                 * lock
                 */
+               delayed_start = delayed_refs->run_delayed_start;
                ret = btrfs_find_ref_cluster(trans, &cluster,
                                             delayed_refs->run_delayed_start);
                if (ret)
                        break;
 
+               if (delayed_start >= delayed_refs->run_delayed_start) {
+                       if (consider_waiting == 0) {
+                               /*
+                                * btrfs_find_ref_cluster looped. let's do one
+                                * more cycle. if we don't run any delayed ref
+                                * during that cycle (because we can't because
+                                * all of them are blocked) and if the number of
+                                * refs doesn't change, we avoid busy waiting.
+                                */
+                               consider_waiting = 1;
+                               num_refs = delayed_refs->num_entries;
+                       } else {
+                               wait_for_more_refs(delayed_refs, num_refs);
+                               /*
+                                * after waiting, things have changed. we
+                                * dropped the lock and someone else might have
+                                * run some refs, built new clusters and so on.
+                                * therefore, we restart staleness detection.
+                                */
+                               consider_waiting = 0;
+                       }
+               }
+
                ret = run_clustered_refs(trans, root, &cluster);
                BUG_ON(ret < 0);
 
@@ -2348,6 +2425,11 @@ again:
 
                if (count == 0)
                        break;
+
+               if (ret || delayed_refs->run_delayed_start == 0) {
+                       /* refs were run, let's reset staleness detection */
+                       consider_waiting = 0;
+               }
        }
 
        if (run_all) {
@@ -2405,7 +2487,8 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
        extent_op->update_key = 0;
        extent_op->is_data = is_data ? 1 : 0;
 
-       ret = btrfs_add_delayed_extent_op(trans, bytenr, num_bytes, extent_op);
+       ret = btrfs_add_delayed_extent_op(root->fs_info, trans, bytenr,
+                                         num_bytes, extent_op);
        if (ret)
                kfree(extent_op);
        return ret;
@@ -2590,7 +2673,7 @@ out:
 static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           struct extent_buffer *buf,
-                          int full_backref, int inc)
+                          int full_backref, int inc, int for_cow)
 {
        u64 bytenr;
        u64 num_bytes;
@@ -2603,7 +2686,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
        int level;
        int ret = 0;
        int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
-                           u64, u64, u64, u64, u64, u64);
+                           u64, u64, u64, u64, u64, u64, int);
 
        ref_root = btrfs_header_owner(buf);
        nritems = btrfs_header_nritems(buf);
@@ -2640,14 +2723,15 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
                        key.offset -= btrfs_file_extent_offset(buf, fi);
                        ret = process_func(trans, root, bytenr, num_bytes,
                                           parent, ref_root, key.objectid,
-                                          key.offset);
+                                          key.offset, for_cow);
                        if (ret)
                                goto fail;
                } else {
                        bytenr = btrfs_node_blockptr(buf, i);
                        num_bytes = btrfs_level_size(root, level - 1);
                        ret = process_func(trans, root, bytenr, num_bytes,
-                                          parent, ref_root, level - 1, 0);
+                                          parent, ref_root, level - 1, 0,
+                                          for_cow);
                        if (ret)
                                goto fail;
                }
@@ -2659,15 +2743,15 @@ fail:
 }
 
 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                 struct extent_buffer *buf, int full_backref)
+                 struct extent_buffer *buf, int full_backref, int for_cow)
 {
-       return __btrfs_mod_ref(trans, root, buf, full_backref, 1);
+       return __btrfs_mod_ref(trans, root, buf, full_backref, 1, for_cow);
 }
 
 int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                 struct extent_buffer *buf, int full_backref)
+                 struct extent_buffer *buf, int full_backref, int for_cow)
 {
-       return __btrfs_mod_ref(trans, root, buf, full_backref, 0);
+       return __btrfs_mod_ref(trans, root, buf, full_backref, 0, for_cow);
 }
 
 static int write_one_cache_group(struct btrfs_trans_handle *trans,
@@ -2993,9 +3077,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
                INIT_LIST_HEAD(&found->block_groups[i]);
        init_rwsem(&found->groups_sem);
        spin_lock_init(&found->lock);
-       found->flags = flags & (BTRFS_BLOCK_GROUP_DATA |
-                               BTRFS_BLOCK_GROUP_SYSTEM |
-                               BTRFS_BLOCK_GROUP_METADATA);
+       found->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
        found->total_bytes = total_bytes;
        found->disk_total = total_bytes * factor;
        found->bytes_used = bytes_used;
@@ -3016,20 +3098,27 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
 
 static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 {
-       u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 |
-                                  BTRFS_BLOCK_GROUP_RAID1 |
-                                  BTRFS_BLOCK_GROUP_RAID10 |
-                                  BTRFS_BLOCK_GROUP_DUP);
-       if (extra_flags) {
-               if (flags & BTRFS_BLOCK_GROUP_DATA)
-                       fs_info->avail_data_alloc_bits |= extra_flags;
-               if (flags & BTRFS_BLOCK_GROUP_METADATA)
-                       fs_info->avail_metadata_alloc_bits |= extra_flags;
-               if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
-                       fs_info->avail_system_alloc_bits |= extra_flags;
-       }
+       u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;
+
+       /* chunk -> extended profile */
+       if (extra_flags == 0)
+               extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+
+       if (flags & BTRFS_BLOCK_GROUP_DATA)
+               fs_info->avail_data_alloc_bits |= extra_flags;
+       if (flags & BTRFS_BLOCK_GROUP_METADATA)
+               fs_info->avail_metadata_alloc_bits |= extra_flags;
+       if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
+               fs_info->avail_system_alloc_bits |= extra_flags;
 }
 
+/*
+ * @flags: available profiles in extended format (see ctree.h)
+ *
+ * Returns reduced profile in chunk format.  If profile changing is in
+ * progress (either running or paused) picks the target profile (if it's
+ * already available), otherwise falls back to plain reducing.
+ */
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 {
        /*
@@ -3040,6 +3129,34 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
        u64 num_devices = root->fs_info->fs_devices->rw_devices +
                root->fs_info->fs_devices->missing_devices;
 
+       /* pick restriper's target profile if it's available */
+       spin_lock(&root->fs_info->balance_lock);
+       if (root->fs_info->balance_ctl) {
+               struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
+               u64 tgt = 0;
+
+               if ((flags & BTRFS_BLOCK_GROUP_DATA) &&
+                   (bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
+                   (flags & bctl->data.target)) {
+                       tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
+               } else if ((flags & BTRFS_BLOCK_GROUP_SYSTEM) &&
+                          (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
+                          (flags & bctl->sys.target)) {
+                       tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
+               } else if ((flags & BTRFS_BLOCK_GROUP_METADATA) &&
+                          (bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
+                          (flags & bctl->meta.target)) {
+                       tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
+               }
+
+               if (tgt) {
+                       spin_unlock(&root->fs_info->balance_lock);
+                       flags = tgt;
+                       goto out;
+               }
+       }
+       spin_unlock(&root->fs_info->balance_lock);
+
        if (num_devices == 1)
                flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
        if (num_devices < 4)
@@ -3059,22 +3176,25 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
        if ((flags & BTRFS_BLOCK_GROUP_RAID0) &&
            ((flags & BTRFS_BLOCK_GROUP_RAID1) |
             (flags & BTRFS_BLOCK_GROUP_RAID10) |
-            (flags & BTRFS_BLOCK_GROUP_DUP)))
+            (flags & BTRFS_BLOCK_GROUP_DUP))) {
                flags &= ~BTRFS_BLOCK_GROUP_RAID0;
+       }
+
+out:
+       /* extended -> chunk profile */
+       flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
        return flags;
 }
 
 static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
 {
        if (flags & BTRFS_BLOCK_GROUP_DATA)
-               flags |= root->fs_info->avail_data_alloc_bits &
-                        root->fs_info->data_alloc_profile;
+               flags |= root->fs_info->avail_data_alloc_bits;
        else if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
-               flags |= root->fs_info->avail_system_alloc_bits &
-                        root->fs_info->system_alloc_profile;
+               flags |= root->fs_info->avail_system_alloc_bits;
        else if (flags & BTRFS_BLOCK_GROUP_METADATA)
-               flags |= root->fs_info->avail_metadata_alloc_bits &
-                        root->fs_info->metadata_alloc_profile;
+               flags |= root->fs_info->avail_metadata_alloc_bits;
+
        return btrfs_reduce_alloc_profile(root, flags);
 }
 
@@ -3191,6 +3311,8 @@ commit_trans:
                return -ENOSPC;
        }
        data_sinfo->bytes_may_use += bytes;
+       trace_btrfs_space_reservation(root->fs_info, "space_info",
+                                     (u64)data_sinfo, bytes, 1);
        spin_unlock(&data_sinfo->lock);
 
        return 0;
@@ -3210,6 +3332,8 @@ void btrfs_free_reserved_data_space(struct inode *inode, u64 bytes)
        data_sinfo = BTRFS_I(inode)->space_info;
        spin_lock(&data_sinfo->lock);
        data_sinfo->bytes_may_use -= bytes;
+       trace_btrfs_space_reservation(root->fs_info, "space_info",
+                                     (u64)data_sinfo, bytes, 0);
        spin_unlock(&data_sinfo->lock);
 }
 
@@ -3257,27 +3381,15 @@ static int should_alloc_chunk(struct btrfs_root *root,
                if (num_bytes - num_allocated < thresh)
                        return 1;
        }
-
-       /*
-        * we have two similar checks here, one based on percentage
-        * and once based on a hard number of 256MB.  The idea
-        * is that if we have a good amount of free
-        * room, don't allocate a chunk.  A good mount is
-        * less than 80% utilized of the chunks we have allocated,
-        * or more than 256MB free
-        */
-       if (num_allocated + alloc_bytes + 256 * 1024 * 1024 < num_bytes)
-               return 0;
-
-       if (num_allocated + alloc_bytes < div_factor(num_bytes, 8))
-               return 0;
-
        thresh = btrfs_super_total_bytes(root->fs_info->super_copy);
 
-       /* 256MB or 5% of the FS */
-       thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5));
+       /* 256MB or 2% of the FS */
+       thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 2));
+       /* system chunks need a much small threshold */
+       if (sinfo->flags & BTRFS_BLOCK_GROUP_SYSTEM)
+               thresh = 32 * 1024 * 1024;
 
-       if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3))
+       if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 8))
                return 0;
        return 1;
 }
@@ -3291,7 +3403,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
        int wait_for_alloc = 0;
        int ret = 0;
 
-       flags = btrfs_reduce_alloc_profile(extent_root, flags);
+       BUG_ON(!profile_is_valid(flags, 0));
 
        space_info = __find_space_info(extent_root->fs_info, flags);
        if (!space_info) {
@@ -3303,7 +3415,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
 
 again:
        spin_lock(&space_info->lock);
-       if (space_info->force_alloc)
+       if (force < space_info->force_alloc)
                force = space_info->force_alloc;
        if (space_info->full) {
                spin_unlock(&space_info->lock);
@@ -3582,6 +3694,10 @@ again:
        if (used <= space_info->total_bytes) {
                if (used + orig_bytes <= space_info->total_bytes) {
                        space_info->bytes_may_use += orig_bytes;
+                       trace_btrfs_space_reservation(root->fs_info,
+                                                     "space_info",
+                                                     (u64)space_info,
+                                                     orig_bytes, 1);
                        ret = 0;
                } else {
                        /*
@@ -3649,6 +3765,10 @@ again:
 
                if (used + num_bytes < space_info->total_bytes + avail) {
                        space_info->bytes_may_use += orig_bytes;
+                       trace_btrfs_space_reservation(root->fs_info,
+                                                     "space_info",
+                                                     (u64)space_info,
+                                                     orig_bytes, 1);
                        ret = 0;
                } else {
                        wait_ordered = true;
@@ -3755,7 +3875,8 @@ static void block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv,
        spin_unlock(&block_rsv->lock);
 }
 
-static void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv,
+static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
+                                   struct btrfs_block_rsv *block_rsv,
                                    struct btrfs_block_rsv *dest, u64 num_bytes)
 {
        struct btrfs_space_info *space_info = block_rsv->space_info;
@@ -3791,6 +3912,9 @@ static void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv,
                if (num_bytes) {
                        spin_lock(&space_info->lock);
                        space_info->bytes_may_use -= num_bytes;
+                       trace_btrfs_space_reservation(fs_info, "space_info",
+                                                     (u64)space_info,
+                                                     num_bytes, 0);
                        space_info->reservation_progress++;
                        spin_unlock(&space_info->lock);
                }
@@ -3947,7 +4071,8 @@ void btrfs_block_rsv_release(struct btrfs_root *root,
        if (global_rsv->full || global_rsv == block_rsv ||
            block_rsv->space_info != global_rsv->space_info)
                global_rsv = NULL;
-       block_rsv_release_bytes(block_rsv, global_rsv, num_bytes);
+       block_rsv_release_bytes(root->fs_info, block_rsv, global_rsv,
+                               num_bytes);
 }
 
 /*
@@ -4006,11 +4131,15 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
                num_bytes = sinfo->total_bytes - num_bytes;
                block_rsv->reserved += num_bytes;
                sinfo->bytes_may_use += num_bytes;
+               trace_btrfs_space_reservation(fs_info, "space_info",
+                                             (u64)sinfo, num_bytes, 1);
        }
 
        if (block_rsv->reserved >= block_rsv->size) {
                num_bytes = block_rsv->reserved - block_rsv->size;
                sinfo->bytes_may_use -= num_bytes;
+               trace_btrfs_space_reservation(fs_info, "space_info",
+                                             (u64)sinfo, num_bytes, 0);
                sinfo->reservation_progress++;
                block_rsv->reserved = block_rsv->size;
                block_rsv->full = 1;
@@ -4045,7 +4174,8 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
 
 static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
 {
-       block_rsv_release_bytes(&fs_info->global_block_rsv, NULL, (u64)-1);
+       block_rsv_release_bytes(fs_info, &fs_info->global_block_rsv, NULL,
+                               (u64)-1);
        WARN_ON(fs_info->delalloc_block_rsv.size > 0);
        WARN_ON(fs_info->delalloc_block_rsv.reserved > 0);
        WARN_ON(fs_info->trans_block_rsv.size > 0);
@@ -4062,6 +4192,8 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
        if (!trans->bytes_reserved)
                return;
 
+       trace_btrfs_space_reservation(root->fs_info, "transaction", (u64)trans,
+                                     trans->bytes_reserved, 0);
        btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
        trans->bytes_reserved = 0;
 }
@@ -4079,6 +4211,8 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
         * when we are truly done with the orphan item.
         */
        u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
+       trace_btrfs_space_reservation(root->fs_info, "orphan",
+                                     btrfs_ino(inode), num_bytes, 1);
        return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
 }
 
@@ -4086,6 +4220,8 @@ void btrfs_orphan_release_metadata(struct inode *inode)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
+       trace_btrfs_space_reservation(root->fs_info, "orphan",
+                                     btrfs_ino(inode), num_bytes, 0);
        btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);
 }
 
@@ -4213,12 +4349,11 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        /* Need to be holding the i_mutex here if we aren't free space cache */
        if (btrfs_is_free_space_inode(root, inode))
                flush = 0;
-       else
-               WARN_ON(!mutex_is_locked(&inode->i_mutex));
 
        if (flush && btrfs_transaction_in_commit(root->fs_info))
                schedule_timeout(1);
 
+       mutex_lock(&BTRFS_I(inode)->delalloc_mutex);
        num_bytes = ALIGN(num_bytes, root->sectorsize);
 
        spin_lock(&BTRFS_I(inode)->lock);
@@ -4266,8 +4401,14 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
                if (dropped)
                        to_free += btrfs_calc_trans_metadata_size(root, dropped);
 
-               if (to_free)
+               if (to_free) {
                        btrfs_block_rsv_release(root, block_rsv, to_free);
+                       trace_btrfs_space_reservation(root->fs_info,
+                                                     "delalloc",
+                                                     btrfs_ino(inode),
+                                                     to_free, 0);
+               }
+               mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
                return ret;
        }
 
@@ -4278,7 +4419,11 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        }
        BTRFS_I(inode)->reserved_extents += nr_extents;
        spin_unlock(&BTRFS_I(inode)->lock);
+       mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
 
+       if (to_reserve)
+               trace_btrfs_space_reservation(root->fs_info,"delalloc",
+                                             btrfs_ino(inode), to_reserve, 1);
        block_rsv_add_bytes(block_rsv, to_reserve, 1);
 
        return 0;
@@ -4308,6 +4453,8 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
        if (dropped > 0)
                to_free += btrfs_calc_trans_metadata_size(root, dropped);
 
+       trace_btrfs_space_reservation(root->fs_info, "delalloc",
+                                     btrfs_ino(inode), to_free, 0);
        btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv,
                                to_free);
 }
@@ -4562,7 +4709,10 @@ static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
                        cache->reserved += num_bytes;
                        space_info->bytes_reserved += num_bytes;
                        if (reserve == RESERVE_ALLOC) {
-                               BUG_ON(space_info->bytes_may_use < num_bytes);
+                               trace_btrfs_space_reservation(cache->fs_info,
+                                                             "space_info",
+                                                             (u64)space_info,
+                                                             num_bytes, 0);
                                space_info->bytes_may_use -= num_bytes;
                        }
                }
@@ -4928,6 +5078,8 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
        rb_erase(&head->node.rb_node, &delayed_refs->root);
 
        delayed_refs->num_entries--;
+       if (waitqueue_active(&delayed_refs->seq_wait))
+               wake_up(&delayed_refs->seq_wait);
 
        /*
         * we don't take a ref on the node because we're removing it from the
@@ -4955,16 +5107,17 @@ out:
 void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           struct extent_buffer *buf,
-                          u64 parent, int last_ref)
+                          u64 parent, int last_ref, int for_cow)
 {
        struct btrfs_block_group_cache *cache = NULL;
        int ret;
 
        if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
-               ret = btrfs_add_delayed_tree_ref(trans, buf->start, buf->len,
-                                               parent, root->root_key.objectid,
-                                               btrfs_header_level(buf),
-                                               BTRFS_DROP_DELAYED_REF, NULL);
+               ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
+                                       buf->start, buf->len,
+                                       parent, root->root_key.objectid,
+                                       btrfs_header_level(buf),
+                                       BTRFS_DROP_DELAYED_REF, NULL, for_cow);
                BUG_ON(ret);
        }
 
@@ -4999,12 +5152,12 @@ out:
        btrfs_put_block_group(cache);
 }
 
-int btrfs_free_extent(struct btrfs_trans_handle *trans,
-                     struct btrfs_root *root,
-                     u64 bytenr, u64 num_bytes, u64 parent,
-                     u64 root_objectid, u64 owner, u64 offset)
+int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+                     u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
+                     u64 owner, u64 offset, int for_cow)
 {
        int ret;
+       struct btrfs_fs_info *fs_info = root->fs_info;
 
        /*
         * tree log blocks never actually go into the extent allocation
@@ -5016,14 +5169,17 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
                btrfs_pin_extent(root, bytenr, num_bytes, 1);
                ret = 0;
        } else if (owner < BTRFS_FIRST_FREE_OBJECTID) {
-               ret = btrfs_add_delayed_tree_ref(trans, bytenr, num_bytes,
+               ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
+                                       num_bytes,
                                        parent, root_objectid, (int)owner,
-                                       BTRFS_DROP_DELAYED_REF, NULL);
+                                       BTRFS_DROP_DELAYED_REF, NULL, for_cow);
                BUG_ON(ret);
        } else {
-               ret = btrfs_add_delayed_data_ref(trans, bytenr, num_bytes,
-                                       parent, root_objectid, owner,
-                                       offset, BTRFS_DROP_DELAYED_REF, NULL);
+               ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
+                                               num_bytes,
+                                               parent, root_objectid, owner,
+                                               offset, BTRFS_DROP_DELAYED_REF,
+                                               NULL, for_cow);
                BUG_ON(ret);
        }
        return ret;
@@ -5146,6 +5302,8 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        ins->objectid = 0;
        ins->offset = 0;
 
+       trace_find_free_extent(orig_root, num_bytes, empty_size, data);
+
        space_info = __find_space_info(root->fs_info, data);
        if (!space_info) {
                printk(KERN_ERR "No space info for %llu\n", data);
@@ -5295,15 +5453,6 @@ 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_cluster + empty_size) {
-                       spin_unlock(&block_group->free_space_ctl->tree_lock);
-                       goto loop;
-               }
-               spin_unlock(&block_group->free_space_ctl->tree_lock);
-
                /*
                 * Ok we want to try and use the cluster allocator, so
                 * lets look there
@@ -5331,6 +5480,8 @@ alloc:
                        if (offset) {
                                /* we have a block, we're done */
                                spin_unlock(&last_ptr->refill_lock);
+                               trace_btrfs_reserve_extent_cluster(root,
+                                       block_group, search_start, num_bytes);
                                goto checks;
                        }
 
@@ -5349,8 +5500,15 @@ refill_cluster:
                         * plenty of times and not have found
                         * anything, so we are likely way too
                         * fragmented for the clustering stuff to find
-                        * anything.  */
-                       if (loop >= LOOP_NO_EMPTY_SIZE) {
+                        * anything.
+                        *
+                        * However, if the cluster is taken from the
+                        * current block group, release the cluster
+                        * first, so that we stand a better chance of
+                        * succeeding in the unclustered
+                        * allocation.  */
+                       if (loop >= LOOP_NO_EMPTY_SIZE &&
+                           last_ptr->block_group != block_group) {
                                spin_unlock(&last_ptr->refill_lock);
                                goto unclustered_alloc;
                        }
@@ -5361,6 +5519,11 @@ refill_cluster:
                         */
                        btrfs_return_cluster_to_free_space(NULL, last_ptr);
 
+                       if (loop >= LOOP_NO_EMPTY_SIZE) {
+                               spin_unlock(&last_ptr->refill_lock);
+                               goto unclustered_alloc;
+                       }
+
                        /* allocate a cluster in this block group */
                        ret = btrfs_find_space_cluster(trans, root,
                                               block_group, last_ptr,
@@ -5377,6 +5540,9 @@ refill_cluster:
                                if (offset) {
                                        /* we found one, proceed */
                                        spin_unlock(&last_ptr->refill_lock);
+                                       trace_btrfs_reserve_extent_cluster(root,
+                                               block_group, search_start,
+                                               num_bytes);
                                        goto checks;
                                }
                        } else if (!cached && loop > LOOP_CACHING_NOWAIT
@@ -5401,6 +5567,15 @@ refill_cluster:
                }
 
 unclustered_alloc:
+               spin_lock(&block_group->free_space_ctl->tree_lock);
+               if (cached &&
+                   block_group->free_space_ctl->free_space <
+                   num_bytes + empty_cluster + empty_size) {
+                       spin_unlock(&block_group->free_space_ctl->tree_lock);
+                       goto loop;
+               }
+               spin_unlock(&block_group->free_space_ctl->tree_lock);
+
                offset = btrfs_find_space_for_alloc(block_group, search_start,
                                                    num_bytes, empty_size);
                /*
@@ -5438,9 +5613,6 @@ checks:
                        goto loop;
                }
 
-               ins->objectid = search_start;
-               ins->offset = num_bytes;
-
                if (offset < search_start)
                        btrfs_add_free_space(used_block_group, offset,
                                             search_start - offset);
@@ -5457,6 +5629,8 @@ checks:
                ins->objectid = search_start;
                ins->offset = num_bytes;
 
+               trace_btrfs_reserve_extent(orig_root, block_group,
+                                          search_start, num_bytes);
                if (offset < search_start)
                        btrfs_add_free_space(used_block_group, offset,
                                             search_start - offset);
@@ -5621,6 +5795,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
                         u64 search_end, struct btrfs_key *ins,
                         u64 data)
 {
+       bool final_tried = false;
        int ret;
        u64 search_start = 0;
 
@@ -5640,22 +5815,25 @@ again:
                               search_start, search_end, hint_byte,
                               ins, data);
 
-       if (ret == -ENOSPC && num_bytes > min_alloc_size) {
-               num_bytes = num_bytes >> 1;
-               num_bytes = num_bytes & ~(root->sectorsize - 1);
-               num_bytes = max(num_bytes, min_alloc_size);
-               do_chunk_alloc(trans, root->fs_info->extent_root,
-                              num_bytes, data, CHUNK_ALLOC_FORCE);
-               goto again;
-       }
-       if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
-               struct btrfs_space_info *sinfo;
-
-               sinfo = __find_space_info(root->fs_info, data);
-               printk(KERN_ERR "btrfs allocation failed flags %llu, "
-                      "wanted %llu\n", (unsigned long long)data,
-                      (unsigned long long)num_bytes);
-               dump_space_info(sinfo, num_bytes, 1);
+       if (ret == -ENOSPC) {
+               if (!final_tried) {
+                       num_bytes = num_bytes >> 1;
+                       num_bytes = num_bytes & ~(root->sectorsize - 1);
+                       num_bytes = max(num_bytes, min_alloc_size);
+                       do_chunk_alloc(trans, root->fs_info->extent_root,
+                                      num_bytes, data, CHUNK_ALLOC_FORCE);
+                       if (num_bytes == min_alloc_size)
+                               final_tried = true;
+                       goto again;
+               } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+                       struct btrfs_space_info *sinfo;
+
+                       sinfo = __find_space_info(root->fs_info, data);
+                       printk(KERN_ERR "btrfs allocation failed flags %llu, "
+                              "wanted %llu\n", (unsigned long long)data,
+                              (unsigned long long)num_bytes);
+                       dump_space_info(sinfo, num_bytes, 1);
+               }
        }
 
        trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
@@ -5842,9 +6020,10 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
 
        BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID);
 
-       ret = btrfs_add_delayed_data_ref(trans, ins->objectid, ins->offset,
-                                        0, root_objectid, owner, offset,
-                                        BTRFS_ADD_DELAYED_EXTENT, NULL);
+       ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid,
+                                        ins->offset, 0,
+                                        root_objectid, owner, offset,
+                                        BTRFS_ADD_DELAYED_EXTENT, NULL, 0);
        return ret;
 }
 
@@ -5997,10 +6176,11 @@ use_block_rsv(struct btrfs_trans_handle *trans,
        return ERR_PTR(-ENOSPC);
 }
 
-static void unuse_block_rsv(struct btrfs_block_rsv *block_rsv, u32 blocksize)
+static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
+                           struct btrfs_block_rsv *block_rsv, u32 blocksize)
 {
        block_rsv_add_bytes(block_rsv, blocksize, 0);
-       block_rsv_release_bytes(block_rsv, NULL, 0);
+       block_rsv_release_bytes(fs_info, block_rsv, NULL, 0);
 }
 
 /*
@@ -6014,7 +6194,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root, u32 blocksize,
                                        u64 parent, u64 root_objectid,
                                        struct btrfs_disk_key *key, int level,
-                                       u64 hint, u64 empty_size)
+                                       u64 hint, u64 empty_size, int for_cow)
 {
        struct btrfs_key ins;
        struct btrfs_block_rsv *block_rsv;
@@ -6030,7 +6210,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
        ret = btrfs_reserve_extent(trans, root, blocksize, blocksize,
                                   empty_size, hint, (u64)-1, &ins, 0);
        if (ret) {
-               unuse_block_rsv(block_rsv, blocksize);
+               unuse_block_rsv(root->fs_info, block_rsv, blocksize);
                return ERR_PTR(ret);
        }
 
@@ -6058,10 +6238,11 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                extent_op->update_flags = 1;
                extent_op->is_data = 0;
 
-               ret = btrfs_add_delayed_tree_ref(trans, ins.objectid,
+               ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
+                                       ins.objectid,
                                        ins.offset, parent, root_objectid,
                                        level, BTRFS_ADD_DELAYED_EXTENT,
-                                       extent_op);
+                                       extent_op, for_cow);
                BUG_ON(ret);
        }
        return buf;
@@ -6078,6 +6259,7 @@ struct walk_control {
        int keep_locks;
        int reada_slot;
        int reada_count;
+       int for_reloc;
 };
 
 #define DROP_REFERENCE 1
@@ -6216,9 +6398,9 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
        /* wc->stage == UPDATE_BACKREF */
        if (!(wc->flags[level] & flag)) {
                BUG_ON(!path->locks[level]);
-               ret = btrfs_inc_ref(trans, root, eb, 1);
+               ret = btrfs_inc_ref(trans, root, eb, 1, wc->for_reloc);
                BUG_ON(ret);
-               ret = btrfs_dec_ref(trans, root, eb, 0);
+               ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc);
                BUG_ON(ret);
                ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
                                                  eb->len, flag, 0);
@@ -6362,7 +6544,7 @@ skip:
                }
 
                ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
-                                       root->root_key.objectid, level - 1, 0);
+                               root->root_key.objectid, level - 1, 0, 0);
                BUG_ON(ret);
        }
        btrfs_tree_unlock(next);
@@ -6436,9 +6618,11 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
        if (wc->refs[level] == 1) {
                if (level == 0) {
                        if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
-                               ret = btrfs_dec_ref(trans, root, eb, 1);
+                               ret = btrfs_dec_ref(trans, root, eb, 1,
+                                                   wc->for_reloc);
                        else
-                               ret = btrfs_dec_ref(trans, root, eb, 0);
+                               ret = btrfs_dec_ref(trans, root, eb, 0,
+                                                   wc->for_reloc);
                        BUG_ON(ret);
                }
                /* make block locked assertion in clean_tree_block happy */
@@ -6465,7 +6649,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                               btrfs_header_owner(path->nodes[level + 1]));
        }
 
-       btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1);
+       btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1, 0);
 out:
        wc->refs[level] = 0;
        wc->flags[level] = 0;
@@ -6549,7 +6733,8 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
  * blocks are properly updated.
  */
 void btrfs_drop_snapshot(struct btrfs_root *root,
-                        struct btrfs_block_rsv *block_rsv, int update_ref)
+                        struct btrfs_block_rsv *block_rsv, int update_ref,
+                        int for_reloc)
 {
        struct btrfs_path *path;
        struct btrfs_trans_handle *trans;
@@ -6637,6 +6822,7 @@ void btrfs_drop_snapshot(struct btrfs_root *root,
        wc->stage = DROP_REFERENCE;
        wc->update_ref = update_ref;
        wc->keep_locks = 0;
+       wc->for_reloc = for_reloc;
        wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root);
 
        while (1) {
@@ -6721,6 +6907,7 @@ out:
  * drop subtree rooted at tree block 'node'.
  *
  * NOTE: this function will unlock and release tree block 'node'
+ * only used by relocation code
  */
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
@@ -6765,6 +6952,7 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
        wc->stage = DROP_REFERENCE;
        wc->update_ref = 0;
        wc->keep_locks = 1;
+       wc->for_reloc = 1;
        wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root);
 
        while (1) {
@@ -6792,6 +6980,29 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
        u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
                BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
 
+       if (root->fs_info->balance_ctl) {
+               struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
+               u64 tgt = 0;
+
+               /* pick restriper's target profile and return */
+               if (flags & BTRFS_BLOCK_GROUP_DATA &&
+                   bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) {
+                       tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
+               } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM &&
+                          bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
+                       tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
+               } else if (flags & BTRFS_BLOCK_GROUP_METADATA &&
+                          bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) {
+                       tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
+               }
+
+               if (tgt) {
+                       /* extended -> chunk profile */
+                       tgt &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+                       return tgt;
+               }
+       }
+
        /*
         * we add in the count of missing devices because we want
         * to make sure that any RAID levels on a degraded FS
@@ -7085,7 +7296,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
                 * space to fit our block group in.
                 */
                if (device->total_bytes > device->bytes_used + min_free) {
-                       ret = find_free_dev_extent(NULL, device, min_free,
+                       ret = find_free_dev_extent(device, min_free,
                                                   &dev_offset, NULL);
                        if (!ret)
                                dev_nr++;
@@ -7447,6 +7658,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        ret = update_space_info(root->fs_info, cache->flags, size, bytes_used,
                                &cache->space_info);
        BUG_ON(ret);
+       update_global_block_rsv(root->fs_info);
 
        spin_lock(&cache->space_info->lock);
        cache->space_info->bytes_readonly += cache->bytes_super;
@@ -7466,6 +7678,22 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
+{
+       u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;
+
+       /* chunk -> extended profile */
+       if (extra_flags == 0)
+               extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+
+       if (flags & BTRFS_BLOCK_GROUP_DATA)
+               fs_info->avail_data_alloc_bits &= ~extra_flags;
+       if (flags & BTRFS_BLOCK_GROUP_METADATA)
+               fs_info->avail_metadata_alloc_bits &= ~extra_flags;
+       if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
+               fs_info->avail_system_alloc_bits &= ~extra_flags;
+}
+
 int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, u64 group_start)
 {
@@ -7476,6 +7704,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        struct btrfs_key key;
        struct inode *inode;
        int ret;
+       int index;
        int factor;
 
        root = root->fs_info->extent_root;
@@ -7491,6 +7720,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        free_excluded_extents(root, block_group);
 
        memcpy(&key, &block_group->key, sizeof(key));
+       index = get_block_group_index(block_group);
        if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP |
                                  BTRFS_BLOCK_GROUP_RAID1 |
                                  BTRFS_BLOCK_GROUP_RAID10))
@@ -7565,6 +7795,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
         * are still on the list after taking the semaphore
         */
        list_del_init(&block_group->list);
+       if (list_empty(&block_group->space_info->block_groups[index]))
+               clear_avail_alloc_bits(root->fs_info, block_group->flags);
        up_write(&block_group->space_info->groups_sem);
 
        if (block_group->cached == BTRFS_CACHE_STARTED)
index 49f3c9dc09f4c81902299fd81c62da1ed8423250..fcf77e1ded40e8d47ed8f64742d8139a61295023 100644 (file)
@@ -18,6 +18,7 @@
 #include "ctree.h"
 #include "btrfs_inode.h"
 #include "volumes.h"
+#include "check-integrity.h"
 
 static struct kmem_cache *extent_state_cache;
 static struct kmem_cache *extent_buffer_cache;
@@ -1895,7 +1896,7 @@ int repair_io_failure(struct btrfs_mapping_tree *map_tree, u64 start,
        }
        bio->bi_bdev = dev->bdev;
        bio_add_page(bio, page, length, start-page_offset(page));
-       submit_bio(WRITE_SYNC, bio);
+       btrfsic_submit_bio(WRITE_SYNC, bio);
        wait_for_completion(&compl);
 
        if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
@@ -2393,7 +2394,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num,
                ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio,
                                           mirror_num, bio_flags, start);
        else
-               submit_bio(rw, bio);
+               btrfsic_submit_bio(rw, bio);
 
        if (bio_flagged(bio, BIO_EOPNOTSUPP))
                ret = -EOPNOTSUPP;
@@ -3579,6 +3580,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
        atomic_set(&eb->blocking_writers, 0);
        atomic_set(&eb->spinning_readers, 0);
        atomic_set(&eb->spinning_writers, 0);
+       eb->lock_nested = 0;
        init_waitqueue_head(&eb->write_lock_wq);
        init_waitqueue_head(&eb->read_lock_wq);
 
@@ -3907,6 +3909,8 @@ int extent_range_uptodate(struct extent_io_tree *tree,
        while (start <= end) {
                index = start >> PAGE_CACHE_SHIFT;
                page = find_get_page(tree->mapping, index);
+               if (!page)
+                       return 1;
                uptodate = PageUptodate(page);
                page_cache_release(page);
                if (!uptodate) {
index 7604c30013227fd823b1523503f8faaeccf283c4..bc6a042cb6fc496e6910d21fb3cdaec000f43b8e 100644 (file)
@@ -129,6 +129,7 @@ struct extent_buffer {
        struct list_head leak_list;
        struct rcu_head rcu_head;
        atomic_t refs;
+       pid_t lock_owner;
 
        /* count of read lock holders on the extent buffer */
        atomic_t write_locks;
@@ -137,6 +138,7 @@ struct extent_buffer {
        atomic_t blocking_readers;
        atomic_t spinning_readers;
        atomic_t spinning_writers;
+       int lock_nested;
 
        /* protects write locks */
        rwlock_t lock;
index 034d985032296cd4dfbc80e4d6717ac8b4ea77c4..859ba2dd88903ba207c7b0e448e0f5ce7f99e46e 100644 (file)
@@ -678,7 +678,7 @@ next_slot:
                                                disk_bytenr, num_bytes, 0,
                                                root->root_key.objectid,
                                                new_key.objectid,
-                                               start - extent_offset);
+                                               start - extent_offset, 0);
                                BUG_ON(ret);
                                *hint_byte = disk_bytenr;
                        }
@@ -753,7 +753,7 @@ next_slot:
                                                disk_bytenr, num_bytes, 0,
                                                root->root_key.objectid,
                                                key.objectid, key.offset -
-                                               extent_offset);
+                                               extent_offset, 0);
                                BUG_ON(ret);
                                inode_sub_bytes(inode,
                                                extent_end - key.offset);
@@ -962,7 +962,7 @@ again:
 
                ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
                                           root->root_key.objectid,
-                                          ino, orig_offset);
+                                          ino, orig_offset, 0);
                BUG_ON(ret);
 
                if (split == start) {
@@ -989,7 +989,7 @@ again:
                del_nr++;
                ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
                                        0, root->root_key.objectid,
-                                       ino, orig_offset);
+                                       ino, orig_offset, 0);
                BUG_ON(ret);
        }
        other_start = 0;
@@ -1006,7 +1006,7 @@ again:
                del_nr++;
                ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
                                        0, root->root_key.objectid,
-                                       ino, orig_offset);
+                                       ino, orig_offset, 0);
                BUG_ON(ret);
        }
        if (del_nr == 0) {
@@ -1274,7 +1274,6 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                                                   dirty_pages);
                if (dirty_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
                        btrfs_btree_balance_dirty(root, 1);
-               btrfs_throttle(root);
 
                pos += copied;
                num_written += copied;
index 9a897bf795380808e728c8d074cb58c5bcd9cf89..c2f20594c9f74fde7e97cbdf4dea728b9c5a4bd8 100644 (file)
@@ -319,9 +319,11 @@ static void io_ctl_drop_pages(struct io_ctl *io_ctl)
        io_ctl_unmap_page(io_ctl);
 
        for (i = 0; i < io_ctl->num_pages; i++) {
-               ClearPageChecked(io_ctl->pages[i]);
-               unlock_page(io_ctl->pages[i]);
-               page_cache_release(io_ctl->pages[i]);
+               if (io_ctl->pages[i]) {
+                       ClearPageChecked(io_ctl->pages[i]);
+                       unlock_page(io_ctl->pages[i]);
+                       page_cache_release(io_ctl->pages[i]);
+               }
        }
 }
 
@@ -635,7 +637,10 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
        if (!num_entries)
                return 0;
 
-       io_ctl_init(&io_ctl, inode, root);
+       ret = io_ctl_init(&io_ctl, inode, root);
+       if (ret)
+               return ret;
+
        ret = readahead_cache(inode);
        if (ret)
                goto out;
@@ -838,7 +843,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
        struct io_ctl io_ctl;
        struct list_head bitmap_list;
        struct btrfs_key key;
-       u64 start, end, len;
+       u64 start, extent_start, extent_end, len;
        int entries = 0;
        int bitmaps = 0;
        int ret;
@@ -849,7 +854,9 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
        if (!i_size_read(inode))
                return -1;
 
-       io_ctl_init(&io_ctl, inode, root);
+       ret = io_ctl_init(&io_ctl, inode, root);
+       if (ret)
+               return -1;
 
        /* Get the cluster for this block_group if it exists */
        if (block_group && !list_empty(&block_group->cluster_list))
@@ -857,25 +864,12 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
                                     struct btrfs_free_cluster,
                                     block_group_list);
 
-       /*
-        * We shouldn't have switched the pinned extents yet so this is the
-        * right one
-        */
-       unpin = root->fs_info->pinned_extents;
-
        /* Lock all pages first so we can lock the extent safely. */
        io_ctl_prepare_pages(&io_ctl, inode, 0);
 
        lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1,
                         0, &cached_state, GFP_NOFS);
 
-       /*
-        * When searching for pinned extents, we need to start at our start
-        * offset.
-        */
-       if (block_group)
-               start = block_group->key.objectid;
-
        node = rb_first(&ctl->free_space_offset);
        if (!node && cluster) {
                node = rb_first(&cluster->root);
@@ -918,9 +912,20 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
         * We want to add any pinned extents to our free space cache
         * so we don't leak the space
         */
+
+       /*
+        * We shouldn't have switched the pinned extents yet so this is the
+        * right one
+        */
+       unpin = root->fs_info->pinned_extents;
+
+       if (block_group)
+               start = block_group->key.objectid;
+
        while (block_group && (start < block_group->key.objectid +
                               block_group->key.offset)) {
-               ret = find_first_extent_bit(unpin, start, &start, &end,
+               ret = find_first_extent_bit(unpin, start,
+                                           &extent_start, &extent_end,
                                            EXTENT_DIRTY);
                if (ret) {
                        ret = 0;
@@ -928,20 +933,21 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
                }
 
                /* This pinned extent is out of our range */
-               if (start >= block_group->key.objectid +
+               if (extent_start >= block_group->key.objectid +
                    block_group->key.offset)
                        break;
 
-               len = block_group->key.objectid +
-                       block_group->key.offset - start;
-               len = min(len, end + 1 - start);
+               extent_start = max(extent_start, start);
+               extent_end = min(block_group->key.objectid +
+                                block_group->key.offset, extent_end + 1);
+               len = extent_end - extent_start;
 
                entries++;
-               ret = io_ctl_add_entry(&io_ctl, start, len, NULL);
+               ret = io_ctl_add_entry(&io_ctl, extent_start, len, NULL);
                if (ret)
                        goto out_nospc;
 
-               start = end + 1;
+               start = extent_end;
        }
 
        /* Write out the bitmaps */
@@ -2236,7 +2242,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                if (entry->bitmap) {
                        ret = btrfs_alloc_from_bitmap(block_group,
                                                      cluster, entry, bytes,
-                                                     min_start);
+                                                     cluster->window_start);
                        if (ret == 0) {
                                node = rb_next(&entry->offset_index);
                                if (!node)
@@ -2245,6 +2251,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                                                 offset_index);
                                continue;
                        }
+                       cluster->window_start += bytes;
                } else {
                        ret = entry->offset;
 
@@ -2283,23 +2290,23 @@ out:
 static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group,
                                struct btrfs_free_space *entry,
                                struct btrfs_free_cluster *cluster,
-                               u64 offset, u64 bytes, u64 min_bytes)
+                               u64 offset, u64 bytes,
+                               u64 cont1_bytes, u64 min_bytes)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        unsigned long next_zero;
        unsigned long i;
-       unsigned long search_bits;
-       unsigned long total_bits;
+       unsigned long want_bits;
+       unsigned long min_bits;
        unsigned long found_bits;
        unsigned long start = 0;
        unsigned long total_found = 0;
        int ret;
-       bool found = false;
 
        i = offset_to_bit(entry->offset, block_group->sectorsize,
                          max_t(u64, offset, entry->offset));
-       search_bits = bytes_to_bits(bytes, block_group->sectorsize);
-       total_bits = bytes_to_bits(min_bytes, block_group->sectorsize);
+       want_bits = bytes_to_bits(bytes, block_group->sectorsize);
+       min_bits = bytes_to_bits(min_bytes, block_group->sectorsize);
 
 again:
        found_bits = 0;
@@ -2308,7 +2315,7 @@ again:
             i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i + 1)) {
                next_zero = find_next_zero_bit(entry->bitmap,
                                               BITS_PER_BITMAP, i);
-               if (next_zero - i >= search_bits) {
+               if (next_zero - i >= min_bits) {
                        found_bits = next_zero - i;
                        break;
                }
@@ -2318,10 +2325,9 @@ again:
        if (!found_bits)
                return -ENOSPC;
 
-       if (!found) {
+       if (!total_found) {
                start = i;
                cluster->max_size = 0;
-               found = true;
        }
 
        total_found += found_bits;
@@ -2329,13 +2335,8 @@ again:
        if (cluster->max_size < found_bits * block_group->sectorsize)
                cluster->max_size = found_bits * block_group->sectorsize;
 
-       if (total_found < total_bits) {
-               i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, next_zero);
-               if (i - start > total_bits * 2) {
-                       total_found = 0;
-                       cluster->max_size = 0;
-                       found = false;
-               }
+       if (total_found < want_bits || cluster->max_size < cont1_bytes) {
+               i = next_zero + 1;
                goto again;
        }
 
@@ -2346,28 +2347,31 @@ again:
                                 &entry->offset_index, 1);
        BUG_ON(ret);
 
+       trace_btrfs_setup_cluster(block_group, cluster,
+                                 total_found * block_group->sectorsize, 1);
        return 0;
 }
 
 /*
  * This searches the block group for just extents to fill the cluster with.
+ * Try to find a cluster with at least bytes total bytes, at least one
+ * extent of cont1_bytes, and other clusters of at least min_bytes.
  */
 static noinline int
 setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
                        struct btrfs_free_cluster *cluster,
                        struct list_head *bitmaps, u64 offset, u64 bytes,
-                       u64 min_bytes)
+                       u64 cont1_bytes, u64 min_bytes)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *first = NULL;
        struct btrfs_free_space *entry = NULL;
-       struct btrfs_free_space *prev = NULL;
        struct btrfs_free_space *last;
        struct rb_node *node;
        u64 window_start;
        u64 window_free;
        u64 max_extent;
-       u64 max_gap = 128 * 1024;
+       u64 total_size = 0;
 
        entry = tree_search_offset(ctl, offset, 0, 1);
        if (!entry)
@@ -2377,8 +2381,8 @@ setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
         * We don't want bitmaps, so just move along until we find a normal
         * extent entry.
         */
-       while (entry->bitmap) {
-               if (list_empty(&entry->list))
+       while (entry->bitmap || entry->bytes < min_bytes) {
+               if (entry->bitmap && list_empty(&entry->list))
                        list_add_tail(&entry->list, bitmaps);
                node = rb_next(&entry->offset_index);
                if (!node)
@@ -2391,12 +2395,9 @@ setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
        max_extent = entry->bytes;
        first = entry;
        last = entry;
-       prev = entry;
 
-       while (window_free <= min_bytes) {
-               node = rb_next(&entry->offset_index);
-               if (!node)
-                       return -ENOSPC;
+       for (node = rb_next(&entry->offset_index); node;
+            node = rb_next(&entry->offset_index)) {
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
 
                if (entry->bitmap) {
@@ -2405,26 +2406,18 @@ setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
                        continue;
                }
 
-               /*
-                * we haven't filled the empty size and the window is
-                * very large.  reset and try again
-                */
-               if (entry->offset - (prev->offset + prev->bytes) > max_gap ||
-                   entry->offset - window_start > (min_bytes * 2)) {
-                       first = entry;
-                       window_start = entry->offset;
-                       window_free = entry->bytes;
-                       last = entry;
+               if (entry->bytes < min_bytes)
+                       continue;
+
+               last = entry;
+               window_free += entry->bytes;
+               if (entry->bytes > max_extent)
                        max_extent = entry->bytes;
-               } else {
-                       last = entry;
-                       window_free += entry->bytes;
-                       if (entry->bytes > max_extent)
-                               max_extent = entry->bytes;
-               }
-               prev = entry;
        }
 
+       if (window_free < bytes || max_extent < cont1_bytes)
+               return -ENOSPC;
+
        cluster->window_start = first->offset;
 
        node = &first->offset_index;
@@ -2438,17 +2431,18 @@ setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
 
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
                node = rb_next(&entry->offset_index);
-               if (entry->bitmap)
+               if (entry->bitmap || entry->bytes < min_bytes)
                        continue;
 
                rb_erase(&entry->offset_index, &ctl->free_space_offset);
                ret = tree_insert_offset(&cluster->root, entry->offset,
                                         &entry->offset_index, 0);
+               total_size += entry->bytes;
                BUG_ON(ret);
        } while (node && entry != last);
 
        cluster->max_size = max_extent;
-
+       trace_btrfs_setup_cluster(block_group, cluster, total_size, 0);
        return 0;
 }
 
@@ -2460,7 +2454,7 @@ static noinline int
 setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
                     struct btrfs_free_cluster *cluster,
                     struct list_head *bitmaps, u64 offset, u64 bytes,
-                    u64 min_bytes)
+                    u64 cont1_bytes, u64 min_bytes)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
@@ -2482,10 +2476,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
        }
 
        list_for_each_entry(entry, bitmaps, list) {
-               if (entry->bytes < min_bytes)
+               if (entry->bytes < bytes)
                        continue;
                ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
-                                          bytes, min_bytes);
+                                          bytes, cont1_bytes, min_bytes);
                if (!ret)
                        return 0;
        }
@@ -2499,7 +2493,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
 
 /*
  * here we try to find a cluster of blocks in a block group.  The goal
- * is to find at least bytes free and up to empty_size + bytes free.
+ * is to find at least bytes+empty_size.
  * We might not find them all in one contiguous area.
  *
  * returns zero and sets up cluster if things worked out, otherwise
@@ -2515,23 +2509,24 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
        struct btrfs_free_space *entry, *tmp;
        LIST_HEAD(bitmaps);
        u64 min_bytes;
+       u64 cont1_bytes;
        int ret;
 
-       /* for metadata, allow allocates with more holes */
+       /*
+        * Choose the minimum extent size we'll require for this
+        * cluster.  For SSD_SPREAD, don't allow any fragmentation.
+        * For metadata, allow allocates with smaller extents.  For
+        * data, keep it dense.
+        */
        if (btrfs_test_opt(root, SSD_SPREAD)) {
-               min_bytes = bytes + empty_size;
+               cont1_bytes = min_bytes = bytes + empty_size;
        } else if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) {
-               /*
-                * we want to do larger allocations when we are
-                * flushing out the delayed refs, it helps prevent
-                * making more work as we go along.
-                */
-               if (trans->transaction->delayed_refs.flushing)
-                       min_bytes = max(bytes, (bytes + empty_size) >> 1);
-               else
-                       min_bytes = max(bytes, (bytes + empty_size) >> 4);
-       } else
-               min_bytes = max(bytes, (bytes + empty_size) >> 2);
+               cont1_bytes = bytes;
+               min_bytes = block_group->sectorsize;
+       } else {
+               cont1_bytes = max(bytes, (bytes + empty_size) >> 2);
+               min_bytes = block_group->sectorsize;
+       }
 
        spin_lock(&ctl->tree_lock);
 
@@ -2539,7 +2534,7 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
         * If we know we don't have enough space to make a cluster don't even
         * bother doing all the work to try and find one.
         */
-       if (ctl->free_space < min_bytes) {
+       if (ctl->free_space < bytes) {
                spin_unlock(&ctl->tree_lock);
                return -ENOSPC;
        }
@@ -2552,11 +2547,17 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                goto out;
        }
 
+       trace_btrfs_find_cluster(block_group, offset, bytes, empty_size,
+                                min_bytes);
+
+       INIT_LIST_HEAD(&bitmaps);
        ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
-                                     bytes, min_bytes);
+                                     bytes + empty_size,
+                                     cont1_bytes, min_bytes);
        if (ret)
                ret = setup_cluster_bitmap(block_group, cluster, &bitmaps,
-                                          offset, bytes, min_bytes);
+                                          offset, bytes + empty_size,
+                                          cont1_bytes, min_bytes);
 
        /* Clear our temporary list */
        list_for_each_entry_safe(entry, tmp, &bitmaps, list)
@@ -2567,6 +2568,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                list_add_tail(&cluster->block_group_list,
                              &block_group->cluster_list);
                cluster->block_group = block_group;
+       } else {
+               trace_btrfs_failed_cluster_setup(block_group);
        }
 out:
        spin_unlock(&cluster->lock);
@@ -2588,17 +2591,57 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster)
        cluster->block_group = NULL;
 }
 
-int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
-                          u64 *trimmed, u64 start, u64 end, u64 minlen)
+static int do_trimming(struct btrfs_block_group_cache *block_group,
+                      u64 *total_trimmed, u64 start, u64 bytes,
+                      u64 reserved_start, u64 reserved_bytes)
 {
-       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-       struct btrfs_free_space *entry = NULL;
+       struct btrfs_space_info *space_info = block_group->space_info;
        struct btrfs_fs_info *fs_info = block_group->fs_info;
-       u64 bytes = 0;
-       u64 actually_trimmed;
-       int ret = 0;
+       int ret;
+       int update = 0;
+       u64 trimmed = 0;
 
-       *trimmed = 0;
+       spin_lock(&space_info->lock);
+       spin_lock(&block_group->lock);
+       if (!block_group->ro) {
+               block_group->reserved += reserved_bytes;
+               space_info->bytes_reserved += reserved_bytes;
+               update = 1;
+       }
+       spin_unlock(&block_group->lock);
+       spin_unlock(&space_info->lock);
+
+       ret = btrfs_error_discard_extent(fs_info->extent_root,
+                                        start, bytes, &trimmed);
+       if (!ret)
+               *total_trimmed += trimmed;
+
+       btrfs_add_free_space(block_group, reserved_start, reserved_bytes);
+
+       if (update) {
+               spin_lock(&space_info->lock);
+               spin_lock(&block_group->lock);
+               if (block_group->ro)
+                       space_info->bytes_readonly += reserved_bytes;
+               block_group->reserved -= reserved_bytes;
+               space_info->bytes_reserved -= reserved_bytes;
+               spin_unlock(&space_info->lock);
+               spin_unlock(&block_group->lock);
+       }
+
+       return ret;
+}
+
+static int trim_no_bitmap(struct btrfs_block_group_cache *block_group,
+                         u64 *total_trimmed, u64 start, u64 end, u64 minlen)
+{
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
+       struct btrfs_free_space *entry;
+       struct rb_node *node;
+       int ret = 0;
+       u64 extent_start;
+       u64 extent_bytes;
+       u64 bytes;
 
        while (start < end) {
                spin_lock(&ctl->tree_lock);
@@ -2609,81 +2652,118 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
                }
 
                entry = tree_search_offset(ctl, start, 0, 1);
-               if (!entry)
-                       entry = tree_search_offset(ctl,
-                                                  offset_to_bitmap(ctl, start),
-                                                  1, 1);
-
-               if (!entry || entry->offset >= end) {
+               if (!entry) {
                        spin_unlock(&ctl->tree_lock);
                        break;
                }
 
-               if (entry->bitmap) {
-                       ret = search_bitmap(ctl, entry, &start, &bytes);
-                       if (!ret) {
-                               if (start >= end) {
-                                       spin_unlock(&ctl->tree_lock);
-                                       break;
-                               }
-                               bytes = min(bytes, end - start);
-                               bitmap_clear_bits(ctl, entry, start, bytes);
-                               if (entry->bytes == 0)
-                                       free_bitmap(ctl, entry);
-                       } else {
-                               start = entry->offset + BITS_PER_BITMAP *
-                                       block_group->sectorsize;
+               /* skip bitmaps */
+               while (entry->bitmap) {
+                       node = rb_next(&entry->offset_index);
+                       if (!node) {
                                spin_unlock(&ctl->tree_lock);
-                               ret = 0;
-                               continue;
+                               goto out;
                        }
-               } else {
-                       start = entry->offset;
-                       bytes = min(entry->bytes, end - start);
-                       unlink_free_space(ctl, entry);
-                       kmem_cache_free(btrfs_free_space_cachep, entry);
+                       entry = rb_entry(node, struct btrfs_free_space,
+                                        offset_index);
                }
 
+               if (entry->offset >= end) {
+                       spin_unlock(&ctl->tree_lock);
+                       break;
+               }
+
+               extent_start = entry->offset;
+               extent_bytes = entry->bytes;
+               start = max(start, extent_start);
+               bytes = min(extent_start + extent_bytes, end) - start;
+               if (bytes < minlen) {
+                       spin_unlock(&ctl->tree_lock);
+                       goto next;
+               }
+
+               unlink_free_space(ctl, entry);
+               kmem_cache_free(btrfs_free_space_cachep, entry);
+
                spin_unlock(&ctl->tree_lock);
 
-               if (bytes >= minlen) {
-                       struct btrfs_space_info *space_info;
-                       int update = 0;
-
-                       space_info = block_group->space_info;
-                       spin_lock(&space_info->lock);
-                       spin_lock(&block_group->lock);
-                       if (!block_group->ro) {
-                               block_group->reserved += bytes;
-                               space_info->bytes_reserved += bytes;
-                               update = 1;
-                       }
-                       spin_unlock(&block_group->lock);
-                       spin_unlock(&space_info->lock);
-
-                       ret = btrfs_error_discard_extent(fs_info->extent_root,
-                                                        start,
-                                                        bytes,
-                                                        &actually_trimmed);
-
-                       btrfs_add_free_space(block_group, start, bytes);
-                       if (update) {
-                               spin_lock(&space_info->lock);
-                               spin_lock(&block_group->lock);
-                               if (block_group->ro)
-                                       space_info->bytes_readonly += bytes;
-                               block_group->reserved -= bytes;
-                               space_info->bytes_reserved -= bytes;
-                               spin_unlock(&space_info->lock);
-                               spin_unlock(&block_group->lock);
-                       }
+               ret = do_trimming(block_group, total_trimmed, start, bytes,
+                                 extent_start, extent_bytes);
+               if (ret)
+                       break;
+next:
+               start += bytes;
 
-                       if (ret)
-                               break;
-                       *trimmed += actually_trimmed;
+               if (fatal_signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+
+               cond_resched();
+       }
+out:
+       return ret;
+}
+
+static int trim_bitmaps(struct btrfs_block_group_cache *block_group,
+                       u64 *total_trimmed, u64 start, u64 end, u64 minlen)
+{
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
+       struct btrfs_free_space *entry;
+       int ret = 0;
+       int ret2;
+       u64 bytes;
+       u64 offset = offset_to_bitmap(ctl, start);
+
+       while (offset < end) {
+               bool next_bitmap = false;
+
+               spin_lock(&ctl->tree_lock);
+
+               if (ctl->free_space < minlen) {
+                       spin_unlock(&ctl->tree_lock);
+                       break;
+               }
+
+               entry = tree_search_offset(ctl, offset, 1, 0);
+               if (!entry) {
+                       spin_unlock(&ctl->tree_lock);
+                       next_bitmap = true;
+                       goto next;
+               }
+
+               bytes = minlen;
+               ret2 = search_bitmap(ctl, entry, &start, &bytes);
+               if (ret2 || start >= end) {
+                       spin_unlock(&ctl->tree_lock);
+                       next_bitmap = true;
+                       goto next;
+               }
+
+               bytes = min(bytes, end - start);
+               if (bytes < minlen) {
+                       spin_unlock(&ctl->tree_lock);
+                       goto next;
+               }
+
+               bitmap_clear_bits(ctl, entry, start, bytes);
+               if (entry->bytes == 0)
+                       free_bitmap(ctl, entry);
+
+               spin_unlock(&ctl->tree_lock);
+
+               ret = do_trimming(block_group, total_trimmed, start, bytes,
+                                 start, bytes);
+               if (ret)
+                       break;
+next:
+               if (next_bitmap) {
+                       offset += BITS_PER_BITMAP * ctl->unit;
+               } else {
+                       start += bytes;
+                       if (start >= offset + BITS_PER_BITMAP * ctl->unit)
+                               offset += BITS_PER_BITMAP * ctl->unit;
                }
-               start += bytes;
-               bytes = 0;
 
                if (fatal_signal_pending(current)) {
                        ret = -ERESTARTSYS;
@@ -2696,6 +2776,22 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
        return ret;
 }
 
+int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
+                          u64 *trimmed, u64 start, u64 end, u64 minlen)
+{
+       int ret;
+
+       *trimmed = 0;
+
+       ret = trim_no_bitmap(block_group, trimmed, start, end, minlen);
+       if (ret)
+               return ret;
+
+       ret = trim_bitmaps(block_group, trimmed, start, end, minlen);
+
+       return ret;
+}
+
 /*
  * Find the left-most item in the cache tree, and then return the
  * smallest inode number in the item.
index f8962a957d656b385d0f99d65f300598e419db4d..213ffa86ce1b81f30a5f4ad50753c6d2ac6435aa 100644 (file)
@@ -438,6 +438,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
                                          trans->bytes_reserved);
        if (ret)
                goto out;
+       trace_btrfs_space_reservation(root->fs_info, "ino_cache", (u64)trans,
+                                     trans->bytes_reserved, 1);
 again:
        inode = lookup_free_ino_inode(root, path);
        if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
@@ -498,6 +500,8 @@ again:
 out_put:
        iput(inode);
 out_release:
+       trace_btrfs_space_reservation(root->fs_info, "ino_cache", (u64)trans,
+                                     trans->bytes_reserved, 0);
        btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
 out:
        trans->block_rsv = rsv;
index 81b235a61f8c4149dd880d1d7d1238ab690a4e09..32214fe0f7e32eda73449b0063aecd3874ade562 100644 (file)
@@ -1951,12 +1951,28 @@ enum btrfs_orphan_cleanup_state {
 void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root)
 {
+       struct btrfs_block_rsv *block_rsv;
        int ret;
 
        if (!list_empty(&root->orphan_list) ||
            root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE)
                return;
 
+       spin_lock(&root->orphan_lock);
+       if (!list_empty(&root->orphan_list)) {
+               spin_unlock(&root->orphan_lock);
+               return;
+       }
+
+       if (root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE) {
+               spin_unlock(&root->orphan_lock);
+               return;
+       }
+
+       block_rsv = root->orphan_block_rsv;
+       root->orphan_block_rsv = NULL;
+       spin_unlock(&root->orphan_lock);
+
        if (root->orphan_item_inserted &&
            btrfs_root_refs(&root->root_item) > 0) {
                ret = btrfs_del_orphan_item(trans, root->fs_info->tree_root,
@@ -1965,10 +1981,9 @@ void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
                root->orphan_item_inserted = 0;
        }
 
-       if (root->orphan_block_rsv) {
-               WARN_ON(root->orphan_block_rsv->size > 0);
-               btrfs_free_block_rsv(root, root->orphan_block_rsv);
-               root->orphan_block_rsv = NULL;
+       if (block_rsv) {
+               WARN_ON(block_rsv->size > 0);
+               btrfs_free_block_rsv(root, block_rsv);
        }
 }
 
@@ -2224,14 +2239,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                                continue;
                        }
                        nr_truncate++;
-                       /*
-                        * Need to hold the imutex for reservation purposes, not
-                        * a huge deal here but I have a WARN_ON in
-                        * btrfs_delalloc_reserve_space to catch offenders.
-                        */
-                       mutex_lock(&inode->i_mutex);
                        ret = btrfs_truncate(inode);
-                       mutex_unlock(&inode->i_mutex);
                } else {
                        nr_unlink++;
                }
@@ -2845,7 +2853,7 @@ static void __unlink_end_trans(struct btrfs_trans_handle *trans,
                BUG_ON(!root->fs_info->enospc_unlink);
                root->fs_info->enospc_unlink = 0;
        }
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
 }
 
 static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
@@ -3009,7 +3017,6 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        int pending_del_nr = 0;
        int pending_del_slot = 0;
        int extent_type = -1;
-       int encoding;
        int ret;
        int err = 0;
        u64 ino = btrfs_ino(inode);
@@ -3059,7 +3066,6 @@ search_again:
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                found_type = btrfs_key_type(&found_key);
-               encoding = 0;
 
                if (found_key.objectid != ino)
                        break;
@@ -3072,10 +3078,6 @@ search_again:
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
                        extent_type = btrfs_file_extent_type(leaf, fi);
-                       encoding = btrfs_file_extent_compression(leaf, fi);
-                       encoding |= btrfs_file_extent_encryption(leaf, fi);
-                       encoding |= btrfs_file_extent_other_encoding(leaf, fi);
-
                        if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
                                item_end +=
                                    btrfs_file_extent_num_bytes(leaf, fi);
@@ -3103,7 +3105,7 @@ search_again:
                if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
                        u64 num_dec;
                        extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
-                       if (!del_item && !encoding) {
+                       if (!del_item) {
                                u64 orig_num_bytes =
                                        btrfs_file_extent_num_bytes(leaf, fi);
                                extent_num_bytes = new_size -
@@ -3179,7 +3181,7 @@ delete:
                        ret = btrfs_free_extent(trans, root, extent_start,
                                                extent_num_bytes, 0,
                                                btrfs_header_owner(leaf),
-                                               ino, extent_offset);
+                                               ino, extent_offset, 0);
                        BUG_ON(ret);
                }
 
@@ -3434,7 +3436,7 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize)
                i_size_write(inode, newsize);
                btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL);
                ret = btrfs_update_inode(trans, root, inode);
-               btrfs_end_transaction_throttle(trans, root);
+               btrfs_end_transaction(trans, root);
        } else {
 
                /*
@@ -4655,7 +4657,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        }
 out_unlock:
        nr = trans->blocks_used;
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root, nr);
        if (drop_inode) {
                inode_dec_link_count(inode);
@@ -4723,7 +4725,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        }
 out_unlock:
        nr = trans->blocks_used;
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
        if (drop_inode) {
                inode_dec_link_count(inode);
                iput(inode);
@@ -4782,7 +4784,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
        }
 
        nr = trans->blocks_used;
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
 fail:
        if (drop_inode) {
                inode_dec_link_count(inode);
@@ -4848,7 +4850,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
 out_fail:
        nr = trans->blocks_used;
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
        if (drop_on_err)
                iput(inode);
        btrfs_btree_balance_dirty(root, nr);
@@ -5121,7 +5123,7 @@ again:
                        }
                        flush_dcache_page(page);
                } else if (create && PageUptodate(page)) {
-                       WARN_ON(1);
+                       BUG();
                        if (!trans) {
                                kunmap(page);
                                free_extent_map(em);
@@ -6399,21 +6401,23 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        unsigned long zero_start;
        loff_t size;
        int ret;
+       int reserved = 0;
        u64 page_start;
        u64 page_end;
 
-       /* Need this to keep space reservations serialized */
-       mutex_lock(&inode->i_mutex);
        ret  = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
-       mutex_unlock(&inode->i_mutex);
-       if (!ret)
+       if (!ret) {
                ret = btrfs_update_time(vma->vm_file);
+               reserved = 1;
+       }
        if (ret) {
                if (ret == -ENOMEM)
                        ret = VM_FAULT_OOM;
                else /* -ENOSPC, -EIO, etc */
                        ret = VM_FAULT_SIGBUS;
-               goto out;
+               if (reserved)
+                       goto out;
+               goto out_noreserve;
        }
 
        ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
@@ -6494,8 +6498,9 @@ out_unlock:
        if (!ret)
                return VM_FAULT_LOCKED;
        unlock_page(page);
-       btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
 out:
+       btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
+out_noreserve:
        return ret;
 }
 
@@ -6668,7 +6673,7 @@ end_trans:
                        err = ret;
 
                nr = trans->blocks_used;
-               ret = btrfs_end_transaction_throttle(trans, root);
+               ret = btrfs_end_transaction(trans, root);
                btrfs_btree_balance_dirty(root, nr);
        }
 
@@ -6749,6 +6754,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        extent_io_tree_init(&ei->io_tree, &inode->i_data);
        extent_io_tree_init(&ei->io_failure_tree, &inode->i_data);
        mutex_init(&ei->log_mutex);
+       mutex_init(&ei->delalloc_mutex);
        btrfs_ordered_inode_tree_init(&ei->ordered_tree);
        INIT_LIST_HEAD(&ei->i_orphan);
        INIT_LIST_HEAD(&ei->delalloc_inodes);
@@ -7074,7 +7080,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                btrfs_end_log_trans(root);
        }
 out_fail:
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
 out_notrans:
        if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
                up_read(&root->fs_info->subvol_sem);
@@ -7246,7 +7252,7 @@ out_unlock:
        if (!err)
                d_instantiate(dentry, inode);
        nr = trans->blocks_used;
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
        if (drop_inode) {
                inode_dec_link_count(inode);
                iput(inode);
index 5441ff1480fdbbd9ce9fe4c9caa6fc0c62392a3c..03bb62a9ee24d3e84cef380cda53af10ff673590 100644 (file)
@@ -176,6 +176,8 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        struct btrfs_trans_handle *trans;
        unsigned int flags, oldflags;
        int ret;
+       u64 ip_oldflags;
+       unsigned int i_oldflags;
 
        if (btrfs_root_readonly(root))
                return -EROFS;
@@ -192,6 +194,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 
        mutex_lock(&inode->i_mutex);
 
+       ip_oldflags = ip->flags;
+       i_oldflags = inode->i_flags;
+
        flags = btrfs_mask_flags(inode->i_mode, flags);
        oldflags = btrfs_flags_to_ioctl(ip->flags);
        if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
@@ -249,19 +254,24 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
                ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
        }
 
-       trans = btrfs_join_transaction(root);
-       BUG_ON(IS_ERR(trans));
+       trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto out_drop;
+       }
 
        btrfs_update_iflags(inode);
        inode->i_ctime = CURRENT_TIME;
        ret = btrfs_update_inode(trans, root, inode);
-       BUG_ON(ret);
 
        btrfs_end_transaction(trans, root);
+ out_drop:
+       if (ret) {
+               ip->flags = ip_oldflags;
+               inode->i_flags = i_oldflags;
+       }
 
        mnt_drop_write_file(file);
-
-       ret = 0;
  out_unlock:
        mutex_unlock(&inode->i_mutex);
        return ret;
@@ -276,14 +286,13 @@ static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
 
 static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
 {
-       struct btrfs_root *root = fdentry(file)->d_sb->s_fs_info;
-       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_fs_info *fs_info = btrfs_sb(fdentry(file)->d_sb);
        struct btrfs_device *device;
        struct request_queue *q;
        struct fstrim_range range;
        u64 minlen = ULLONG_MAX;
        u64 num_devices = 0;
-       u64 total_bytes = btrfs_super_total_bytes(root->fs_info->super_copy);
+       u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
        int ret;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -312,7 +321,7 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
 
        range.len = min(range.len, total_bytes - range.start);
        range.minlen = max(range.minlen, minlen);
-       ret = btrfs_trim_fs(root, &range);
+       ret = btrfs_trim_fs(fs_info->tree_root, &range);
        if (ret < 0)
                return ret;
 
@@ -358,7 +367,7 @@ static noinline int create_subvol(struct btrfs_root *root,
                return PTR_ERR(trans);
 
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
-                                     0, objectid, NULL, 0, 0, 0);
+                                     0, objectid, NULL, 0, 0, 0, 0);
        if (IS_ERR(leaf)) {
                ret = PTR_ERR(leaf);
                goto fail;
@@ -858,10 +867,8 @@ static int cluster_pages_for_defrag(struct inode *inode,
                return 0;
        file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
 
-       mutex_lock(&inode->i_mutex);
        ret = btrfs_delalloc_reserve_space(inode,
                                           num_pages << PAGE_CACHE_SHIFT);
-       mutex_unlock(&inode->i_mutex);
        if (ret)
                return ret;
 again:
@@ -1058,7 +1065,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
                i = range->start >> PAGE_CACHE_SHIFT;
        }
        if (!max_to_defrag)
-               max_to_defrag = last_index;
+               max_to_defrag = last_index + 1;
 
        /*
         * make writeback starts from i, so the defrag range can be
@@ -1203,13 +1210,21 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       mutex_lock(&root->fs_info->volume_mutex);
+       if (root->fs_info->balance_ctl) {
+               printk(KERN_INFO "btrfs: balance in progress\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
        vol_args = memdup_user(arg, sizeof(*vol_args));
-       if (IS_ERR(vol_args))
-               return PTR_ERR(vol_args);
+       if (IS_ERR(vol_args)) {
+               ret = PTR_ERR(vol_args);
+               goto out;
+       }
 
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
 
-       mutex_lock(&root->fs_info->volume_mutex);
        sizestr = vol_args->name;
        devstr = strchr(sizestr, ':');
        if (devstr) {
@@ -1226,7 +1241,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
                       (unsigned long long)devid);
                ret = -EINVAL;
-               goto out_unlock;
+               goto out_free;
        }
        if (!strcmp(sizestr, "max"))
                new_size = device->bdev->bd_inode->i_size;
@@ -1241,7 +1256,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                new_size = memparse(sizestr, NULL);
                if (new_size == 0) {
                        ret = -EINVAL;
-                       goto out_unlock;
+                       goto out_free;
                }
        }
 
@@ -1250,7 +1265,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
        if (mod < 0) {
                if (new_size > old_size) {
                        ret = -EINVAL;
-                       goto out_unlock;
+                       goto out_free;
                }
                new_size = old_size - new_size;
        } else if (mod > 0) {
@@ -1259,11 +1274,11 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
 
        if (new_size < 256 * 1024 * 1024) {
                ret = -EINVAL;
-               goto out_unlock;
+               goto out_free;
        }
        if (new_size > device->bdev->bd_inode->i_size) {
                ret = -EFBIG;
-               goto out_unlock;
+               goto out_free;
        }
 
        do_div(new_size, root->sectorsize);
@@ -1276,7 +1291,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                trans = btrfs_start_transaction(root, 0);
                if (IS_ERR(trans)) {
                        ret = PTR_ERR(trans);
-                       goto out_unlock;
+                       goto out_free;
                }
                ret = btrfs_grow_device(trans, device, new_size);
                btrfs_commit_transaction(trans, root);
@@ -1284,9 +1299,10 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                ret = btrfs_shrink_device(device, new_size);
        }
 
-out_unlock:
-       mutex_unlock(&root->fs_info->volume_mutex);
+out_free:
        kfree(vol_args);
+out:
+       mutex_unlock(&root->fs_info->volume_mutex);
        return ret;
 }
 
@@ -2052,14 +2068,25 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       mutex_lock(&root->fs_info->volume_mutex);
+       if (root->fs_info->balance_ctl) {
+               printk(KERN_INFO "btrfs: balance in progress\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
        vol_args = memdup_user(arg, sizeof(*vol_args));
-       if (IS_ERR(vol_args))
-               return PTR_ERR(vol_args);
+       if (IS_ERR(vol_args)) {
+               ret = PTR_ERR(vol_args);
+               goto out;
+       }
 
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
        ret = btrfs_init_new_device(root, vol_args->name);
 
        kfree(vol_args);
+out:
+       mutex_unlock(&root->fs_info->volume_mutex);
        return ret;
 }
 
@@ -2074,14 +2101,25 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
        if (root->fs_info->sb->s_flags & MS_RDONLY)
                return -EROFS;
 
+       mutex_lock(&root->fs_info->volume_mutex);
+       if (root->fs_info->balance_ctl) {
+               printk(KERN_INFO "btrfs: balance in progress\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
        vol_args = memdup_user(arg, sizeof(*vol_args));
-       if (IS_ERR(vol_args))
-               return PTR_ERR(vol_args);
+       if (IS_ERR(vol_args)) {
+               ret = PTR_ERR(vol_args);
+               goto out;
+       }
 
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
        ret = btrfs_rm_device(root, vol_args->name);
 
        kfree(vol_args);
+out:
+       mutex_unlock(&root->fs_info->volume_mutex);
        return ret;
 }
 
@@ -2427,7 +2465,8 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                                        disko, diskl, 0,
                                                        root->root_key.objectid,
                                                        btrfs_ino(inode),
-                                                       new_key.offset - datao);
+                                                       new_key.offset - datao,
+                                                       0);
                                        BUG_ON(ret);
                                }
                        } else if (type == BTRFS_FILE_EXTENT_INLINE) {
@@ -2977,7 +3016,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
 {
        int ret = 0;
        int size;
-       u64 extent_offset;
+       u64 extent_item_pos;
        struct btrfs_ioctl_logical_ino_args *loi;
        struct btrfs_data_container *inodes = NULL;
        struct btrfs_path *path = NULL;
@@ -3008,15 +3047,17 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
        }
 
        ret = extent_from_logical(root->fs_info, loi->logical, path, &key);
+       btrfs_release_path(path);
 
        if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
                ret = -ENOENT;
        if (ret < 0)
                goto out;
 
-       extent_offset = loi->logical - key.objectid;
+       extent_item_pos = loi->logical - key.objectid;
        ret = iterate_extent_inodes(root->fs_info, path, key.objectid,
-                                       extent_offset, build_ino_list, inodes);
+                                       extent_item_pos, build_ino_list,
+                                       inodes);
 
        if (ret < 0)
                goto out;
@@ -3034,6 +3075,163 @@ out:
        return ret;
 }
 
+void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
+                              struct btrfs_ioctl_balance_args *bargs)
+{
+       struct btrfs_balance_control *bctl = fs_info->balance_ctl;
+
+       bargs->flags = bctl->flags;
+
+       if (atomic_read(&fs_info->balance_running))
+               bargs->state |= BTRFS_BALANCE_STATE_RUNNING;
+       if (atomic_read(&fs_info->balance_pause_req))
+               bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ;
+       if (atomic_read(&fs_info->balance_cancel_req))
+               bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ;
+
+       memcpy(&bargs->data, &bctl->data, sizeof(bargs->data));
+       memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta));
+       memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys));
+
+       if (lock) {
+               spin_lock(&fs_info->balance_lock);
+               memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
+               spin_unlock(&fs_info->balance_lock);
+       } else {
+               memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
+       }
+}
+
+static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_ioctl_balance_args *bargs;
+       struct btrfs_balance_control *bctl;
+       int ret;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (fs_info->sb->s_flags & MS_RDONLY)
+               return -EROFS;
+
+       mutex_lock(&fs_info->volume_mutex);
+       mutex_lock(&fs_info->balance_mutex);
+
+       if (arg) {
+               bargs = memdup_user(arg, sizeof(*bargs));
+               if (IS_ERR(bargs)) {
+                       ret = PTR_ERR(bargs);
+                       goto out;
+               }
+
+               if (bargs->flags & BTRFS_BALANCE_RESUME) {
+                       if (!fs_info->balance_ctl) {
+                               ret = -ENOTCONN;
+                               goto out_bargs;
+                       }
+
+                       bctl = fs_info->balance_ctl;
+                       spin_lock(&fs_info->balance_lock);
+                       bctl->flags |= BTRFS_BALANCE_RESUME;
+                       spin_unlock(&fs_info->balance_lock);
+
+                       goto do_balance;
+               }
+       } else {
+               bargs = NULL;
+       }
+
+       if (fs_info->balance_ctl) {
+               ret = -EINPROGRESS;
+               goto out_bargs;
+       }
+
+       bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
+       if (!bctl) {
+               ret = -ENOMEM;
+               goto out_bargs;
+       }
+
+       bctl->fs_info = fs_info;
+       if (arg) {
+               memcpy(&bctl->data, &bargs->data, sizeof(bctl->data));
+               memcpy(&bctl->meta, &bargs->meta, sizeof(bctl->meta));
+               memcpy(&bctl->sys, &bargs->sys, sizeof(bctl->sys));
+
+               bctl->flags = bargs->flags;
+       } else {
+               /* balance everything - no filters */
+               bctl->flags |= BTRFS_BALANCE_TYPE_MASK;
+       }
+
+do_balance:
+       ret = btrfs_balance(bctl, bargs);
+       /*
+        * bctl is freed in __cancel_balance or in free_fs_info if
+        * restriper was paused all the way until unmount
+        */
+       if (arg) {
+               if (copy_to_user(arg, bargs, sizeof(*bargs)))
+                       ret = -EFAULT;
+       }
+
+out_bargs:
+       kfree(bargs);
+out:
+       mutex_unlock(&fs_info->balance_mutex);
+       mutex_unlock(&fs_info->volume_mutex);
+       return ret;
+}
+
+static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd)
+{
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       switch (cmd) {
+       case BTRFS_BALANCE_CTL_PAUSE:
+               return btrfs_pause_balance(root->fs_info);
+       case BTRFS_BALANCE_CTL_CANCEL:
+               return btrfs_cancel_balance(root->fs_info);
+       }
+
+       return -EINVAL;
+}
+
+static long btrfs_ioctl_balance_progress(struct btrfs_root *root,
+                                        void __user *arg)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_ioctl_balance_args *bargs;
+       int ret = 0;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       mutex_lock(&fs_info->balance_mutex);
+       if (!fs_info->balance_ctl) {
+               ret = -ENOTCONN;
+               goto out;
+       }
+
+       bargs = kzalloc(sizeof(*bargs), GFP_NOFS);
+       if (!bargs) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       update_ioctl_balance_args(fs_info, 1, bargs);
+
+       if (copy_to_user(arg, bargs, sizeof(*bargs)))
+               ret = -EFAULT;
+
+       kfree(bargs);
+out:
+       mutex_unlock(&fs_info->balance_mutex);
+       return ret;
+}
+
 long btrfs_ioctl(struct file *file, unsigned int
                cmd, unsigned long arg)
 {
@@ -3078,7 +3276,7 @@ long btrfs_ioctl(struct file *file, unsigned int
        case BTRFS_IOC_DEV_INFO:
                return btrfs_ioctl_dev_info(root, argp);
        case BTRFS_IOC_BALANCE:
-               return btrfs_balance(root->fs_info->dev_root);
+               return btrfs_ioctl_balance(root, NULL);
        case BTRFS_IOC_CLONE:
                return btrfs_ioctl_clone(file, arg, 0, 0, 0);
        case BTRFS_IOC_CLONE_RANGE:
@@ -3110,6 +3308,12 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_scrub_cancel(root, argp);
        case BTRFS_IOC_SCRUB_PROGRESS:
                return btrfs_ioctl_scrub_progress(root, argp);
+       case BTRFS_IOC_BALANCE_V2:
+               return btrfs_ioctl_balance(root, argp);
+       case BTRFS_IOC_BALANCE_CTL:
+               return btrfs_ioctl_balance_ctl(root, arg);
+       case BTRFS_IOC_BALANCE_PROGRESS:
+               return btrfs_ioctl_balance_progress(root, argp);
        }
 
        return -ENOTTY;
index 252ae9915de8fcfa4b6b7a3a502735c28d1819f6..4f69028a68c486268bf5bcfc097a5412dbdd2ad0 100644 (file)
@@ -109,6 +109,55 @@ struct btrfs_ioctl_fs_info_args {
        __u64 reserved[124];                    /* pad to 1k */
 };
 
+/* balance control ioctl modes */
+#define BTRFS_BALANCE_CTL_PAUSE                1
+#define BTRFS_BALANCE_CTL_CANCEL       2
+
+/*
+ * this is packed, because it should be exactly the same as its disk
+ * byte order counterpart (struct btrfs_disk_balance_args)
+ */
+struct btrfs_balance_args {
+       __u64 profiles;
+       __u64 usage;
+       __u64 devid;
+       __u64 pstart;
+       __u64 pend;
+       __u64 vstart;
+       __u64 vend;
+
+       __u64 target;
+
+       __u64 flags;
+
+       __u64 unused[8];
+} __attribute__ ((__packed__));
+
+/* report balance progress to userspace */
+struct btrfs_balance_progress {
+       __u64 expected;         /* estimated # of chunks that will be
+                                * relocated to fulfill the request */
+       __u64 considered;       /* # of chunks we have considered so far */
+       __u64 completed;        /* # of chunks relocated so far */
+};
+
+#define BTRFS_BALANCE_STATE_RUNNING    (1ULL << 0)
+#define BTRFS_BALANCE_STATE_PAUSE_REQ  (1ULL << 1)
+#define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2)
+
+struct btrfs_ioctl_balance_args {
+       __u64 flags;                            /* in/out */
+       __u64 state;                            /* out */
+
+       struct btrfs_balance_args data;         /* in/out */
+       struct btrfs_balance_args meta;         /* in/out */
+       struct btrfs_balance_args sys;          /* in/out */
+
+       struct btrfs_balance_progress stat;     /* out */
+
+       __u64 unused[72];                       /* pad to 1k */
+};
+
 #define BTRFS_INO_LOOKUP_PATH_MAX 4080
 struct btrfs_ioctl_ino_lookup_args {
        __u64 treeid;
@@ -272,6 +321,11 @@ struct btrfs_ioctl_logical_ino_args {
                                 struct btrfs_ioctl_dev_info_args)
 #define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
                               struct btrfs_ioctl_fs_info_args)
+#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \
+                                  struct btrfs_ioctl_balance_args)
+#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
+#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
+                                       struct btrfs_ioctl_balance_args)
 #define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
                                        struct btrfs_ioctl_ino_path_args)
 #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
index d77b67c4b275731417c11e04ad38b3dc9c4d456b..5e178d8f7167f496e928613b6c1f0000c2ea242e 100644 (file)
@@ -33,6 +33,14 @@ void btrfs_assert_tree_read_locked(struct extent_buffer *eb);
  */
 void btrfs_set_lock_blocking_rw(struct extent_buffer *eb, int rw)
 {
+       if (eb->lock_nested) {
+               read_lock(&eb->lock);
+               if (eb->lock_nested && current->pid == eb->lock_owner) {
+                       read_unlock(&eb->lock);
+                       return;
+               }
+               read_unlock(&eb->lock);
+       }
        if (rw == BTRFS_WRITE_LOCK) {
                if (atomic_read(&eb->blocking_writers) == 0) {
                        WARN_ON(atomic_read(&eb->spinning_writers) != 1);
@@ -57,6 +65,14 @@ void btrfs_set_lock_blocking_rw(struct extent_buffer *eb, int rw)
  */
 void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw)
 {
+       if (eb->lock_nested) {
+               read_lock(&eb->lock);
+               if (&eb->lock_nested && current->pid == eb->lock_owner) {
+                       read_unlock(&eb->lock);
+                       return;
+               }
+               read_unlock(&eb->lock);
+       }
        if (rw == BTRFS_WRITE_LOCK_BLOCKING) {
                BUG_ON(atomic_read(&eb->blocking_writers) != 1);
                write_lock(&eb->lock);
@@ -81,12 +97,25 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw)
 void btrfs_tree_read_lock(struct extent_buffer *eb)
 {
 again:
+       read_lock(&eb->lock);
+       if (atomic_read(&eb->blocking_writers) &&
+           current->pid == eb->lock_owner) {
+               /*
+                * This extent is already write-locked by our thread. We allow
+                * an additional read lock to be added because it's for the same
+                * thread. btrfs_find_all_roots() depends on this as it may be
+                * called on a partly (write-)locked tree.
+                */
+               BUG_ON(eb->lock_nested);
+               eb->lock_nested = 1;
+               read_unlock(&eb->lock);
+               return;
+       }
+       read_unlock(&eb->lock);
        wait_event(eb->write_lock_wq, atomic_read(&eb->blocking_writers) == 0);
        read_lock(&eb->lock);
        if (atomic_read(&eb->blocking_writers)) {
                read_unlock(&eb->lock);
-               wait_event(eb->write_lock_wq,
-                          atomic_read(&eb->blocking_writers) == 0);
                goto again;
        }
        atomic_inc(&eb->read_locks);
@@ -129,6 +158,7 @@ int btrfs_try_tree_write_lock(struct extent_buffer *eb)
        }
        atomic_inc(&eb->write_locks);
        atomic_inc(&eb->spinning_writers);
+       eb->lock_owner = current->pid;
        return 1;
 }
 
@@ -137,6 +167,15 @@ int btrfs_try_tree_write_lock(struct extent_buffer *eb)
  */
 void btrfs_tree_read_unlock(struct extent_buffer *eb)
 {
+       if (eb->lock_nested) {
+               read_lock(&eb->lock);
+               if (eb->lock_nested && current->pid == eb->lock_owner) {
+                       eb->lock_nested = 0;
+                       read_unlock(&eb->lock);
+                       return;
+               }
+               read_unlock(&eb->lock);
+       }
        btrfs_assert_tree_read_locked(eb);
        WARN_ON(atomic_read(&eb->spinning_readers) == 0);
        atomic_dec(&eb->spinning_readers);
@@ -149,6 +188,15 @@ void btrfs_tree_read_unlock(struct extent_buffer *eb)
  */
 void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb)
 {
+       if (eb->lock_nested) {
+               read_lock(&eb->lock);
+               if (eb->lock_nested && current->pid == eb->lock_owner) {
+                       eb->lock_nested = 0;
+                       read_unlock(&eb->lock);
+                       return;
+               }
+               read_unlock(&eb->lock);
+       }
        btrfs_assert_tree_read_locked(eb);
        WARN_ON(atomic_read(&eb->blocking_readers) == 0);
        if (atomic_dec_and_test(&eb->blocking_readers))
@@ -181,6 +229,7 @@ again:
        WARN_ON(atomic_read(&eb->spinning_writers));
        atomic_inc(&eb->spinning_writers);
        atomic_inc(&eb->write_locks);
+       eb->lock_owner = current->pid;
        return 0;
 }
 
index cfb55434a46981fa64416e68fa3fd29cf58238f5..8c1aae2c845d49960fe352c809033f1bdf5ffb74 100644 (file)
@@ -1604,12 +1604,12 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
                ret = btrfs_inc_extent_ref(trans, root, new_bytenr,
                                           num_bytes, parent,
                                           btrfs_header_owner(leaf),
-                                          key.objectid, key.offset);
+                                          key.objectid, key.offset, 1);
                BUG_ON(ret);
 
                ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
                                        parent, btrfs_header_owner(leaf),
-                                       key.objectid, key.offset);
+                                       key.objectid, key.offset, 1);
                BUG_ON(ret);
        }
        if (dirty)
@@ -1778,21 +1778,23 @@ again:
 
                ret = btrfs_inc_extent_ref(trans, src, old_bytenr, blocksize,
                                        path->nodes[level]->start,
-                                       src->root_key.objectid, level - 1, 0);
+                                       src->root_key.objectid, level - 1, 0,
+                                       1);
                BUG_ON(ret);
                ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
                                        0, dest->root_key.objectid, level - 1,
-                                       0);
+                                       0, 1);
                BUG_ON(ret);
 
                ret = btrfs_free_extent(trans, src, new_bytenr, blocksize,
                                        path->nodes[level]->start,
-                                       src->root_key.objectid, level - 1, 0);
+                                       src->root_key.objectid, level - 1, 0,
+                                       1);
                BUG_ON(ret);
 
                ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize,
                                        0, dest->root_key.objectid, level - 1,
-                                       0);
+                                       0, 1);
                BUG_ON(ret);
 
                btrfs_unlock_up_safe(path, 0);
@@ -2244,7 +2246,7 @@ again:
                } else {
                        list_del_init(&reloc_root->root_list);
                }
-               btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0);
+               btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1);
        }
 
        if (found) {
@@ -2558,7 +2560,7 @@ static int do_relocation(struct btrfs_trans_handle *trans,
                                                node->eb->start, blocksize,
                                                upper->eb->start,
                                                btrfs_header_owner(upper->eb),
-                                               node->level, 0);
+                                               node->level, 0, 1);
                        BUG_ON(ret);
 
                        ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
@@ -2947,9 +2949,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
        index = (cluster->start - offset) >> PAGE_CACHE_SHIFT;
        last_index = (cluster->end - offset) >> PAGE_CACHE_SHIFT;
        while (index <= last_index) {
-               mutex_lock(&inode->i_mutex);
                ret = btrfs_delalloc_reserve_metadata(inode, PAGE_CACHE_SIZE);
-               mutex_unlock(&inode->i_mutex);
                if (ret)
                        goto out;
 
index ddf2c90d3fc0c475cbfabf6397c84f734abcc5e8..9770cc5bfb76c6829f96924bb82f9b3b564ca646 100644 (file)
@@ -25,6 +25,7 @@
 #include "transaction.h"
 #include "backref.h"
 #include "extent_io.h"
+#include "check-integrity.h"
 
 /*
  * This is only the first step towards a full-features scrub. It reads all
@@ -309,7 +310,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio,
        u8 ref_level;
        unsigned long ptr = 0;
        const int bufsize = 4096;
-       u64 extent_offset;
+       u64 extent_item_pos;
 
        path = btrfs_alloc_path();
 
@@ -329,12 +330,13 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio,
        if (ret < 0)
                goto out;
 
-       extent_offset = swarn.logical - found_key.objectid;
+       extent_item_pos = swarn.logical - found_key.objectid;
        swarn.extent_item_size = found_key.offset;
 
        eb = path->nodes[0];
        ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
        item_size = btrfs_item_size_nr(eb, path->slots[0]);
+       btrfs_release_path(path);
 
        if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
                do {
@@ -351,7 +353,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio,
        } else {
                swarn.path = path;
                iterate_extent_inodes(fs_info, path, found_key.objectid,
-                                       extent_offset,
+                                       extent_item_pos,
                                        scrub_print_warning_inode, &swarn);
        }
 
@@ -732,7 +734,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,
        bio_add_page(bio, page, PAGE_SIZE, 0);
        bio->bi_end_io = scrub_fixup_end_io;
        bio->bi_private = &complete;
-       submit_bio(rw, bio);
+       btrfsic_submit_bio(rw, bio);
 
        /* this will also unplug the queue */
        wait_for_completion(&complete);
@@ -958,7 +960,7 @@ static int scrub_submit(struct scrub_dev *sdev)
        sdev->curr = -1;
        atomic_inc(&sdev->in_flight);
 
-       submit_bio(READ, sbio->bio);
+       btrfsic_submit_bio(READ, sbio->bio);
 
        return 0;
 }
index ae488aa1966a1b32d6a3c4438424eb690740d4c9..3ce97b217cbeae21ef23e57fe2a605ed11572af1 100644 (file)
@@ -147,13 +147,13 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
 
 static void btrfs_put_super(struct super_block *sb)
 {
-       struct btrfs_root *root = btrfs_sb(sb);
-       int ret;
-
-       ret = close_ctree(root);
-       sb->s_fs_info = NULL;
-
-       (void)ret; /* FIXME: need to fix VFS to return error? */
+       (void)close_ctree(btrfs_sb(sb)->tree_root);
+       /* FIXME: need to fix VFS to return error? */
+       /* AV: return it _where_?  ->put_super() can be triggered by any number
+        * of async events, up to and including delivery of SIGKILL to the
+        * last process that kept it busy.  Or segfault in the aforementioned
+        * process...  Whom would you report that to?
+        */
 }
 
 enum {
@@ -163,8 +163,11 @@ enum {
        Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
        Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
        Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
-       Opt_enospc_debug, Opt_subvolrootid, Opt_defrag,
-       Opt_inode_cache, Opt_no_space_cache, Opt_recovery, Opt_err,
+       Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache,
+       Opt_no_space_cache, Opt_recovery, Opt_skip_balance,
+       Opt_check_integrity, Opt_check_integrity_including_extent_data,
+       Opt_check_integrity_print_mask,
+       Opt_err,
 };
 
 static match_table_t tokens = {
@@ -199,6 +202,10 @@ static match_table_t tokens = {
        {Opt_inode_cache, "inode_cache"},
        {Opt_no_space_cache, "nospace_cache"},
        {Opt_recovery, "recovery"},
+       {Opt_skip_balance, "skip_balance"},
+       {Opt_check_integrity, "check_int"},
+       {Opt_check_integrity_including_extent_data, "check_int_data"},
+       {Opt_check_integrity_print_mask, "check_int_print_mask=%d"},
        {Opt_err, NULL},
 };
 
@@ -397,6 +404,40 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        printk(KERN_INFO "btrfs: enabling auto recovery");
                        btrfs_set_opt(info->mount_opt, RECOVERY);
                        break;
+               case Opt_skip_balance:
+                       btrfs_set_opt(info->mount_opt, SKIP_BALANCE);
+                       break;
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+               case Opt_check_integrity_including_extent_data:
+                       printk(KERN_INFO "btrfs: enabling check integrity"
+                              " including extent data\n");
+                       btrfs_set_opt(info->mount_opt,
+                                     CHECK_INTEGRITY_INCLUDING_EXTENT_DATA);
+                       btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
+                       break;
+               case Opt_check_integrity:
+                       printk(KERN_INFO "btrfs: enabling check integrity\n");
+                       btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
+                       break;
+               case Opt_check_integrity_print_mask:
+                       intarg = 0;
+                       match_int(&args[0], &intarg);
+                       if (intarg) {
+                               info->check_integrity_print_mask = intarg;
+                               printk(KERN_INFO "btrfs:"
+                                      " check_integrity_print_mask 0x%x\n",
+                                      info->check_integrity_print_mask);
+                       }
+                       break;
+#else
+               case Opt_check_integrity_including_extent_data:
+               case Opt_check_integrity:
+               case Opt_check_integrity_print_mask:
+                       printk(KERN_ERR "btrfs: support for check_integrity*"
+                              " not compiled in!\n");
+                       ret = -EINVAL;
+                       goto out;
+#endif
                case Opt_err:
                        printk(KERN_INFO "btrfs: unrecognized mount option "
                               "'%s'\n", p);
@@ -500,7 +541,8 @@ out:
 static struct dentry *get_default_root(struct super_block *sb,
                                       u64 subvol_objectid)
 {
-       struct btrfs_root *root = sb->s_fs_info;
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       struct btrfs_root *root = fs_info->tree_root;
        struct btrfs_root *new_root;
        struct btrfs_dir_item *di;
        struct btrfs_path *path;
@@ -530,7 +572,7 @@ static struct dentry *get_default_root(struct super_block *sb,
         * will mount by default if we haven't been given a specific subvolume
         * to mount.
         */
-       dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
+       dir_id = btrfs_super_root_dir(fs_info->super_copy);
        di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0);
        if (IS_ERR(di)) {
                btrfs_free_path(path);
@@ -544,7 +586,7 @@ static struct dentry *get_default_root(struct super_block *sb,
                 */
                btrfs_free_path(path);
                dir_id = BTRFS_FIRST_FREE_OBJECTID;
-               new_root = root->fs_info->fs_root;
+               new_root = fs_info->fs_root;
                goto setup_root;
        }
 
@@ -552,7 +594,7 @@ static struct dentry *get_default_root(struct super_block *sb,
        btrfs_free_path(path);
 
 find_root:
-       new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
+       new_root = btrfs_read_fs_root_no_name(fs_info, &location);
        if (IS_ERR(new_root))
                return ERR_CAST(new_root);
 
@@ -588,7 +630,7 @@ static int btrfs_fill_super(struct super_block *sb,
 {
        struct inode *inode;
        struct dentry *root_dentry;
-       struct btrfs_root *tree_root;
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
        struct btrfs_key key;
        int err;
 
@@ -603,18 +645,16 @@ static int btrfs_fill_super(struct super_block *sb,
        sb->s_flags |= MS_POSIXACL;
 #endif
 
-       tree_root = open_ctree(sb, fs_devices, (char *)data);
-
-       if (IS_ERR(tree_root)) {
+       err = open_ctree(sb, fs_devices, (char *)data);
+       if (err) {
                printk("btrfs: open_ctree failed\n");
-               return PTR_ERR(tree_root);
+               return err;
        }
-       sb->s_fs_info = tree_root;
 
        key.objectid = BTRFS_FIRST_FREE_OBJECTID;
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
-       inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root, NULL);
+       inode = btrfs_iget(sb, &key, fs_info->fs_root, NULL);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto fail_close;
@@ -631,23 +671,25 @@ static int btrfs_fill_super(struct super_block *sb,
 
        save_mount_options(sb, data);
        cleancache_init_fs(sb);
+       sb->s_flags |= MS_ACTIVE;
        return 0;
 
 fail_close:
-       close_ctree(tree_root);
+       close_ctree(fs_info->tree_root);
        return err;
 }
 
 int btrfs_sync_fs(struct super_block *sb, int wait)
 {
        struct btrfs_trans_handle *trans;
-       struct btrfs_root *root = btrfs_sb(sb);
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       struct btrfs_root *root = fs_info->tree_root;
        int ret;
 
        trace_btrfs_sync_fs(wait);
 
        if (!wait) {
-               filemap_flush(root->fs_info->btree_inode->i_mapping);
+               filemap_flush(fs_info->btree_inode->i_mapping);
                return 0;
        }
 
@@ -663,8 +705,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
 
 static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
 {
-       struct btrfs_root *root = btrfs_sb(dentry->d_sb);
-       struct btrfs_fs_info *info = root->fs_info;
+       struct btrfs_fs_info *info = btrfs_sb(dentry->d_sb);
+       struct btrfs_root *root = info->tree_root;
        char *compress_type;
 
        if (btrfs_test_opt(root, DEGRADED))
@@ -722,28 +764,25 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                seq_puts(seq, ",autodefrag");
        if (btrfs_test_opt(root, INODE_MAP_CACHE))
                seq_puts(seq, ",inode_cache");
+       if (btrfs_test_opt(root, SKIP_BALANCE))
+               seq_puts(seq, ",skip_balance");
        return 0;
 }
 
 static int btrfs_test_super(struct super_block *s, void *data)
 {
-       struct btrfs_root *test_root = data;
-       struct btrfs_root *root = btrfs_sb(s);
+       struct btrfs_fs_info *p = data;
+       struct btrfs_fs_info *fs_info = btrfs_sb(s);
 
-       /*
-        * If this super block is going away, return false as it
-        * can't match as an existing super block.
-        */
-       if (!atomic_read(&s->s_active))
-               return 0;
-       return root->fs_info->fs_devices == test_root->fs_info->fs_devices;
+       return fs_info->fs_devices == p->fs_devices;
 }
 
 static int btrfs_set_super(struct super_block *s, void *data)
 {
-       s->s_fs_info = data;
-
-       return set_anon_super(s, data);
+       int err = set_anon_super(s, data);
+       if (!err)
+               s->s_fs_info = data;
+       return err;
 }
 
 /*
@@ -903,12 +942,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        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_fs_info;
-       }
-       fs_info->tree_root->fs_info = fs_info;
        fs_info->fs_devices = fs_devices;
 
        fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
@@ -928,43 +961,30 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        }
 
        bdev = fs_devices->latest_bdev;
-       s = sget(fs_type, btrfs_test_super, btrfs_set_super,
-                fs_info->tree_root);
+       s = sget(fs_type, btrfs_test_super, btrfs_set_super, fs_info);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto error_close_devices;
        }
 
        if (s->s_root) {
-               if ((flags ^ s->s_flags) & MS_RDONLY) {
-                       deactivate_locked_super(s);
-                       error = -EBUSY;
-                       goto error_close_devices;
-               }
-
                btrfs_close_devices(fs_devices);
                free_fs_info(fs_info);
+               if ((flags ^ s->s_flags) & MS_RDONLY)
+                       error = -EBUSY;
        } else {
                char b[BDEVNAME_SIZE];
 
                s->s_flags = flags | MS_NOSEC;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
-               btrfs_sb(s)->fs_info->bdev_holder = fs_type;
+               btrfs_sb(s)->bdev_holder = fs_type;
                error = btrfs_fill_super(s, fs_devices, data,
                                         flags & MS_SILENT ? 1 : 0);
-               if (error) {
-                       deactivate_locked_super(s);
-                       return ERR_PTR(error);
-               }
-
-               s->s_flags |= MS_ACTIVE;
        }
 
-       root = get_default_root(s, subvol_objectid);
-       if (IS_ERR(root)) {
+       root = !error ? get_default_root(s, subvol_objectid) : ERR_PTR(error);
+       if (IS_ERR(root))
                deactivate_locked_super(s);
-               return root;
-       }
 
        return root;
 
@@ -977,7 +997,8 @@ error_fs_info:
 
 static int btrfs_remount(struct super_block *sb, int *flags, char *data)
 {
-       struct btrfs_root *root = btrfs_sb(sb);
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       struct btrfs_root *root = fs_info->tree_root;
        int ret;
 
        ret = btrfs_parse_options(root, data);
@@ -993,13 +1014,13 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                ret =  btrfs_commit_super(root);
                WARN_ON(ret);
        } else {
-               if (root->fs_info->fs_devices->rw_devices == 0)
+               if (fs_info->fs_devices->rw_devices == 0)
                        return -EACCES;
 
-               if (btrfs_super_log_root(root->fs_info->super_copy) != 0)
+               if (btrfs_super_log_root(fs_info->super_copy) != 0)
                        return -EINVAL;
 
-               ret = btrfs_cleanup_fs_roots(root->fs_info);
+               ret = btrfs_cleanup_fs_roots(fs_info);
                WARN_ON(ret);
 
                /* recover relocation */
@@ -1168,18 +1189,18 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
 
 static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct btrfs_root *root = btrfs_sb(dentry->d_sb);
-       struct btrfs_super_block *disk_super = root->fs_info->super_copy;
-       struct list_head *head = &root->fs_info->space_info;
+       struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb);
+       struct btrfs_super_block *disk_super = fs_info->super_copy;
+       struct list_head *head = &fs_info->space_info;
        struct btrfs_space_info *found;
        u64 total_used = 0;
        u64 total_free_data = 0;
        int bits = dentry->d_sb->s_blocksize_bits;
-       __be32 *fsid = (__be32 *)root->fs_info->fsid;
+       __be32 *fsid = (__be32 *)fs_info->fsid;
        int ret;
 
        /* holding chunk_muext to avoid allocating new chunks */
-       mutex_lock(&root->fs_info->chunk_mutex);
+       mutex_lock(&fs_info->chunk_mutex);
        rcu_read_lock();
        list_for_each_entry_rcu(found, head, list) {
                if (found->flags & BTRFS_BLOCK_GROUP_DATA) {
@@ -1198,14 +1219,14 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_bsize = dentry->d_sb->s_blocksize;
        buf->f_type = BTRFS_SUPER_MAGIC;
        buf->f_bavail = total_free_data;
-       ret = btrfs_calc_avail_data_space(root, &total_free_data);
+       ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data);
        if (ret) {
-               mutex_unlock(&root->fs_info->chunk_mutex);
+               mutex_unlock(&fs_info->chunk_mutex);
                return ret;
        }
        buf->f_bavail += total_free_data;
        buf->f_bavail = buf->f_bavail >> bits;
-       mutex_unlock(&root->fs_info->chunk_mutex);
+       mutex_unlock(&fs_info->chunk_mutex);
 
        /* We treat it as constant endianness (it doesn't matter _which_)
           because we want the fsid to come out the same whether mounted
@@ -1219,11 +1240,18 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
+static void btrfs_kill_super(struct super_block *sb)
+{
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       kill_anon_super(sb);
+       free_fs_info(fs_info);
+}
+
 static struct file_system_type btrfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "btrfs",
        .mount          = btrfs_mount,
-       .kill_sb        = kill_anon_super,
+       .kill_sb        = btrfs_kill_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
@@ -1257,17 +1285,17 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
 
 static int btrfs_freeze(struct super_block *sb)
 {
-       struct btrfs_root *root = btrfs_sb(sb);
-       mutex_lock(&root->fs_info->transaction_kthread_mutex);
-       mutex_lock(&root->fs_info->cleaner_mutex);
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       mutex_lock(&fs_info->transaction_kthread_mutex);
+       mutex_lock(&fs_info->cleaner_mutex);
        return 0;
 }
 
 static int btrfs_unfreeze(struct super_block *sb)
 {
-       struct btrfs_root *root = btrfs_sb(sb);
-       mutex_unlock(&root->fs_info->cleaner_mutex);
-       mutex_unlock(&root->fs_info->transaction_kthread_mutex);
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       mutex_unlock(&fs_info->cleaner_mutex);
+       mutex_unlock(&fs_info->transaction_kthread_mutex);
        return 0;
 }
 
index 81376d94cd3c6a4639ebef35df501dbefbfb2435..287a6728b1ad6ddc726b64122223bfc71e7e165d 100644 (file)
@@ -36,6 +36,8 @@ static noinline void put_transaction(struct btrfs_transaction *transaction)
        WARN_ON(atomic_read(&transaction->use_count) == 0);
        if (atomic_dec_and_test(&transaction->use_count)) {
                BUG_ON(!list_empty(&transaction->list));
+               WARN_ON(transaction->delayed_refs.root.rb_node);
+               WARN_ON(!list_empty(&transaction->delayed_refs.seq_head));
                memset(transaction, 0, sizeof(*transaction));
                kmem_cache_free(btrfs_transaction_cachep, transaction);
        }
@@ -108,8 +110,11 @@ loop:
        cur_trans->delayed_refs.num_heads = 0;
        cur_trans->delayed_refs.flushing = 0;
        cur_trans->delayed_refs.run_delayed_start = 0;
+       cur_trans->delayed_refs.seq = 1;
+       init_waitqueue_head(&cur_trans->delayed_refs.seq_wait);
        spin_lock_init(&cur_trans->commit_lock);
        spin_lock_init(&cur_trans->delayed_refs.lock);
+       INIT_LIST_HEAD(&cur_trans->delayed_refs.seq_head);
 
        INIT_LIST_HEAD(&cur_trans->pending_snapshots);
        list_add_tail(&cur_trans->list, &root->fs_info->trans_list);
@@ -321,6 +326,8 @@ again:
        }
 
        if (num_bytes) {
+               trace_btrfs_space_reservation(root->fs_info, "transaction",
+                                             (u64)h, num_bytes, 1);
                h->block_rsv = &root->fs_info->trans_block_rsv;
                h->bytes_reserved = num_bytes;
        }
@@ -467,19 +474,12 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_metadata(trans, root);
        trans->block_rsv = NULL;
-       while (count < 4) {
+       while (count < 2) {
                unsigned long cur = trans->delayed_ref_updates;
                trans->delayed_ref_updates = 0;
                if (cur &&
                    trans->transaction->delayed_refs.num_heads_ready > 64) {
                        trans->delayed_ref_updates = 0;
-
-                       /*
-                        * do a full flush if the transaction is trying
-                        * to close
-                        */
-                       if (trans->transaction->delayed_refs.flushing)
-                               cur = 0;
                        btrfs_run_delayed_refs(trans, root, cur);
                } else {
                        break;
@@ -1393,9 +1393,9 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root)
 
                if (btrfs_header_backref_rev(root->node) <
                    BTRFS_MIXED_BACKREF_REV)
-                       btrfs_drop_snapshot(root, NULL, 0);
+                       btrfs_drop_snapshot(root, NULL, 0, 0);
                else
-                       btrfs_drop_snapshot(root, NULL, 1);
+                       btrfs_drop_snapshot(root, NULL, 1, 0);
        }
        return 0;
 }
index 3568374d419da8ee50eb17f4af5319964750614d..966cc74f5d6c7303b06bb8bd067826f07510ffc8 100644 (file)
@@ -589,7 +589,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                                ret = btrfs_inc_extent_ref(trans, root,
                                                ins.objectid, ins.offset,
                                                0, root->root_key.objectid,
-                                               key->objectid, offset);
+                                               key->objectid, offset, 0);
                                BUG_ON(ret);
                        } else {
                                /*
@@ -1957,7 +1957,8 @@ static int wait_log_commit(struct btrfs_trans_handle *trans,
 
                finish_wait(&root->log_commit_wait[index], &wait);
                mutex_lock(&root->log_mutex);
-       } while (root->log_transid < transid + 2 &&
+       } while (root->fs_info->last_trans_log_full_commit !=
+                trans->transid && root->log_transid < transid + 2 &&
                 atomic_read(&root->log_commit[index]));
        return 0;
 }
@@ -1966,7 +1967,8 @@ static int wait_for_writer(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root)
 {
        DEFINE_WAIT(wait);
-       while (atomic_read(&root->log_writers)) {
+       while (root->fs_info->last_trans_log_full_commit !=
+              trans->transid && atomic_read(&root->log_writers)) {
                prepare_to_wait(&root->log_writer_wait,
                                &wait, TASK_UNINTERRUPTIBLE);
                mutex_unlock(&root->log_mutex);
diff --git a/fs/btrfs/ulist.c b/fs/btrfs/ulist.c
new file mode 100644 (file)
index 0000000..12f5147
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2011 STRATO AG
+ * written by Arne Jansen <sensille@gmx.net>
+ * Distributed under the GNU GPL license version 2.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include "ulist.h"
+
+/*
+ * ulist is a generic data structure to hold a collection of unique u64
+ * values. The only operations it supports is adding to the list and
+ * enumerating it.
+ * It is possible to store an auxiliary value along with the key.
+ *
+ * The implementation is preliminary and can probably be sped up
+ * significantly. A first step would be to store the values in an rbtree
+ * as soon as ULIST_SIZE is exceeded.
+ *
+ * A sample usage for ulists is the enumeration of directed graphs without
+ * visiting a node twice. The pseudo-code could look like this:
+ *
+ * ulist = ulist_alloc();
+ * ulist_add(ulist, root);
+ * elem = NULL;
+ *
+ * while ((elem = ulist_next(ulist, elem)) {
+ *     for (all child nodes n in elem)
+ *             ulist_add(ulist, n);
+ *     do something useful with the node;
+ * }
+ * ulist_free(ulist);
+ *
+ * This assumes the graph nodes are adressable by u64. This stems from the
+ * usage for tree enumeration in btrfs, where the logical addresses are
+ * 64 bit.
+ *
+ * It is also useful for tree enumeration which could be done elegantly
+ * recursively, but is not possible due to kernel stack limitations. The
+ * loop would be similar to the above.
+ */
+
+/**
+ * ulist_init - freshly initialize a ulist
+ * @ulist:     the ulist to initialize
+ *
+ * Note: don't use this function to init an already used ulist, use
+ * ulist_reinit instead.
+ */
+void ulist_init(struct ulist *ulist)
+{
+       ulist->nnodes = 0;
+       ulist->nodes = ulist->int_nodes;
+       ulist->nodes_alloced = ULIST_SIZE;
+}
+EXPORT_SYMBOL(ulist_init);
+
+/**
+ * ulist_fini - free up additionally allocated memory for the ulist
+ * @ulist:     the ulist from which to free the additional memory
+ *
+ * This is useful in cases where the base 'struct ulist' has been statically
+ * allocated.
+ */
+void ulist_fini(struct ulist *ulist)
+{
+       /*
+        * The first ULIST_SIZE elements are stored inline in struct ulist.
+        * Only if more elements are alocated they need to be freed.
+        */
+       if (ulist->nodes_alloced > ULIST_SIZE)
+               kfree(ulist->nodes);
+       ulist->nodes_alloced = 0;       /* in case ulist_fini is called twice */
+}
+EXPORT_SYMBOL(ulist_fini);
+
+/**
+ * ulist_reinit - prepare a ulist for reuse
+ * @ulist:     ulist to be reused
+ *
+ * Free up all additional memory allocated for the list elements and reinit
+ * the ulist.
+ */
+void ulist_reinit(struct ulist *ulist)
+{
+       ulist_fini(ulist);
+       ulist_init(ulist);
+}
+EXPORT_SYMBOL(ulist_reinit);
+
+/**
+ * ulist_alloc - dynamically allocate a ulist
+ * @gfp_mask:  allocation flags to for base allocation
+ *
+ * The allocated ulist will be returned in an initialized state.
+ */
+struct ulist *ulist_alloc(unsigned long gfp_mask)
+{
+       struct ulist *ulist = kmalloc(sizeof(*ulist), gfp_mask);
+
+       if (!ulist)
+               return NULL;
+
+       ulist_init(ulist);
+
+       return ulist;
+}
+EXPORT_SYMBOL(ulist_alloc);
+
+/**
+ * ulist_free - free dynamically allocated ulist
+ * @ulist:     ulist to free
+ *
+ * It is not necessary to call ulist_fini before.
+ */
+void ulist_free(struct ulist *ulist)
+{
+       if (!ulist)
+               return;
+       ulist_fini(ulist);
+       kfree(ulist);
+}
+EXPORT_SYMBOL(ulist_free);
+
+/**
+ * ulist_add - add an element to the ulist
+ * @ulist:     ulist to add the element to
+ * @val:       value to add to ulist
+ * @aux:       auxiliary value to store along with val
+ * @gfp_mask:  flags to use for allocation
+ *
+ * Note: locking must be provided by the caller. In case of rwlocks write
+ *       locking is needed
+ *
+ * Add an element to a ulist. The @val will only be added if it doesn't
+ * already exist. If it is added, the auxiliary value @aux is stored along with
+ * it. In case @val already exists in the ulist, @aux is ignored, even if
+ * it differs from the already stored value.
+ *
+ * ulist_add returns 0 if @val already exists in ulist and 1 if @val has been
+ * inserted.
+ * In case of allocation failure -ENOMEM is returned and the ulist stays
+ * unaltered.
+ */
+int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
+             unsigned long gfp_mask)
+{
+       int i;
+
+       for (i = 0; i < ulist->nnodes; ++i) {
+               if (ulist->nodes[i].val == val)
+                       return 0;
+       }
+
+       if (ulist->nnodes >= ulist->nodes_alloced) {
+               u64 new_alloced = ulist->nodes_alloced + 128;
+               struct ulist_node *new_nodes;
+               void *old = NULL;
+
+               /*
+                * if nodes_alloced == ULIST_SIZE no memory has been allocated
+                * yet, so pass NULL to krealloc
+                */
+               if (ulist->nodes_alloced > ULIST_SIZE)
+                       old = ulist->nodes;
+
+               new_nodes = krealloc(old, sizeof(*new_nodes) * new_alloced,
+                                    gfp_mask);
+               if (!new_nodes)
+                       return -ENOMEM;
+
+               if (!old)
+                       memcpy(new_nodes, ulist->int_nodes,
+                              sizeof(ulist->int_nodes));
+
+               ulist->nodes = new_nodes;
+               ulist->nodes_alloced = new_alloced;
+       }
+       ulist->nodes[ulist->nnodes].val = val;
+       ulist->nodes[ulist->nnodes].aux = aux;
+       ++ulist->nnodes;
+
+       return 1;
+}
+EXPORT_SYMBOL(ulist_add);
+
+/**
+ * ulist_next - iterate ulist
+ * @ulist:     ulist to iterate
+ * @prev:      previously returned element or %NULL to start iteration
+ *
+ * Note: locking must be provided by the caller. In case of rwlocks only read
+ *       locking is needed
+ *
+ * This function is used to iterate an ulist. The iteration is started with
+ * @prev = %NULL. It returns the next element from the ulist or %NULL when the
+ * end is reached. No guarantee is made with respect to the order in which
+ * the elements are returned. They might neither be returned in order of
+ * addition nor in ascending order.
+ * It is allowed to call ulist_add during an enumeration. Newly added items
+ * are guaranteed to show up in the running enumeration.
+ */
+struct ulist_node *ulist_next(struct ulist *ulist, struct ulist_node *prev)
+{
+       int next;
+
+       if (ulist->nnodes == 0)
+               return NULL;
+
+       if (!prev)
+               return &ulist->nodes[0];
+
+       next = (prev - ulist->nodes) + 1;
+       if (next < 0 || next >= ulist->nnodes)
+               return NULL;
+
+       return &ulist->nodes[next];
+}
+EXPORT_SYMBOL(ulist_next);
diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h
new file mode 100644 (file)
index 0000000..2e25dec
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 STRATO AG
+ * written by Arne Jansen <sensille@gmx.net>
+ * Distributed under the GNU GPL license version 2.
+ *
+ */
+
+#ifndef __ULIST__
+#define __ULIST__
+
+/*
+ * ulist is a generic data structure to hold a collection of unique u64
+ * values. The only operations it supports is adding to the list and
+ * enumerating it.
+ * It is possible to store an auxiliary value along with the key.
+ *
+ * The implementation is preliminary and can probably be sped up
+ * significantly. A first step would be to store the values in an rbtree
+ * as soon as ULIST_SIZE is exceeded.
+ */
+
+/*
+ * number of elements statically allocated inside struct ulist
+ */
+#define ULIST_SIZE 16
+
+/*
+ * element of the list
+ */
+struct ulist_node {
+       u64 val;                /* value to store */
+       unsigned long aux;      /* auxiliary value saved along with the val */
+};
+
+struct ulist {
+       /*
+        * number of elements stored in list
+        */
+       unsigned long nnodes;
+
+       /*
+        * number of nodes we already have room for
+        */
+       unsigned long nodes_alloced;
+
+       /*
+        * pointer to the array storing the elements. The first ULIST_SIZE
+        * elements are stored inline. In this case the it points to int_nodes.
+        * After exceeding ULIST_SIZE, dynamic memory is allocated.
+        */
+       struct ulist_node *nodes;
+
+       /*
+        * inline storage space for the first ULIST_SIZE entries
+        */
+       struct ulist_node int_nodes[ULIST_SIZE];
+};
+
+void ulist_init(struct ulist *ulist);
+void ulist_fini(struct ulist *ulist);
+void ulist_reinit(struct ulist *ulist);
+struct ulist *ulist_alloc(unsigned long gfp_mask);
+void ulist_free(struct ulist *ulist);
+int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
+             unsigned long gfp_mask);
+struct ulist_node *ulist_next(struct ulist *ulist, struct ulist_node *prev);
+
+#endif
index f4b839fd3c9dd5cd854cb7bada4e3831d8ea1713..0b4e2af7954d3c209d8f1e581d4ee26c0cb60c2f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/random.h>
 #include <linux/iocontext.h>
 #include <linux/capability.h>
+#include <linux/kthread.h>
 #include <asm/div64.h>
 #include "compat.h"
 #include "ctree.h"
@@ -32,6 +33,7 @@
 #include "print-tree.h"
 #include "volumes.h"
 #include "async-thread.h"
+#include "check-integrity.h"
 
 static int init_first_rw_device(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
@@ -246,7 +248,7 @@ loop_lock:
                        sync_pending = 0;
                }
 
-               submit_bio(cur->bi_rw, cur);
+               btrfsic_submit_bio(cur->bi_rw, cur);
                num_run++;
                batch_run++;
                if (need_resched())
@@ -706,8 +708,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        u64 devid;
        u64 transid;
 
-       mutex_lock(&uuid_mutex);
-
        flags |= FMODE_EXCL;
        bdev = blkdev_get_by_path(path, flags, holder);
 
@@ -716,6 +716,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
                goto error;
        }
 
+       mutex_lock(&uuid_mutex);
        ret = set_blocksize(bdev, 4096);
        if (ret)
                goto error_close;
@@ -737,9 +738,9 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 
        brelse(bh);
 error_close:
+       mutex_unlock(&uuid_mutex);
        blkdev_put(bdev, flags);
 error:
-       mutex_unlock(&uuid_mutex);
        return ret;
 }
 
@@ -829,7 +830,6 @@ out:
 
 /*
  * find_free_dev_extent - find free space in the specified device
- * @trans:     transaction handler
  * @device:    the device which we search the free space in
  * @num_bytes: the size of the free space that we need
  * @start:     store the start of the free space.
@@ -848,8 +848,7 @@ out:
  * But if we don't find suitable free space, it is used to store the size of
  * the max free space.
  */
-int find_free_dev_extent(struct btrfs_trans_handle *trans,
-                        struct btrfs_device *device, u64 num_bytes,
+int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
                         u64 *start, u64 *len)
 {
        struct btrfs_key key;
@@ -893,7 +892,7 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans,
        key.offset = search_start;
        key.type = BTRFS_DEV_EXTENT_KEY;
 
-       ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
+       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
                goto out;
        if (ret > 0) {
@@ -1282,7 +1281,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
        bool clear_super = false;
 
        mutex_lock(&uuid_mutex);
-       mutex_lock(&root->fs_info->volume_mutex);
 
        all_avail = root->fs_info->avail_data_alloc_bits |
                root->fs_info->avail_system_alloc_bits |
@@ -1452,7 +1450,6 @@ error_close:
        if (bdev)
                blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
 out:
-       mutex_unlock(&root->fs_info->volume_mutex);
        mutex_unlock(&uuid_mutex);
        return ret;
 error_undo:
@@ -1469,8 +1466,7 @@ error_undo:
 /*
  * does all the dirty work required for changing file system's UUID.
  */
-static int btrfs_prepare_sprout(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root)
+static int btrfs_prepare_sprout(struct btrfs_root *root)
 {
        struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
        struct btrfs_fs_devices *old_devices;
@@ -1629,7 +1625,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
        }
 
        filemap_write_and_wait(bdev->bd_inode->i_mapping);
-       mutex_lock(&root->fs_info->volume_mutex);
 
        devices = &root->fs_info->fs_devices->devices;
        /*
@@ -1695,7 +1690,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 
        if (seeding_dev) {
                sb->s_flags &= ~MS_RDONLY;
-               ret = btrfs_prepare_sprout(trans, root);
+               ret = btrfs_prepare_sprout(root);
                BUG_ON(ret);
        }
 
@@ -1757,8 +1752,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                ret = btrfs_relocate_sys_chunks(root);
                BUG_ON(ret);
        }
-out:
-       mutex_unlock(&root->fs_info->volume_mutex);
+
        return ret;
 error:
        blkdev_put(bdev, FMODE_EXCL);
@@ -1766,7 +1760,7 @@ error:
                mutex_unlock(&uuid_mutex);
                up_write(&sb->s_umount);
        }
-       goto out;
+       return ret;
 }
 
 static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
@@ -2077,6 +2071,362 @@ error:
        return ret;
 }
 
+static int insert_balance_item(struct btrfs_root *root,
+                              struct btrfs_balance_control *bctl)
+{
+       struct btrfs_trans_handle *trans;
+       struct btrfs_balance_item *item;
+       struct btrfs_disk_balance_args disk_bargs;
+       struct btrfs_path *path;
+       struct extent_buffer *leaf;
+       struct btrfs_key key;
+       int ret, err;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       trans = btrfs_start_transaction(root, 0);
+       if (IS_ERR(trans)) {
+               btrfs_free_path(path);
+               return PTR_ERR(trans);
+       }
+
+       key.objectid = BTRFS_BALANCE_OBJECTID;
+       key.type = BTRFS_BALANCE_ITEM_KEY;
+       key.offset = 0;
+
+       ret = btrfs_insert_empty_item(trans, root, path, &key,
+                                     sizeof(*item));
+       if (ret)
+               goto out;
+
+       leaf = path->nodes[0];
+       item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item);
+
+       memset_extent_buffer(leaf, 0, (unsigned long)item, sizeof(*item));
+
+       btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->data);
+       btrfs_set_balance_data(leaf, item, &disk_bargs);
+       btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->meta);
+       btrfs_set_balance_meta(leaf, item, &disk_bargs);
+       btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->sys);
+       btrfs_set_balance_sys(leaf, item, &disk_bargs);
+
+       btrfs_set_balance_flags(leaf, item, bctl->flags);
+
+       btrfs_mark_buffer_dirty(leaf);
+out:
+       btrfs_free_path(path);
+       err = btrfs_commit_transaction(trans, root);
+       if (err && !ret)
+               ret = err;
+       return ret;
+}
+
+static int del_balance_item(struct btrfs_root *root)
+{
+       struct btrfs_trans_handle *trans;
+       struct btrfs_path *path;
+       struct btrfs_key key;
+       int ret, err;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       trans = btrfs_start_transaction(root, 0);
+       if (IS_ERR(trans)) {
+               btrfs_free_path(path);
+               return PTR_ERR(trans);
+       }
+
+       key.objectid = BTRFS_BALANCE_OBJECTID;
+       key.type = BTRFS_BALANCE_ITEM_KEY;
+       key.offset = 0;
+
+       ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+       if (ret < 0)
+               goto out;
+       if (ret > 0) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       ret = btrfs_del_item(trans, root, path);
+out:
+       btrfs_free_path(path);
+       err = btrfs_commit_transaction(trans, root);
+       if (err && !ret)
+               ret = err;
+       return ret;
+}
+
+/*
+ * This is a heuristic used to reduce the number of chunks balanced on
+ * resume after balance was interrupted.
+ */
+static void update_balance_args(struct btrfs_balance_control *bctl)
+{
+       /*
+        * Turn on soft mode for chunk types that were being converted.
+        */
+       if (bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT)
+               bctl->data.flags |= BTRFS_BALANCE_ARGS_SOFT;
+       if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT)
+               bctl->sys.flags |= BTRFS_BALANCE_ARGS_SOFT;
+       if (bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT)
+               bctl->meta.flags |= BTRFS_BALANCE_ARGS_SOFT;
+
+       /*
+        * Turn on usage filter if is not already used.  The idea is
+        * that chunks that we have already balanced should be
+        * reasonably full.  Don't do it for chunks that are being
+        * converted - that will keep us from relocating unconverted
+        * (albeit full) chunks.
+        */
+       if (!(bctl->data.flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           !(bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT)) {
+               bctl->data.flags |= BTRFS_BALANCE_ARGS_USAGE;
+               bctl->data.usage = 90;
+       }
+       if (!(bctl->sys.flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           !(bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT)) {
+               bctl->sys.flags |= BTRFS_BALANCE_ARGS_USAGE;
+               bctl->sys.usage = 90;
+       }
+       if (!(bctl->meta.flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           !(bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT)) {
+               bctl->meta.flags |= BTRFS_BALANCE_ARGS_USAGE;
+               bctl->meta.usage = 90;
+       }
+}
+
+/*
+ * Should be called with both balance and volume mutexes held to
+ * serialize other volume operations (add_dev/rm_dev/resize) with
+ * restriper.  Same goes for unset_balance_control.
+ */
+static void set_balance_control(struct btrfs_balance_control *bctl)
+{
+       struct btrfs_fs_info *fs_info = bctl->fs_info;
+
+       BUG_ON(fs_info->balance_ctl);
+
+       spin_lock(&fs_info->balance_lock);
+       fs_info->balance_ctl = bctl;
+       spin_unlock(&fs_info->balance_lock);
+}
+
+static void unset_balance_control(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_balance_control *bctl = fs_info->balance_ctl;
+
+       BUG_ON(!fs_info->balance_ctl);
+
+       spin_lock(&fs_info->balance_lock);
+       fs_info->balance_ctl = NULL;
+       spin_unlock(&fs_info->balance_lock);
+
+       kfree(bctl);
+}
+
+/*
+ * Balance filters.  Return 1 if chunk should be filtered out
+ * (should not be balanced).
+ */
+static int chunk_profiles_filter(u64 chunk_profile,
+                                struct btrfs_balance_args *bargs)
+{
+       chunk_profile &= BTRFS_BLOCK_GROUP_PROFILE_MASK;
+
+       if (chunk_profile == 0)
+               chunk_profile = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+
+       if (bargs->profiles & chunk_profile)
+               return 0;
+
+       return 1;
+}
+
+static u64 div_factor_fine(u64 num, int factor)
+{
+       if (factor <= 0)
+               return 0;
+       if (factor >= 100)
+               return num;
+
+       num *= factor;
+       do_div(num, 100);
+       return num;
+}
+
+static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
+                             struct btrfs_balance_args *bargs)
+{
+       struct btrfs_block_group_cache *cache;
+       u64 chunk_used, user_thresh;
+       int ret = 1;
+
+       cache = btrfs_lookup_block_group(fs_info, chunk_offset);
+       chunk_used = btrfs_block_group_used(&cache->item);
+
+       user_thresh = div_factor_fine(cache->key.offset, bargs->usage);
+       if (chunk_used < user_thresh)
+               ret = 0;
+
+       btrfs_put_block_group(cache);
+       return ret;
+}
+
+static int chunk_devid_filter(struct extent_buffer *leaf,
+                             struct btrfs_chunk *chunk,
+                             struct btrfs_balance_args *bargs)
+{
+       struct btrfs_stripe *stripe;
+       int num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+       int i;
+
+       for (i = 0; i < num_stripes; i++) {
+               stripe = btrfs_stripe_nr(chunk, i);
+               if (btrfs_stripe_devid(leaf, stripe) == bargs->devid)
+                       return 0;
+       }
+
+       return 1;
+}
+
+/* [pstart, pend) */
+static int chunk_drange_filter(struct extent_buffer *leaf,
+                              struct btrfs_chunk *chunk,
+                              u64 chunk_offset,
+                              struct btrfs_balance_args *bargs)
+{
+       struct btrfs_stripe *stripe;
+       int num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+       u64 stripe_offset;
+       u64 stripe_length;
+       int factor;
+       int i;
+
+       if (!(bargs->flags & BTRFS_BALANCE_ARGS_DEVID))
+               return 0;
+
+       if (btrfs_chunk_type(leaf, chunk) & (BTRFS_BLOCK_GROUP_DUP |
+            BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10))
+               factor = 2;
+       else
+               factor = 1;
+       factor = num_stripes / factor;
+
+       for (i = 0; i < num_stripes; i++) {
+               stripe = btrfs_stripe_nr(chunk, i);
+               if (btrfs_stripe_devid(leaf, stripe) != bargs->devid)
+                       continue;
+
+               stripe_offset = btrfs_stripe_offset(leaf, stripe);
+               stripe_length = btrfs_chunk_length(leaf, chunk);
+               do_div(stripe_length, factor);
+
+               if (stripe_offset < bargs->pend &&
+                   stripe_offset + stripe_length > bargs->pstart)
+                       return 0;
+       }
+
+       return 1;
+}
+
+/* [vstart, vend) */
+static int chunk_vrange_filter(struct extent_buffer *leaf,
+                              struct btrfs_chunk *chunk,
+                              u64 chunk_offset,
+                              struct btrfs_balance_args *bargs)
+{
+       if (chunk_offset < bargs->vend &&
+           chunk_offset + btrfs_chunk_length(leaf, chunk) > bargs->vstart)
+               /* at least part of the chunk is inside this vrange */
+               return 0;
+
+       return 1;
+}
+
+static int chunk_soft_convert_filter(u64 chunk_profile,
+                                    struct btrfs_balance_args *bargs)
+{
+       if (!(bargs->flags & BTRFS_BALANCE_ARGS_CONVERT))
+               return 0;
+
+       chunk_profile &= BTRFS_BLOCK_GROUP_PROFILE_MASK;
+
+       if (chunk_profile == 0)
+               chunk_profile = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+
+       if (bargs->target & chunk_profile)
+               return 1;
+
+       return 0;
+}
+
+static int should_balance_chunk(struct btrfs_root *root,
+                               struct extent_buffer *leaf,
+                               struct btrfs_chunk *chunk, u64 chunk_offset)
+{
+       struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
+       struct btrfs_balance_args *bargs = NULL;
+       u64 chunk_type = btrfs_chunk_type(leaf, chunk);
+
+       /* type filter */
+       if (!((chunk_type & BTRFS_BLOCK_GROUP_TYPE_MASK) &
+             (bctl->flags & BTRFS_BALANCE_TYPE_MASK))) {
+               return 0;
+       }
+
+       if (chunk_type & BTRFS_BLOCK_GROUP_DATA)
+               bargs = &bctl->data;
+       else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM)
+               bargs = &bctl->sys;
+       else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA)
+               bargs = &bctl->meta;
+
+       /* profiles filter */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_PROFILES) &&
+           chunk_profiles_filter(chunk_type, bargs)) {
+               return 0;
+       }
+
+       /* usage filter */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           chunk_usage_filter(bctl->fs_info, chunk_offset, bargs)) {
+               return 0;
+       }
+
+       /* devid filter */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_DEVID) &&
+           chunk_devid_filter(leaf, chunk, bargs)) {
+               return 0;
+       }
+
+       /* drange filter, makes sense only with devid filter */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_DRANGE) &&
+           chunk_drange_filter(leaf, chunk, chunk_offset, bargs)) {
+               return 0;
+       }
+
+       /* vrange filter */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_VRANGE) &&
+           chunk_vrange_filter(leaf, chunk, chunk_offset, bargs)) {
+               return 0;
+       }
+
+       /* soft profile changing mode */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_SOFT) &&
+           chunk_soft_convert_filter(chunk_type, bargs)) {
+               return 0;
+       }
+
+       return 1;
+}
+
 static u64 div_factor(u64 num, int factor)
 {
        if (factor == 10)
@@ -2086,29 +2436,28 @@ static u64 div_factor(u64 num, int factor)
        return num;
 }
 
-int btrfs_balance(struct btrfs_root *dev_root)
+static int __btrfs_balance(struct btrfs_fs_info *fs_info)
 {
-       int ret;
-       struct list_head *devices = &dev_root->fs_info->fs_devices->devices;
+       struct btrfs_balance_control *bctl = fs_info->balance_ctl;
+       struct btrfs_root *chunk_root = fs_info->chunk_root;
+       struct btrfs_root *dev_root = fs_info->dev_root;
+       struct list_head *devices;
        struct btrfs_device *device;
        u64 old_size;
        u64 size_to_free;
+       struct btrfs_chunk *chunk;
        struct btrfs_path *path;
        struct btrfs_key key;
-       struct btrfs_root *chunk_root = dev_root->fs_info->chunk_root;
-       struct btrfs_trans_handle *trans;
        struct btrfs_key found_key;
-
-       if (dev_root->fs_info->sb->s_flags & MS_RDONLY)
-               return -EROFS;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       mutex_lock(&dev_root->fs_info->volume_mutex);
-       dev_root = dev_root->fs_info->dev_root;
+       struct btrfs_trans_handle *trans;
+       struct extent_buffer *leaf;
+       int slot;
+       int ret;
+       int enospc_errors = 0;
+       bool counting = true;
 
        /* step one make some room on all the devices */
+       devices = &fs_info->fs_devices->devices;
        list_for_each_entry(device, devices, dev_list) {
                old_size = device->total_bytes;
                size_to_free = div_factor(old_size, 1);
@@ -2137,11 +2486,23 @@ int btrfs_balance(struct btrfs_root *dev_root)
                ret = -ENOMEM;
                goto error;
        }
+
+       /* zero out stat counters */
+       spin_lock(&fs_info->balance_lock);
+       memset(&bctl->stat, 0, sizeof(bctl->stat));
+       spin_unlock(&fs_info->balance_lock);
+again:
        key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
        key.offset = (u64)-1;
        key.type = BTRFS_CHUNK_ITEM_KEY;
 
        while (1) {
+               if ((!counting && atomic_read(&fs_info->balance_pause_req)) ||
+                   atomic_read(&fs_info->balance_cancel_req)) {
+                       ret = -ECANCELED;
+                       goto error;
+               }
+
                ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
                if (ret < 0)
                        goto error;
@@ -2151,15 +2512,19 @@ int btrfs_balance(struct btrfs_root *dev_root)
                 * failed
                 */
                if (ret == 0)
-                       break;
+                       BUG(); /* FIXME break ? */
 
                ret = btrfs_previous_item(chunk_root, path, 0,
                                          BTRFS_CHUNK_ITEM_KEY);
-               if (ret)
+               if (ret) {
+                       ret = 0;
                        break;
+               }
+
+               leaf = path->nodes[0];
+               slot = path->slots[0];
+               btrfs_item_key_to_cpu(leaf, &found_key, slot);
 
-               btrfs_item_key_to_cpu(path->nodes[0], &found_key,
-                                     path->slots[0]);
                if (found_key.objectid != key.objectid)
                        break;
 
@@ -2167,22 +2532,375 @@ int btrfs_balance(struct btrfs_root *dev_root)
                if (found_key.offset == 0)
                        break;
 
+               chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
+
+               if (!counting) {
+                       spin_lock(&fs_info->balance_lock);
+                       bctl->stat.considered++;
+                       spin_unlock(&fs_info->balance_lock);
+               }
+
+               ret = should_balance_chunk(chunk_root, leaf, chunk,
+                                          found_key.offset);
                btrfs_release_path(path);
+               if (!ret)
+                       goto loop;
+
+               if (counting) {
+                       spin_lock(&fs_info->balance_lock);
+                       bctl->stat.expected++;
+                       spin_unlock(&fs_info->balance_lock);
+                       goto loop;
+               }
+
                ret = btrfs_relocate_chunk(chunk_root,
                                           chunk_root->root_key.objectid,
                                           found_key.objectid,
                                           found_key.offset);
                if (ret && ret != -ENOSPC)
                        goto error;
+               if (ret == -ENOSPC) {
+                       enospc_errors++;
+               } else {
+                       spin_lock(&fs_info->balance_lock);
+                       bctl->stat.completed++;
+                       spin_unlock(&fs_info->balance_lock);
+               }
+loop:
                key.offset = found_key.offset - 1;
        }
-       ret = 0;
+
+       if (counting) {
+               btrfs_release_path(path);
+               counting = false;
+               goto again;
+       }
 error:
        btrfs_free_path(path);
-       mutex_unlock(&dev_root->fs_info->volume_mutex);
+       if (enospc_errors) {
+               printk(KERN_INFO "btrfs: %d enospc errors during balance\n",
+                      enospc_errors);
+               if (!ret)
+                       ret = -ENOSPC;
+       }
+
        return ret;
 }
 
+static inline int balance_need_close(struct btrfs_fs_info *fs_info)
+{
+       /* cancel requested || normal exit path */
+       return atomic_read(&fs_info->balance_cancel_req) ||
+               (atomic_read(&fs_info->balance_pause_req) == 0 &&
+                atomic_read(&fs_info->balance_cancel_req) == 0);
+}
+
+static void __cancel_balance(struct btrfs_fs_info *fs_info)
+{
+       int ret;
+
+       unset_balance_control(fs_info);
+       ret = del_balance_item(fs_info->tree_root);
+       BUG_ON(ret);
+}
+
+void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
+                              struct btrfs_ioctl_balance_args *bargs);
+
+/*
+ * Should be called with both balance and volume mutexes held
+ */
+int btrfs_balance(struct btrfs_balance_control *bctl,
+                 struct btrfs_ioctl_balance_args *bargs)
+{
+       struct btrfs_fs_info *fs_info = bctl->fs_info;
+       u64 allowed;
+       int ret;
+
+       if (btrfs_fs_closing(fs_info) ||
+           atomic_read(&fs_info->balance_pause_req) ||
+           atomic_read(&fs_info->balance_cancel_req)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /*
+        * In case of mixed groups both data and meta should be picked,
+        * and identical options should be given for both of them.
+        */
+       allowed = btrfs_super_incompat_flags(fs_info->super_copy);
+       if ((allowed & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) &&
+           (bctl->flags & (BTRFS_BALANCE_DATA | BTRFS_BALANCE_METADATA))) {
+               if (!(bctl->flags & BTRFS_BALANCE_DATA) ||
+                   !(bctl->flags & BTRFS_BALANCE_METADATA) ||
+                   memcmp(&bctl->data, &bctl->meta, sizeof(bctl->data))) {
+                       printk(KERN_ERR "btrfs: with mixed groups data and "
+                              "metadata balance options must be the same\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+       /*
+        * Profile changing sanity checks.  Skip them if a simple
+        * balance is requested.
+        */
+       if (!((bctl->data.flags | bctl->sys.flags | bctl->meta.flags) &
+             BTRFS_BALANCE_ARGS_CONVERT))
+               goto do_balance;
+
+       allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+       if (fs_info->fs_devices->num_devices == 1)
+               allowed |= BTRFS_BLOCK_GROUP_DUP;
+       else if (fs_info->fs_devices->num_devices < 4)
+               allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1);
+       else
+               allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
+                               BTRFS_BLOCK_GROUP_RAID10);
+
+       if (!profile_is_valid(bctl->data.target, 1) ||
+           bctl->data.target & ~allowed) {
+               printk(KERN_ERR "btrfs: unable to start balance with target "
+                      "data profile %llu\n",
+                      (unsigned long long)bctl->data.target);
+               ret = -EINVAL;
+               goto out;
+       }
+       if (!profile_is_valid(bctl->meta.target, 1) ||
+           bctl->meta.target & ~allowed) {
+               printk(KERN_ERR "btrfs: unable to start balance with target "
+                      "metadata profile %llu\n",
+                      (unsigned long long)bctl->meta.target);
+               ret = -EINVAL;
+               goto out;
+       }
+       if (!profile_is_valid(bctl->sys.target, 1) ||
+           bctl->sys.target & ~allowed) {
+               printk(KERN_ERR "btrfs: unable to start balance with target "
+                      "system profile %llu\n",
+                      (unsigned long long)bctl->sys.target);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (bctl->data.target & BTRFS_BLOCK_GROUP_DUP) {
+               printk(KERN_ERR "btrfs: dup for data is not allowed\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* allow to reduce meta or sys integrity only if force set */
+       allowed = BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 |
+                       BTRFS_BLOCK_GROUP_RAID10;
+       if (((bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
+            (fs_info->avail_system_alloc_bits & allowed) &&
+            !(bctl->sys.target & allowed)) ||
+           ((bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
+            (fs_info->avail_metadata_alloc_bits & allowed) &&
+            !(bctl->meta.target & allowed))) {
+               if (bctl->flags & BTRFS_BALANCE_FORCE) {
+                       printk(KERN_INFO "btrfs: force reducing metadata "
+                              "integrity\n");
+               } else {
+                       printk(KERN_ERR "btrfs: balance will reduce metadata "
+                              "integrity, use force if you want this\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+do_balance:
+       ret = insert_balance_item(fs_info->tree_root, bctl);
+       if (ret && ret != -EEXIST)
+               goto out;
+
+       if (!(bctl->flags & BTRFS_BALANCE_RESUME)) {
+               BUG_ON(ret == -EEXIST);
+               set_balance_control(bctl);
+       } else {
+               BUG_ON(ret != -EEXIST);
+               spin_lock(&fs_info->balance_lock);
+               update_balance_args(bctl);
+               spin_unlock(&fs_info->balance_lock);
+       }
+
+       atomic_inc(&fs_info->balance_running);
+       mutex_unlock(&fs_info->balance_mutex);
+
+       ret = __btrfs_balance(fs_info);
+
+       mutex_lock(&fs_info->balance_mutex);
+       atomic_dec(&fs_info->balance_running);
+
+       if (bargs) {
+               memset(bargs, 0, sizeof(*bargs));
+               update_ioctl_balance_args(fs_info, 0, bargs);
+       }
+
+       if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
+           balance_need_close(fs_info)) {
+               __cancel_balance(fs_info);
+       }
+
+       wake_up(&fs_info->balance_wait_q);
+
+       return ret;
+out:
+       if (bctl->flags & BTRFS_BALANCE_RESUME)
+               __cancel_balance(fs_info);
+       else
+               kfree(bctl);
+       return ret;
+}
+
+static int balance_kthread(void *data)
+{
+       struct btrfs_balance_control *bctl =
+                       (struct btrfs_balance_control *)data;
+       struct btrfs_fs_info *fs_info = bctl->fs_info;
+       int ret = 0;
+
+       mutex_lock(&fs_info->volume_mutex);
+       mutex_lock(&fs_info->balance_mutex);
+
+       set_balance_control(bctl);
+
+       if (btrfs_test_opt(fs_info->tree_root, SKIP_BALANCE)) {
+               printk(KERN_INFO "btrfs: force skipping balance\n");
+       } else {
+               printk(KERN_INFO "btrfs: continuing balance\n");
+               ret = btrfs_balance(bctl, NULL);
+       }
+
+       mutex_unlock(&fs_info->balance_mutex);
+       mutex_unlock(&fs_info->volume_mutex);
+       return ret;
+}
+
+int btrfs_recover_balance(struct btrfs_root *tree_root)
+{
+       struct task_struct *tsk;
+       struct btrfs_balance_control *bctl;
+       struct btrfs_balance_item *item;
+       struct btrfs_disk_balance_args disk_bargs;
+       struct btrfs_path *path;
+       struct extent_buffer *leaf;
+       struct btrfs_key key;
+       int ret;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
+       if (!bctl) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       key.objectid = BTRFS_BALANCE_OBJECTID;
+       key.type = BTRFS_BALANCE_ITEM_KEY;
+       key.offset = 0;
+
+       ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
+       if (ret < 0)
+               goto out_bctl;
+       if (ret > 0) { /* ret = -ENOENT; */
+               ret = 0;
+               goto out_bctl;
+       }
+
+       leaf = path->nodes[0];
+       item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item);
+
+       bctl->fs_info = tree_root->fs_info;
+       bctl->flags = btrfs_balance_flags(leaf, item) | BTRFS_BALANCE_RESUME;
+
+       btrfs_balance_data(leaf, item, &disk_bargs);
+       btrfs_disk_balance_args_to_cpu(&bctl->data, &disk_bargs);
+       btrfs_balance_meta(leaf, item, &disk_bargs);
+       btrfs_disk_balance_args_to_cpu(&bctl->meta, &disk_bargs);
+       btrfs_balance_sys(leaf, item, &disk_bargs);
+       btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
+
+       tsk = kthread_run(balance_kthread, bctl, "btrfs-balance");
+       if (IS_ERR(tsk))
+               ret = PTR_ERR(tsk);
+       else
+               goto out;
+
+out_bctl:
+       kfree(bctl);
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+int btrfs_pause_balance(struct btrfs_fs_info *fs_info)
+{
+       int ret = 0;
+
+       mutex_lock(&fs_info->balance_mutex);
+       if (!fs_info->balance_ctl) {
+               mutex_unlock(&fs_info->balance_mutex);
+               return -ENOTCONN;
+       }
+
+       if (atomic_read(&fs_info->balance_running)) {
+               atomic_inc(&fs_info->balance_pause_req);
+               mutex_unlock(&fs_info->balance_mutex);
+
+               wait_event(fs_info->balance_wait_q,
+                          atomic_read(&fs_info->balance_running) == 0);
+
+               mutex_lock(&fs_info->balance_mutex);
+               /* we are good with balance_ctl ripped off from under us */
+               BUG_ON(atomic_read(&fs_info->balance_running));
+               atomic_dec(&fs_info->balance_pause_req);
+       } else {
+               ret = -ENOTCONN;
+       }
+
+       mutex_unlock(&fs_info->balance_mutex);
+       return ret;
+}
+
+int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
+{
+       mutex_lock(&fs_info->balance_mutex);
+       if (!fs_info->balance_ctl) {
+               mutex_unlock(&fs_info->balance_mutex);
+               return -ENOTCONN;
+       }
+
+       atomic_inc(&fs_info->balance_cancel_req);
+       /*
+        * if we are running just wait and return, balance item is
+        * deleted in btrfs_balance in this case
+        */
+       if (atomic_read(&fs_info->balance_running)) {
+               mutex_unlock(&fs_info->balance_mutex);
+               wait_event(fs_info->balance_wait_q,
+                          atomic_read(&fs_info->balance_running) == 0);
+               mutex_lock(&fs_info->balance_mutex);
+       } else {
+               /* __cancel_balance needs volume_mutex */
+               mutex_unlock(&fs_info->balance_mutex);
+               mutex_lock(&fs_info->volume_mutex);
+               mutex_lock(&fs_info->balance_mutex);
+
+               if (fs_info->balance_ctl)
+                       __cancel_balance(fs_info);
+
+               mutex_unlock(&fs_info->volume_mutex);
+       }
+
+       BUG_ON(fs_info->balance_ctl || atomic_read(&fs_info->balance_running));
+       atomic_dec(&fs_info->balance_cancel_req);
+       mutex_unlock(&fs_info->balance_mutex);
+       return 0;
+}
+
 /*
  * shrinking a device means finding all of the device extents past
  * the new size, and then following the back refs to the chunks.
@@ -2323,8 +3041,7 @@ done:
        return ret;
 }
 
-static int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
-                          struct btrfs_root *root,
+static int btrfs_add_system_chunk(struct btrfs_root *root,
                           struct btrfs_key *key,
                           struct btrfs_chunk *chunk, int item_size)
 {
@@ -2441,10 +3158,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                max_stripe_size = 1024 * 1024 * 1024;
                max_chunk_size = 10 * max_stripe_size;
        } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
-               max_stripe_size = 256 * 1024 * 1024;
+               /* for larger filesystems, use larger metadata chunks */
+               if (fs_devices->total_rw_bytes > 50ULL * 1024 * 1024 * 1024)
+                       max_stripe_size = 1024 * 1024 * 1024;
+               else
+                       max_stripe_size = 256 * 1024 * 1024;
                max_chunk_size = max_stripe_size;
        } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
-               max_stripe_size = 8 * 1024 * 1024;
+               max_stripe_size = 32 * 1024 * 1024;
                max_chunk_size = 2 * max_stripe_size;
        } else {
                printk(KERN_ERR "btrfs: invalid chunk type 0x%llx requested\n",
@@ -2496,7 +3217,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                if (total_avail == 0)
                        continue;
 
-               ret = find_free_dev_extent(trans, device,
+               ret = find_free_dev_extent(device,
                                           max_stripe_size * dev_stripes,
                                           &dev_offset, &max_avail);
                if (ret && ret != -ENOSPC)
@@ -2687,7 +3408,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans,
        BUG_ON(ret);
 
        if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) {
-               ret = btrfs_add_system_chunk(trans, chunk_root, &key, chunk,
+               ret = btrfs_add_system_chunk(chunk_root, &key, chunk,
                                             item_size);
                BUG_ON(ret);
        }
@@ -2752,8 +3473,7 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
                return ret;
 
        alloc_profile = BTRFS_BLOCK_GROUP_METADATA |
-                       (fs_info->metadata_alloc_profile &
-                        fs_info->avail_metadata_alloc_bits);
+                               fs_info->avail_metadata_alloc_bits;
        alloc_profile = btrfs_reduce_alloc_profile(root, alloc_profile);
 
        ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size,
@@ -2763,8 +3483,7 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
        sys_chunk_offset = chunk_offset + chunk_size;
 
        alloc_profile = BTRFS_BLOCK_GROUP_SYSTEM |
-                       (fs_info->system_alloc_profile &
-                        fs_info->avail_system_alloc_bits);
+                               fs_info->avail_system_alloc_bits;
        alloc_profile = btrfs_reduce_alloc_profile(root, alloc_profile);
 
        ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
@@ -2901,26 +3620,13 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
        u64 stripe_nr;
        u64 stripe_nr_orig;
        u64 stripe_nr_end;
-       int stripes_allocated = 8;
-       int stripes_required = 1;
        int stripe_index;
        int i;
+       int ret = 0;
        int num_stripes;
        int max_errors = 0;
        struct btrfs_bio *bbio = NULL;
 
-       if (bbio_ret && !(rw & (REQ_WRITE | REQ_DISCARD)))
-               stripes_allocated = 1;
-again:
-       if (bbio_ret) {
-               bbio = kzalloc(btrfs_bio_size(stripes_allocated),
-                               GFP_NOFS);
-               if (!bbio)
-                       return -ENOMEM;
-
-               atomic_set(&bbio->error, 0);
-       }
-
        read_lock(&em_tree->lock);
        em = lookup_extent_mapping(em_tree, logical, *length);
        read_unlock(&em_tree->lock);
@@ -2939,32 +3645,6 @@ again:
        if (mirror_num > map->num_stripes)
                mirror_num = 0;
 
-       /* if our btrfs_bio struct is too small, back off and try again */
-       if (rw & REQ_WRITE) {
-               if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
-                                BTRFS_BLOCK_GROUP_DUP)) {
-                       stripes_required = map->num_stripes;
-                       max_errors = 1;
-               } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
-                       stripes_required = map->sub_stripes;
-                       max_errors = 1;
-               }
-       }
-       if (rw & REQ_DISCARD) {
-               if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
-                                BTRFS_BLOCK_GROUP_RAID1 |
-                                BTRFS_BLOCK_GROUP_DUP |
-                                BTRFS_BLOCK_GROUP_RAID10)) {
-                       stripes_required = map->num_stripes;
-               }
-       }
-       if (bbio_ret && (rw & (REQ_WRITE | REQ_DISCARD)) &&
-           stripes_allocated < stripes_required) {
-               stripes_allocated = map->num_stripes;
-               free_extent_map(em);
-               kfree(bbio);
-               goto again;
-       }
        stripe_nr = offset;
        /*
         * stripe_nr counts the total number of stripes we have to stride
@@ -2980,10 +3660,7 @@ again:
 
        if (rw & REQ_DISCARD)
                *length = min_t(u64, em->len - offset, *length);
-       else if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
-                             BTRFS_BLOCK_GROUP_RAID1 |
-                             BTRFS_BLOCK_GROUP_RAID10 |
-                             BTRFS_BLOCK_GROUP_DUP)) {
+       else if (map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
                /* we limit the length of each bio to what fits in a stripe */
                *length = min_t(u64, em->len - offset,
                                map->stripe_len - stripe_offset);
@@ -3059,81 +3736,55 @@ again:
        }
        BUG_ON(stripe_index >= map->num_stripes);
 
+       bbio = kzalloc(btrfs_bio_size(num_stripes), GFP_NOFS);
+       if (!bbio) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       atomic_set(&bbio->error, 0);
+
        if (rw & REQ_DISCARD) {
+               int factor = 0;
+               int sub_stripes = 0;
+               u64 stripes_per_dev = 0;
+               u32 remaining_stripes = 0;
+
+               if (map->type &
+                   (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
+                       if (map->type & BTRFS_BLOCK_GROUP_RAID0)
+                               sub_stripes = 1;
+                       else
+                               sub_stripes = map->sub_stripes;
+
+                       factor = map->num_stripes / sub_stripes;
+                       stripes_per_dev = div_u64_rem(stripe_nr_end -
+                                                     stripe_nr_orig,
+                                                     factor,
+                                                     &remaining_stripes);
+               }
+
                for (i = 0; i < num_stripes; i++) {
                        bbio->stripes[i].physical =
                                map->stripes[stripe_index].physical +
                                stripe_offset + stripe_nr * map->stripe_len;
                        bbio->stripes[i].dev = map->stripes[stripe_index].dev;
 
-                       if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
-                               u64 stripes;
-                               u32 last_stripe = 0;
-                               int j;
-
-                               div_u64_rem(stripe_nr_end - 1,
-                                           map->num_stripes,
-                                           &last_stripe);
-
-                               for (j = 0; j < map->num_stripes; j++) {
-                                       u32 test;
-
-                                       div_u64_rem(stripe_nr_end - 1 - j,
-                                                   map->num_stripes, &test);
-                                       if (test == stripe_index)
-                                               break;
-                               }
-                               stripes = stripe_nr_end - 1 - j;
-                               do_div(stripes, map->num_stripes);
-                               bbio->stripes[i].length = map->stripe_len *
-                                       (stripes - stripe_nr + 1);
-
-                               if (i == 0) {
-                                       bbio->stripes[i].length -=
-                                               stripe_offset;
-                                       stripe_offset = 0;
-                               }
-                               if (stripe_index == last_stripe)
-                                       bbio->stripes[i].length -=
-                                               stripe_end_offset;
-                       } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
-                               u64 stripes;
-                               int j;
-                               int factor = map->num_stripes /
-                                            map->sub_stripes;
-                               u32 last_stripe = 0;
-
-                               div_u64_rem(stripe_nr_end - 1,
-                                           factor, &last_stripe);
-                               last_stripe *= map->sub_stripes;
-
-                               for (j = 0; j < factor; j++) {
-                                       u32 test;
-
-                                       div_u64_rem(stripe_nr_end - 1 - j,
-                                                   factor, &test);
-
-                                       if (test ==
-                                           stripe_index / map->sub_stripes)
-                                               break;
-                               }
-                               stripes = stripe_nr_end - 1 - j;
-                               do_div(stripes, factor);
-                               bbio->stripes[i].length = map->stripe_len *
-                                       (stripes - stripe_nr + 1);
-
-                               if (i < map->sub_stripes) {
+                       if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
+                                        BTRFS_BLOCK_GROUP_RAID10)) {
+                               bbio->stripes[i].length = stripes_per_dev *
+                                                         map->stripe_len;
+                               if (i / sub_stripes < remaining_stripes)
+                                       bbio->stripes[i].length +=
+                                               map->stripe_len;
+                               if (i < sub_stripes)
                                        bbio->stripes[i].length -=
                                                stripe_offset;
-                                       if (i == map->sub_stripes - 1)
-                                               stripe_offset = 0;
-                               }
-                               if (stripe_index >= last_stripe &&
-                                   stripe_index <= (last_stripe +
-                                                    map->sub_stripes - 1)) {
+                               if ((i / sub_stripes + 1) %
+                                   sub_stripes == remaining_stripes)
                                        bbio->stripes[i].length -=
                                                stripe_end_offset;
-                               }
+                               if (i == sub_stripes - 1)
+                                       stripe_offset = 0;
                        } else
                                bbio->stripes[i].length = *length;
 
@@ -3155,15 +3806,22 @@ again:
                        stripe_index++;
                }
        }
-       if (bbio_ret) {
-               *bbio_ret = bbio;
-               bbio->num_stripes = num_stripes;
-               bbio->max_errors = max_errors;
-               bbio->mirror_num = mirror_num;
+
+       if (rw & REQ_WRITE) {
+               if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
+                                BTRFS_BLOCK_GROUP_RAID10 |
+                                BTRFS_BLOCK_GROUP_DUP)) {
+                       max_errors = 1;
+               }
        }
+
+       *bbio_ret = bbio;
+       bbio->num_stripes = num_stripes;
+       bbio->max_errors = max_errors;
+       bbio->mirror_num = mirror_num;
 out:
        free_extent_map(em);
-       return 0;
+       return ret;
 }
 
 int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
@@ -3304,7 +3962,7 @@ static noinline int schedule_bio(struct btrfs_root *root,
        /* don't bother with additional async steps for reads, right now */
        if (!(rw & REQ_WRITE)) {
                bio_get(bio);
-               submit_bio(rw, bio);
+               btrfsic_submit_bio(rw, bio);
                bio_put(bio);
                return 0;
        }
@@ -3399,7 +4057,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
                        if (async_submit)
                                schedule_bio(root, dev, rw, bio);
                        else
-                               submit_bio(rw, bio);
+                               btrfsic_submit_bio(rw, bio);
                } else {
                        bio->bi_bdev = root->fs_info->fs_devices->latest_bdev;
                        bio->bi_sector = logical >> 9;
@@ -3568,7 +4226,7 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
        struct btrfs_fs_devices *fs_devices;
        int ret;
 
-       mutex_lock(&uuid_mutex);
+       BUG_ON(!mutex_is_locked(&uuid_mutex));
 
        fs_devices = root->fs_info->fs_devices->seed;
        while (fs_devices) {
@@ -3606,7 +4264,6 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
        fs_devices->seed = root->fs_info->fs_devices->seed;
        root->fs_info->fs_devices->seed = fs_devices;
 out:
-       mutex_unlock(&uuid_mutex);
        return ret;
 }
 
@@ -3749,6 +4406,9 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
        if (!path)
                return -ENOMEM;
 
+       mutex_lock(&uuid_mutex);
+       lock_chunks(root);
+
        /* first we search for all of the device items, and then we
         * read in all of the chunk items.  This way we can create chunk
         * mappings that reference all of the devices that are afound
@@ -3799,6 +4459,9 @@ again:
        }
        ret = 0;
 error:
+       unlock_chunks(root);
+       mutex_unlock(&uuid_mutex);
+
        btrfs_free_path(path);
        return ret;
 }
index 78f2d4d4f37fe81317395688a8b090b71e53a612..19ac95048b88596e44b6dd667b050fb796ab20e7 100644 (file)
@@ -186,6 +186,51 @@ struct map_lookup {
 #define map_lookup_size(n) (sizeof(struct map_lookup) + \
                            (sizeof(struct btrfs_bio_stripe) * (n)))
 
+/*
+ * Restriper's general type filter
+ */
+#define BTRFS_BALANCE_DATA             (1ULL << 0)
+#define BTRFS_BALANCE_SYSTEM           (1ULL << 1)
+#define BTRFS_BALANCE_METADATA         (1ULL << 2)
+
+#define BTRFS_BALANCE_TYPE_MASK                (BTRFS_BALANCE_DATA |       \
+                                        BTRFS_BALANCE_SYSTEM |     \
+                                        BTRFS_BALANCE_METADATA)
+
+#define BTRFS_BALANCE_FORCE            (1ULL << 3)
+#define BTRFS_BALANCE_RESUME           (1ULL << 4)
+
+/*
+ * Balance filters
+ */
+#define BTRFS_BALANCE_ARGS_PROFILES    (1ULL << 0)
+#define BTRFS_BALANCE_ARGS_USAGE       (1ULL << 1)
+#define BTRFS_BALANCE_ARGS_DEVID       (1ULL << 2)
+#define BTRFS_BALANCE_ARGS_DRANGE      (1ULL << 3)
+#define BTRFS_BALANCE_ARGS_VRANGE      (1ULL << 4)
+
+/*
+ * Profile changing flags.  When SOFT is set we won't relocate chunk if
+ * it already has the target profile (even though it may be
+ * half-filled).
+ */
+#define BTRFS_BALANCE_ARGS_CONVERT     (1ULL << 8)
+#define BTRFS_BALANCE_ARGS_SOFT                (1ULL << 9)
+
+struct btrfs_balance_args;
+struct btrfs_balance_progress;
+struct btrfs_balance_control {
+       struct btrfs_fs_info *fs_info;
+
+       struct btrfs_balance_args data;
+       struct btrfs_balance_args meta;
+       struct btrfs_balance_args sys;
+
+       u64 flags;
+
+       struct btrfs_balance_progress stat;
+};
+
 int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
                                   u64 end, u64 *length);
 
@@ -228,9 +273,12 @@ struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid,
                                       u8 *uuid, u8 *fsid);
 int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
 int btrfs_init_new_device(struct btrfs_root *root, char *path);
-int btrfs_balance(struct btrfs_root *dev_root);
+int btrfs_balance(struct btrfs_balance_control *bctl,
+                 struct btrfs_ioctl_balance_args *bargs);
+int btrfs_recover_balance(struct btrfs_root *tree_root);
+int btrfs_pause_balance(struct btrfs_fs_info *fs_info);
+int btrfs_cancel_balance(struct btrfs_fs_info *fs_info);
 int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
-int find_free_dev_extent(struct btrfs_trans_handle *trans,
-                        struct btrfs_device *device, u64 num_bytes,
+int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
                         u64 *start, u64 *max_avail);
 #endif
index 3848b04e310e4800f6768160c6ef5111734ad1d5..e7a5659087e66f93769bc750562d21294c9bd2b6 100644 (file)
@@ -200,7 +200,7 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans,
        ret = btrfs_update_inode(trans, root, inode);
        BUG_ON(ret);
 out:
-       btrfs_end_transaction_throttle(trans, root);
+       btrfs_end_transaction(trans, root);
        return ret;
 }
 
index b60fc8bfb3e9fdb71ffd1e7ded00ea2154958900..620daad201dbc8905f09359b8237a542be1f311e 100644 (file)
@@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap)
        unsigned long ttl;
        u32 gen;
 
-       spin_lock(&cap->session->s_cap_lock);
+       spin_lock(&cap->session->s_gen_ttl_lock);
        gen = cap->session->s_cap_gen;
        ttl = cap->session->s_cap_ttl;
-       spin_unlock(&cap->session->s_cap_lock);
+       spin_unlock(&cap->session->s_gen_ttl_lock);
 
        if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {
                dout("__cap_is_valid %p cap %p issued %s "
index 618246bc2196eee020f6c53ccf789d784603e090..3e8094be4604a481999e2921fb0942441c9086a7 100644 (file)
@@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry)
        di = ceph_dentry(dentry);
        if (di->lease_session) {
                s = di->lease_session;
-               spin_lock(&s->s_cap_lock);
+               spin_lock(&s->s_gen_ttl_lock);
                gen = s->s_cap_gen;
                ttl = s->s_cap_ttl;
-               spin_unlock(&s->s_cap_lock);
+               spin_unlock(&s->s_gen_ttl_lock);
 
                if (di->lease_gen == gen &&
                    time_before(jiffies, dentry->d_time) &&
index 23ab6a3f1825e85cb839f508535a56cdc0cc55fe..866e8d7ca37d7343fe7c30cc5e036cb5d6b9494e 100644 (file)
@@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg,
        /* trace */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
+               ceph_decode_need(&p, end, len, bad);
                err = parse_reply_info_trace(&p, p+len, info, features);
                if (err < 0)
                        goto out_bad;
@@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg,
        /* extra */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
+               ceph_decode_need(&p, end, len, bad);
                err = parse_reply_info_extra(&p, p+len, info, features);
                if (err < 0)
                        goto out_bad;
@@ -398,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
        s->s_con.peer_name.num = cpu_to_le64(mds);
 
-       spin_lock_init(&s->s_cap_lock);
+       spin_lock_init(&s->s_gen_ttl_lock);
        s->s_cap_gen = 0;
        s->s_cap_ttl = 0;
+
+       spin_lock_init(&s->s_cap_lock);
        s->s_renew_requested = 0;
        s->s_renew_seq = 0;
        INIT_LIST_HEAD(&s->s_caps);
@@ -2326,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session,
        case CEPH_SESSION_STALE:
                pr_info("mds%d caps went stale, renewing\n",
                        session->s_mds);
-               spin_lock(&session->s_cap_lock);
+               spin_lock(&session->s_gen_ttl_lock);
                session->s_cap_gen++;
                session->s_cap_ttl = 0;
-               spin_unlock(&session->s_cap_lock);
+               spin_unlock(&session->s_gen_ttl_lock);
                send_renew_caps(mdsc, session);
                break;
 
index a50ca0e39475794018c2350570547bff4f6a7df8..8c7c04ebb595a1a8bd2e9c1b177890f8ba234b9a 100644 (file)
@@ -117,10 +117,13 @@ struct ceph_mds_session {
        void             *s_authorizer_buf, *s_authorizer_reply_buf;
        size_t            s_authorizer_buf_len, s_authorizer_reply_buf_len;
 
-       /* protected by s_cap_lock */
-       spinlock_t        s_cap_lock;
+       /* protected by s_gen_ttl_lock */
+       spinlock_t        s_gen_ttl_lock;
        u32               s_cap_gen;  /* inc each time we get mds stale msg */
        unsigned long     s_cap_ttl;  /* when session caps expire */
+
+       /* protected by s_cap_lock */
+       spinlock_t        s_cap_lock;
        struct list_head  s_caps;     /* all caps issued by this session */
        int               s_nr_caps, s_trim_caps;
        int               s_num_cap_releases;
index 857214ae8c0893181c85c6fb081ef13ae171f0e7..a76f697303d9e5db700598fc817008494908bb99 100644 (file)
@@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
 }
 
 static struct ceph_vxattr_cb ceph_file_vxattrs[] = {
+       { true, "ceph.file.layout", ceph_vxattrcb_layout},
+       /* The following extended attribute name is deprecated */
        { true, "ceph.layout", ceph_vxattrcb_layout},
-       { NULL, NULL }
+       { true, NULL, NULL }
 };
 
 static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode)
index f66cc1625150839244870bb6bbb3d27893b7ec82..2b243af70aa325b3c6049ded6121473f98cfbe8e 100644 (file)
@@ -139,8 +139,7 @@ config CIFS_DFS_UPCALL
            points. If unsure, say N.
 
 config CIFS_FSCACHE
-         bool "Provide CIFS client caching support (EXPERIMENTAL)"
-         depends on EXPERIMENTAL
+         bool "Provide CIFS client caching support"
          depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
          help
            Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
@@ -148,8 +147,8 @@ config CIFS_FSCACHE
            manager. If unsure, say N.
 
 config CIFS_ACL
-         bool "Provide CIFS ACL support (EXPERIMENTAL)"
-         depends on EXPERIMENTAL && CIFS_XATTR && KEYS
+         bool "Provide CIFS ACL support"
+         depends on CIFS_XATTR && KEYS
          help
            Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob
            is handed over to the application/caller.
index 84e8c0724704173669659f899e7cc83c6741b857..24b3dfc05282e2214df5f3eb014eb124651d6ffe 100644 (file)
@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
 {
        char c;
        int rc;
+       static bool warned;
 
        rc = get_user(c, buffer);
        if (rc)
                return rc;
        if (c == '0' || c == 'n' || c == 'N')
                multiuser_mount = 0;
-       else if (c == '1' || c == 'y' || c == 'Y')
+       else if (c == '1' || c == 'y' || c == 'Y') {
                multiuser_mount = 1;
+               if (!warned) {
+                       warned = true;
+                       printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
+                               "mount code is scheduled to be deprecated in "
+                               "3.5. Please switch to using the multiuser "
+                               "mount option.");
+               }
+       }
 
        return count;
 }
index 2272fd5fe5b74fcac62d001987ce3980a8a0b3e0..e622863b292f736fc8cc6e5d2ab8105986ad83bf 100644 (file)
@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
                   MAX_MECH_STR_LEN +
                   UID_KEY_LEN + (sizeof(uid_t) * 2) +
                   CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
-                  USER_KEY_LEN + strlen(sesInfo->user_name) +
                   PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
 
+       if (sesInfo->user_name)
+               desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
+
        spnego_key = ERR_PTR(-ENOMEM);
        description = kzalloc(desc_len, GFP_KERNEL);
        if (description == NULL)
@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
        dp = description + strlen(description);
        sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
 
-       dp = description + strlen(description);
-       sprintf(dp, ";user=%s", sesInfo->user_name);
+       if (sesInfo->user_name) {
+               dp = description + strlen(description);
+               sprintf(dp, ";user=%s", sesInfo->user_name);
+       }
 
        dp = description + strlen(description);
        sprintf(dp, ";pid=0x%x", current->pid);
index 1b2e180b018dd01e9d65041c6eb8cc288974b2c3..fbb9da95184379bcec53499a7fcac55ff6078f17 100644 (file)
 #include "cifs_debug.h"
 
 /*
- * cifs_ucs2_bytes - how long will a string be after conversion?
- * @ucs - pointer to input string
+ * cifs_utf16_bytes - how long will a string be after conversion?
+ * @utf16 - pointer to input string
  * @maxbytes - don't go past this many bytes of input string
  * @codepage - destination codepage
  *
- * Walk a ucs2le string and return the number of bytes that the string will
+ * Walk a utf16le string and return the number of bytes that the string will
  * be after being converted to the given charset, not including any null
  * termination required. Don't walk past maxbytes in the source buffer.
  */
 int
-cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+cifs_utf16_bytes(const __le16 *from, int maxbytes,
                const struct nls_table *codepage)
 {
        int i;
@@ -122,7 +122,7 @@ cp_convert:
 }
 
 /*
- * cifs_from_ucs2 - convert utf16le string to local charset
+ * cifs_from_utf16 - convert utf16le string to local charset
  * @to - destination buffer
  * @from - source buffer
  * @tolen - destination buffer size (in bytes)
@@ -130,7 +130,7 @@ cp_convert:
  * @codepage - codepage to which characters should be converted
  * @mapchar - should characters be remapped according to the mapchars option?
  *
- * Convert a little-endian ucs2le string (as sent by the server) to a string
+ * Convert a little-endian utf16le string (as sent by the server) to a string
  * in the provided codepage. The tolen and fromlen parameters are to ensure
  * that the code doesn't walk off of the end of the buffer (which is always
  * a danger if the alignment of the source buffer is off). The destination
@@ -139,12 +139,12 @@ cp_convert:
  * null terminator).
  *
  * Note that some windows versions actually send multiword UTF-16 characters
- * instead of straight UCS-2. The linux nls routines however aren't able to
+ * instead of straight UTF16-2. The linux nls routines however aren't able to
  * deal with those characters properly. In the event that we get some of
  * those characters, they won't be translated properly.
  */
 int
-cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
                 const struct nls_table *codepage, bool mapchar)
 {
        int i, charlen, safelen;
@@ -190,13 +190,13 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
 }
 
 /*
- * NAME:       cifs_strtoUCS()
+ * NAME:       cifs_strtoUTF16()
  *
  * FUNCTION:   Convert character string to unicode string
  *
  */
 int
-cifs_strtoUCS(__le16 *to, const char *from, int len,
+cifs_strtoUTF16(__le16 *to, const char *from, int len,
              const struct nls_table *codepage)
 {
        int charlen;
@@ -206,7 +206,7 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
        for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
                charlen = codepage->char2uni(from, len, &wchar_to);
                if (charlen < 1) {
-                       cERROR(1, "strtoUCS: char2uni of 0x%x returned %d",
+                       cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d",
                                *from, charlen);
                        /* A question mark */
                        wchar_to = 0x003f;
@@ -220,7 +220,8 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
 }
 
 /*
- * cifs_strndup_from_ucs - copy a string from wire format to the local codepage
+ * cifs_strndup_from_utf16 - copy a string from wire format to the local
+ * codepage
  * @src - source string
  * @maxlen - don't walk past this many bytes in the source string
  * @is_unicode - is this a unicode string?
@@ -231,19 +232,19 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
  * error.
  */
 char *
-cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
-            const struct nls_table *codepage)
+cifs_strndup_from_utf16(const char *src, const int maxlen,
+                       const bool is_unicode, const struct nls_table *codepage)
 {
        int len;
        char *dst;
 
        if (is_unicode) {
-               len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
+               len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
                len += nls_nullsize(codepage);
                dst = kmalloc(len, GFP_KERNEL);
                if (!dst)
                        return NULL;
-               cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
+               cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
                               false);
        } else {
                len = strnlen(src, maxlen);
@@ -264,7 +265,7 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
  * names are little endian 16 bit Unicode on the wire
  */
 int
-cifsConvertToUCS(__le16 *target, const char *source, int srclen,
+cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
                 const struct nls_table *cp, int mapChars)
 {
        int i, j, charlen;
@@ -273,7 +274,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
        wchar_t tmp;
 
        if (!mapChars)
-               return cifs_strtoUCS(target, source, PATH_MAX, cp);
+               return cifs_strtoUTF16(target, source, PATH_MAX, cp);
 
        for (i = 0, j = 0; i < srclen; j++) {
                src_char = source[i];
@@ -281,7 +282,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
                switch (src_char) {
                case 0:
                        put_unaligned(0, &target[j]);
-                       goto ctoUCS_out;
+                       goto ctoUTF16_out;
                case ':':
                        dst_char = cpu_to_le16(UNI_COLON);
                        break;
@@ -326,7 +327,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
                put_unaligned(dst_char, &target[j]);
        }
 
-ctoUCS_out:
+ctoUTF16_out:
        return i;
 }
 
index 6d02fd560566b8184f004f9087dd7ea48ef590d7..a513a546700b5e1a9be653b77316b9487d04cde0 100644 (file)
@@ -74,16 +74,16 @@ extern const struct UniCaseRange CifsUniLowerRange[];
 #endif                         /* UNIUPR_NOLOWER */
 
 #ifdef __KERNEL__
-int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
-                  const struct nls_table *codepage, bool mapchar);
-int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
-                   const struct nls_table *codepage);
-int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
-char *cifs_strndup_from_ucs(const char *src, const int maxlen,
-                           const bool is_unicode,
-                           const struct nls_table *codepage);
-extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
-                       const struct nls_table *cp, int mapChars);
+int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
+                   const struct nls_table *codepage, bool mapchar);
+int cifs_utf16_bytes(const __le16 *from, int maxbytes,
+                    const struct nls_table *codepage);
+int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup_from_utf16(const char *src, const int maxlen,
+                             const bool is_unicode,
+                             const struct nls_table *codepage);
+extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
+                             const struct nls_table *cp, int mapChars);
 
 #endif
 
index 72ddf23ef6f7d77145dbe765732633ff8e588076..c1b254487388ab3a23ce4af9d1226e84a7ead901 100644 (file)
@@ -909,6 +909,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
                umode_t group_mask = S_IRWXG;
                umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
 
+               if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
+                       return;
                ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
                                GFP_KERNEL);
                if (!ppace) {
index 5d9b9acc5fcebd1b9c9eff1ab3458acc19fbc72b..63c460e503b601b6bd71ee8185849e82aa04f1dd 100644 (file)
@@ -327,7 +327,7 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
        attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
        attrptr->length = cpu_to_le16(2 * dlen);
        blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
-       cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+       cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
 
        return 0;
 }
@@ -376,7 +376,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
                                        kmalloc(attrsize + 1, GFP_KERNEL);
                                if (!ses->domainName)
                                                return -ENOMEM;
-                               cifs_from_ucs2(ses->domainName,
+                               cifs_from_utf16(ses->domainName,
                                        (__le16 *)blobptr, attrsize, attrsize,
                                        nls_cp, false);
                                break;
@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
        }
 
        /* convert ses->user_name to unicode and uppercase */
-       len = strlen(ses->user_name);
+       len = ses->user_name ? strlen(ses->user_name) : 0;
        user = kmalloc(2 + (len * 2), GFP_KERNEL);
        if (user == NULL) {
                cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
                rc = -ENOMEM;
                return rc;
        }
-       len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
-       UniStrupr(user);
+
+       if (len) {
+               len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp);
+               UniStrupr(user);
+       } else {
+               memset(user, '\0', 2);
+       }
 
        rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                                (char *)user, 2 * len);
@@ -448,8 +453,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                        rc = -ENOMEM;
                        return rc;
                }
-               len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
-                                       nls_cp);
+               len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
+                                     nls_cp);
                rc =
                crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
                                        (char *)domain, 2 * len);
@@ -468,7 +473,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                        rc = -ENOMEM;
                        return rc;
                }
-               len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
+               len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
                                        nls_cp);
                rc =
                crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
index ba53c1c6c6cc091f045de3769d7fd8d295de8ce6..76e7d8b6da171c6af1d8cb8466c9bfbc77d00dbf 100644 (file)
@@ -879,6 +879,8 @@ require use of the stronger protocol */
 #define   CIFSSEC_MASK          0xB70B7 /* current flags supported if weak */
 #endif /* UPCALL */
 #else /* do not allow weak pw hash */
+#define   CIFSSEC_MUST_LANMAN  0
+#define   CIFSSEC_MUST_PLNTXT  0
 #ifdef CONFIG_CIFS_UPCALL
 #define   CIFSSEC_MASK          0x8F08F /* flags supported if no weak allowed */
 #else
index 6600aa2d2ef38a38c228a1cd26cbeae2ea2b6b06..8b7794c315919c5328a5bffbcb2aa5a9d7ad5b30 100644 (file)
@@ -821,8 +821,8 @@ PsxDelete:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else { /* BB add path length overrun check */
@@ -893,8 +893,8 @@ DelFileRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve check for buffer overruns BB */
@@ -938,8 +938,8 @@ RmDirRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
-                                        PATH_MAX, nls_codepage, remap);
+               name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
+                                             PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve check for buffer overruns BB */
@@ -981,8 +981,8 @@ MkDirRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
-                                           PATH_MAX, nls_codepage, remap);
+               name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
+                                             PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve check for buffer overruns BB */
@@ -1030,8 +1030,8 @@ PsxCreat:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, name,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -1197,8 +1197,8 @@ OldOpenRetry:
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                count = 1;      /* account for one byte pad to word boundary */
                name_len =
-                  cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
-                                   fileName, PATH_MAX, nls_codepage, remap);
+                  cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+                                     fileName, PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve check for buffer overruns BB */
@@ -1304,8 +1304,8 @@ openRetry:
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                count = 1;      /* account for one byte pad to word boundary */
                name_len =
-                   cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
-                                    fileName, PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+                                      fileName, PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->NameLength = cpu_to_le16(name_len);
@@ -2649,16 +2649,16 @@ renameRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->OldFileName[name_len] = 0x04;     /* pad */
        /* protocol requires ASCII signature byte on Unicode string */
                pSMB->OldFileName[name_len + 1] = 0x00;
                name_len2 =
-                   cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
-                                    toName, PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+                                      toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {        /* BB improve the check for buffer overruns BB */
@@ -2738,10 +2738,12 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
        /* unicode only call */
        if (target_name == NULL) {
                sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
-               len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+               len_of_str =
+                       cifsConvertToUTF16((__le16 *)rename_info->target_name,
                                        dummy_string, 24, nls_codepage, remap);
        } else {
-               len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+               len_of_str =
+                       cifsConvertToUTF16((__le16 *)rename_info->target_name,
                                        target_name, PATH_MAX, nls_codepage,
                                        remap);
        }
@@ -2795,17 +2797,17 @@ copyRetry:
        pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
-                                           fromName, PATH_MAX, nls_codepage,
-                                           remap);
+               name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
+                                             fromName, PATH_MAX, nls_codepage,
+                                             remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->OldFileName[name_len] = 0x04;     /* pad */
                /* protocol requires ASCII signature byte on Unicode string */
                pSMB->OldFileName[name_len + 1] = 0x00;
                name_len2 =
-                   cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
-                               toName, PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+                                      toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {        /* BB improve the check for buffer overruns BB */
@@ -2861,9 +2863,9 @@ createSymLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
+                                   /* find define for this maxpathcomponent */
+                                   PATH_MAX, nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
 
@@ -2885,9 +2887,9 @@ createSymLinkRetry:
        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len_target =
-                   cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
+                                   /* find define for this maxpathcomponent */
+                                   , nls_codepage);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -2949,8 +2951,8 @@ createHardLinkRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
-                                           PATH_MAX, nls_codepage, remap);
+               name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
+                                             PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
 
@@ -2972,8 +2974,8 @@ createHardLinkRetry:
        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len_target =
-                   cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
-                                    nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) data_offset, fromName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -3042,8 +3044,8 @@ winCreateHardLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
 
@@ -3051,8 +3053,8 @@ winCreateHardLinkRetry:
                pSMB->OldFileName[name_len] = 0x04;
                pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
                name_len2 =
-                   cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
-                                    toName, PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+                                      toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {        /* BB improve the check for buffer overruns BB */
@@ -3108,8 +3110,8 @@ querySymLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
-                                 PATH_MAX, nls_codepage);
+                       cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
+                                       PATH_MAX, nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -3166,8 +3168,8 @@ querySymLinkRetry:
                                is_unicode = false;
 
                        /* BB FIXME investigate remapping reserved chars here */
-                       *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
-                                                   is_unicode, nls_codepage);
+                       *symlinkinfo = cifs_strndup_from_utf16(data_start,
+                                       count, is_unicode, nls_codepage);
                        if (!*symlinkinfo)
                                rc = -ENOMEM;
                }
@@ -3450,8 +3452,9 @@ queryAclRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                        PATH_MAX, nls_codepage, remap);
+                       cifsConvertToUTF16((__le16 *) pSMB->FileName,
+                                          searchName, PATH_MAX, nls_codepage,
+                                          remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->FileName[name_len] = 0;
@@ -3537,8 +3540,8 @@ setAclRetry:
                return rc;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-                                     PATH_MAX, nls_codepage, remap);
+                       cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+                                          PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -3948,8 +3951,9 @@ QInfRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                       PATH_MAX, nls_codepage, remap);
+                       cifsConvertToUTF16((__le16 *) pSMB->FileName,
+                                          searchName, PATH_MAX, nls_codepage,
+                                          remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {
@@ -4086,8 +4090,8 @@ QPathInfoRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -4255,8 +4259,8 @@ UnixQPathInfoRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                 PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -4344,8 +4348,8 @@ findFirstRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+                                      PATH_MAX, nls_codepage, remap);
                /* We can not add the asterik earlier in case
                it got remapped to 0xF03A as if it were part of the
                directory name instead of a wildcard */
@@ -4656,8 +4660,9 @@ GetInodeNumberRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                        PATH_MAX, nls_codepage, remap);
+                       cifsConvertToUTF16((__le16 *) pSMB->FileName,
+                                          searchName, PATH_MAX, nls_codepage,
+                                          remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -4794,9 +4799,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
                                rc = -ENOMEM;
                                goto parse_DFS_referrals_exit;
                        }
-                       cifsConvertToUCS((__le16 *) tmp, searchName,
-                                       PATH_MAX, nls_codepage, remap);
-                       node->path_consumed = cifs_ucs2_bytes(tmp,
+                       cifsConvertToUTF16((__le16 *) tmp, searchName,
+                                          PATH_MAX, nls_codepage, remap);
+                       node->path_consumed = cifs_utf16_bytes(tmp,
                                        le16_to_cpu(pSMBr->PathConsumed),
                                        nls_codepage);
                        kfree(tmp);
@@ -4809,8 +4814,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
                /* copy DfsPath */
                temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
                max_len = data_end - temp;
-               node->path_name = cifs_strndup_from_ucs(temp, max_len,
-                                                     is_unicode, nls_codepage);
+               node->path_name = cifs_strndup_from_utf16(temp, max_len,
+                                               is_unicode, nls_codepage);
                if (!node->path_name) {
                        rc = -ENOMEM;
                        goto parse_DFS_referrals_exit;
@@ -4819,8 +4824,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
                /* copy link target UNC */
                temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
                max_len = data_end - temp;
-               node->node_name = cifs_strndup_from_ucs(temp, max_len,
-                                                     is_unicode, nls_codepage);
+               node->node_name = cifs_strndup_from_utf16(temp, max_len,
+                                               is_unicode, nls_codepage);
                if (!node->node_name)
                        rc = -ENOMEM;
        }
@@ -4873,8 +4878,9 @@ getDFSRetry:
        if (ses->capabilities & CAP_UNICODE) {
                pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
-                                    searchName, PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
+                                      searchName, PATH_MAX, nls_codepage,
+                                      remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -5506,8 +5512,8 @@ SetEOFRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -5796,8 +5802,8 @@ SetTimesRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -5877,8 +5883,8 @@ SetAttrLgcyRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       ConvertToUCS((__le16 *) pSMB->fileName, fileName,
-                               PATH_MAX, nls_codepage);
+                       ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
+                                      PATH_MAX, nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -6030,8 +6036,8 @@ setPermsRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -6123,8 +6129,8 @@ QAllEAsRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                list_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+                                      PATH_MAX, nls_codepage, remap);
                list_len++;     /* trailing null */
                list_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -6301,8 +6307,8 @@ SetEARetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-                                    PATH_MAX, nls_codepage, remap);
+                   cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+                                      PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
index 4666780f315d22e1674abce6db61288871c9ad47..602f77c304c90fc402c9ec221eff2b78be818081 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/processor.h>
 #include <linux/inet.h>
 #include <linux/module.h>
+#include <keys/user-type.h>
 #include <net/ipv6.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB)
 
 static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
 {
-       struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
+       struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond;
        struct smb_t2_rsp *pSMBt  = (struct smb_t2_rsp *)pTargetSMB;
-       char *data_area_of_target;
-       char *data_area_of_buf2;
+       char *data_area_of_tgt;
+       char *data_area_of_src;
        int remaining;
-       unsigned int byte_count, total_in_buf;
-       __u16 total_data_size, total_in_buf2;
+       unsigned int byte_count, total_in_tgt;
+       __u16 tgt_total_cnt, src_total_cnt, total_in_src;
 
-       total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+       src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
+       tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
 
-       if (total_data_size !=
-           get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount))
-               cFYI(1, "total data size of primary and secondary t2 differ");
+       if (tgt_total_cnt != src_total_cnt)
+               cFYI(1, "total data count of primary and secondary t2 differ "
+                       "source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
 
-       total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+       total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
 
-       remaining = total_data_size - total_in_buf;
+       remaining = tgt_total_cnt - total_in_tgt;
 
-       if (remaining < 0)
+       if (remaining < 0) {
+               cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
+                       "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
                return -EPROTO;
+       }
 
-       if (remaining == 0) /* nothing to do, ignore */
+       if (remaining == 0) {
+               /* nothing to do, ignore */
+               cFYI(1, "no more data remains");
                return 0;
+       }
 
-       total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount);
-       if (remaining < total_in_buf2) {
+       total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
+       if (remaining < total_in_src)
                cFYI(1, "transact2 2nd response contains too much data");
-       }
 
        /* find end of first SMB data area */
-       data_area_of_target = (char *)&pSMBt->hdr.Protocol +
+       data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
                                get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
-       /* validate target area */
 
-       data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol +
-                               get_unaligned_le16(&pSMB2->t2_rsp.DataOffset);
+       /* validate target area */
+       data_area_of_src = (char *)&pSMBs->hdr.Protocol +
+                               get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
 
-       data_area_of_target += total_in_buf;
+       data_area_of_tgt += total_in_tgt;
 
-       /* copy second buffer into end of first buffer */
-       total_in_buf += total_in_buf2;
+       total_in_tgt += total_in_src;
        /* is the result too big for the field? */
-       if (total_in_buf > USHRT_MAX)
+       if (total_in_tgt > USHRT_MAX) {
+               cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
                return -EPROTO;
-       put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
+       }
+       put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
 
        /* fix up the BCC */
        byte_count = get_bcc(pTargetSMB);
-       byte_count += total_in_buf2;
+       byte_count += total_in_src;
        /* is the result too big for the field? */
-       if (byte_count > USHRT_MAX)
+       if (byte_count > USHRT_MAX) {
+               cFYI(1, "coalesced BCC too large (%u)", byte_count);
                return -EPROTO;
+       }
        put_bcc(byte_count, pTargetSMB);
 
        byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
-       byte_count += total_in_buf2;
+       byte_count += total_in_src;
        /* don't allow buffer to overflow */
-       if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
+       if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+               cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
                return -ENOBUFS;
+       }
        pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
 
-       memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
+       /* copy second buffer into end of first buffer */
+       memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
 
-       if (remaining == total_in_buf2) {
-               cFYI(1, "found the last secondary response");
-               return 0; /* we are done */
-       } else /* more responses to go */
+       if (remaining != total_in_src) {
+               /* more responses to go */
+               cFYI(1, "waiting for more secondary responses");
                return 1;
+       }
+
+       /* we are done */
+       cFYI(1, "found the last secondary response");
+       return 0;
 }
 
 static void
@@ -756,10 +773,11 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                cifs_dump_mem("Bad SMB: ", buf,
                        min_t(unsigned int, server->total_read, 48));
 
-       if (mid)
-               handle_mid(mid, server, smb_buffer, length);
+       if (!mid)
+               return length;
 
-       return length;
+       handle_mid(mid, server, smb_buffer, length);
+       return 0;
 }
 
 static int
@@ -1578,11 +1596,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                }
        }
 
-       if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
-               cERROR(1, "Multiuser mounts currently require krb5 "
-                         "authentication!");
+#ifndef CONFIG_KEYS
+       /* Muliuser mounts require CONFIG_KEYS support */
+       if (vol->multiuser) {
+               cERROR(1, "Multiuser mounts require kernels with "
+                         "CONFIG_KEYS enabled.");
                goto cifs_parse_mount_err;
        }
+#endif
 
        if (vol->UNCip == NULL)
                vol->UNCip = &vol->UNC[2];
@@ -1981,10 +2002,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
                        return 0;
                break;
        default:
+               /* NULL username means anonymous session */
+               if (ses->user_name == NULL) {
+                       if (!vol->nullauth)
+                               return 0;
+                       break;
+               }
+
                /* anything else takes username/password */
-               if (ses->user_name == NULL)
-                       return 0;
-               if (strncmp(ses->user_name, vol->username,
+               if (strncmp(ses->user_name,
+                           vol->username ? vol->username : "",
                            MAX_USERNAME_SIZE))
                        return 0;
                if (strlen(vol->username) != 0 &&
@@ -2039,6 +2066,132 @@ cifs_put_smb_ses(struct cifs_ses *ses)
        cifs_put_tcp_session(server);
 }
 
+#ifdef CONFIG_KEYS
+
+/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
+
+/* Populate username and pw fields from keyring if possible */
+static int
+cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
+{
+       int rc = 0;
+       char *desc, *delim, *payload;
+       ssize_t len;
+       struct key *key;
+       struct TCP_Server_Info *server = ses->server;
+       struct sockaddr_in *sa;
+       struct sockaddr_in6 *sa6;
+       struct user_key_payload *upayload;
+
+       desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       /* try to find an address key first */
+       switch (server->dstaddr.ss_family) {
+       case AF_INET:
+               sa = (struct sockaddr_in *)&server->dstaddr;
+               sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
+               break;
+       case AF_INET6:
+               sa6 = (struct sockaddr_in6 *)&server->dstaddr;
+               sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
+               break;
+       default:
+               cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
+               rc = -EINVAL;
+               goto out_err;
+       }
+
+       cFYI(1, "%s: desc=%s", __func__, desc);
+       key = request_key(&key_type_logon, desc, "");
+       if (IS_ERR(key)) {
+               if (!ses->domainName) {
+                       cFYI(1, "domainName is NULL");
+                       rc = PTR_ERR(key);
+                       goto out_err;
+               }
+
+               /* didn't work, try to find a domain key */
+               sprintf(desc, "cifs:d:%s", ses->domainName);
+               cFYI(1, "%s: desc=%s", __func__, desc);
+               key = request_key(&key_type_logon, desc, "");
+               if (IS_ERR(key)) {
+                       rc = PTR_ERR(key);
+                       goto out_err;
+               }
+       }
+
+       down_read(&key->sem);
+       upayload = key->payload.data;
+       if (IS_ERR_OR_NULL(upayload)) {
+               rc = upayload ? PTR_ERR(upayload) : -EINVAL;
+               goto out_key_put;
+       }
+
+       /* find first : in payload */
+       payload = (char *)upayload->data;
+       delim = strnchr(payload, upayload->datalen, ':');
+       cFYI(1, "payload=%s", payload);
+       if (!delim) {
+               cFYI(1, "Unable to find ':' in payload (datalen=%d)",
+                               upayload->datalen);
+               rc = -EINVAL;
+               goto out_key_put;
+       }
+
+       len = delim - payload;
+       if (len > MAX_USERNAME_SIZE || len <= 0) {
+               cFYI(1, "Bad value from username search (len=%zd)", len);
+               rc = -EINVAL;
+               goto out_key_put;
+       }
+
+       vol->username = kstrndup(payload, len, GFP_KERNEL);
+       if (!vol->username) {
+               cFYI(1, "Unable to allocate %zd bytes for username", len);
+               rc = -ENOMEM;
+               goto out_key_put;
+       }
+       cFYI(1, "%s: username=%s", __func__, vol->username);
+
+       len = key->datalen - (len + 1);
+       if (len > MAX_PASSWORD_SIZE || len <= 0) {
+               cFYI(1, "Bad len for password search (len=%zd)", len);
+               rc = -EINVAL;
+               kfree(vol->username);
+               vol->username = NULL;
+               goto out_key_put;
+       }
+
+       ++delim;
+       vol->password = kstrndup(delim, len, GFP_KERNEL);
+       if (!vol->password) {
+               cFYI(1, "Unable to allocate %zd bytes for password", len);
+               rc = -ENOMEM;
+               kfree(vol->username);
+               vol->username = NULL;
+               goto out_key_put;
+       }
+
+out_key_put:
+       up_read(&key->sem);
+       key_put(key);
+out_err:
+       kfree(desc);
+       cFYI(1, "%s: returning %d", __func__, rc);
+       return rc;
+}
+#else /* ! CONFIG_KEYS */
+static inline int
+cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
+                  struct cifs_ses *ses __attribute__((unused)))
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_KEYS */
+
 static bool warned_on_ntlm;  /* globals init to false automatically */
 
 static struct cifs_ses *
@@ -2914,18 +3067,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 #define CIFS_DEFAULT_IOSIZE (1024 * 1024)
 
 /*
- * Windows only supports a max of 60k reads. Default to that when posix
- * extensions aren't in force.
+ * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
+ * those values when posix extensions aren't in force. In actuality here, we
+ * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
+ * to be ok with the extra byte even though Windows doesn't send writes that
+ * are that large.
+ *
+ * Citation:
+ *
+ * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
  */
 #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
+#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
 
 static unsigned int
 cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
 {
        __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
        struct TCP_Server_Info *server = tcon->ses->server;
-       unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
-                               CIFS_DEFAULT_IOSIZE;
+       unsigned int wsize;
+
+       /* start with specified wsize, or default */
+       if (pvolume_info->wsize)
+               wsize = pvolume_info->wsize;
+       else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+               wsize = CIFS_DEFAULT_IOSIZE;
+       else
+               wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
 
        /* can server support 24-bit write sizes? (via UNIX extensions) */
        if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
@@ -3136,10 +3304,9 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
                return -EINVAL;
 
        if (volume_info->nullauth) {
-               cFYI(1, "null user");
-               volume_info->username = kzalloc(1, GFP_KERNEL);
-               if (volume_info->username == NULL)
-                       return -ENOMEM;
+               cFYI(1, "Anonymous login");
+               kfree(volume_info->username);
+               volume_info->username = NULL;
        } else if (volume_info->username) {
                /* BB fixme parse for domain name here */
                cFYI(1, "Username: %s", volume_info->username);
@@ -3478,7 +3645,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
                length =
-                   cifs_strtoUCS((__le16 *) bcc_ptr, tree,
+                   cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
                        6 /* max utf8 char length in bytes */ *
                        (/* server len*/ + 256 /* share len */), nls_codepage);
                bcc_ptr += 2 * length;  /* convert num 16 bit words to bytes */
@@ -3533,7 +3700,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
 
                /* mostly informational -- no need to fail on error here */
                kfree(tcon->nativeFileSystem);
-               tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
+               tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
                                                      bytes_left, is_unicode,
                                                      nls_codepage);
 
@@ -3657,25 +3824,43 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
        return rc;
 }
 
+static int
+cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
+{
+       switch (ses->server->secType) {
+       case Kerberos:
+               vol->secFlg = CIFSSEC_MUST_KRB5;
+               return 0;
+       case NTLMv2:
+               vol->secFlg = CIFSSEC_MUST_NTLMV2;
+               break;
+       case NTLM:
+               vol->secFlg = CIFSSEC_MUST_NTLM;
+               break;
+       case RawNTLMSSP:
+               vol->secFlg = CIFSSEC_MUST_NTLMSSP;
+               break;
+       case LANMAN:
+               vol->secFlg = CIFSSEC_MUST_LANMAN;
+               break;
+       }
+
+       return cifs_set_cifscreds(vol, ses);
+}
+
 static struct cifs_tcon *
 cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
 {
+       int rc;
        struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
        struct cifs_ses *ses;
        struct cifs_tcon *tcon = NULL;
        struct smb_vol *vol_info;
-       char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
-                          /* We used to have this as MAX_USERNAME which is   */
-                          /* way too big now (256 instead of 32) */
 
        vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
-       if (vol_info == NULL) {
-               tcon = ERR_PTR(-ENOMEM);
-               goto out;
-       }
+       if (vol_info == NULL)
+               return ERR_PTR(-ENOMEM);
 
-       snprintf(username, sizeof(username), "krb50x%x", fsuid);
-       vol_info->username = username;
        vol_info->local_nls = cifs_sb->local_nls;
        vol_info->linux_uid = fsuid;
        vol_info->cred_uid = fsuid;
@@ -3685,8 +3870,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
        vol_info->local_lease = master_tcon->local_lease;
        vol_info->no_linux_ext = !master_tcon->unix_ext;
 
-       /* FIXME: allow for other secFlg settings */
-       vol_info->secFlg = CIFSSEC_MUST_KRB5;
+       rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
+       if (rc) {
+               tcon = ERR_PTR(rc);
+               goto out;
+       }
 
        /* get a reference for the same TCP session */
        spin_lock(&cifs_tcp_ses_lock);
@@ -3709,6 +3897,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
        if (ses->capabilities & CAP_UNIX)
                reset_cifs_unix_caps(0, tcon, NULL, vol_info);
 out:
+       kfree(vol_info->username);
+       kfree(vol_info->password);
        kfree(vol_info);
 
        return tcon;
index df8fecb5b993316dfb5787098a3470eba8e3446c..63a196b97d5094a02e0f68b4fe5084051e7ad33a 100644 (file)
@@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 {
        int xid;
        int rc = 0; /* to get around spurious gcc warning, set to zero here */
-       __u32 oplock = 0;
+       __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
        __u16 fileHandle = 0;
        bool posix_open = false;
        struct cifs_sb_info *cifs_sb;
index a090bbe6ee29e196018867c9f5e4da3efe9d82b9..e2bbc683e0184a736509b7a41337b2fda401e4a3 100644 (file)
@@ -647,10 +647,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
 
                name.name = scratch_buf;
                name.len =
-                       cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
-                                      UNICODE_NAME_MAX,
-                                      min(de.namelen, (size_t)max_len), nlt,
-                                      cifs_sb->mnt_cifs_flags &
+                       cifs_from_utf16((char *)name.name, (__le16 *)de.name,
+                                       UNICODE_NAME_MAX,
+                                       min_t(size_t, de.namelen,
+                                             (size_t)max_len), nlt,
+                                       cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                name.len -= nls_nullsize(nlt);
        } else {
index 4ec3ee9d72ccc228b9fac929c23b80fc8f314fff..551d0c2b973699634bdd057d3eaf2e19d3b55b8a 100644 (file)
@@ -167,16 +167,16 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
        int bytes_ret = 0;
 
        /* Copy OS version */
-       bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
-                                 nls_cp);
+       bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
+                                   nls_cp);
        bcc_ptr += 2 * bytes_ret;
-       bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
-                                 32, nls_cp);
+       bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
+                                   32, nls_cp);
        bcc_ptr += 2 * bytes_ret;
        bcc_ptr += 2; /* trailing null */
 
-       bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
-                                 32, nls_cp);
+       bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+                                   32, nls_cp);
        bcc_ptr += 2 * bytes_ret;
        bcc_ptr += 2; /* trailing null */
 
@@ -197,8 +197,8 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
                *(bcc_ptr+1) = 0;
                bytes_ret = 0;
        } else
-               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
-                                         256, nls_cp);
+               bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
+                                           256, nls_cp);
        bcc_ptr += 2 * bytes_ret;
        bcc_ptr += 2;  /* account for null terminator */
 
@@ -226,8 +226,8 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
                *bcc_ptr = 0;
                *(bcc_ptr+1) = 0;
        } else {
-               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name,
-                                         MAX_USERNAME_SIZE, nls_cp);
+               bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
+                                           MAX_USERNAME_SIZE, nls_cp);
        }
        bcc_ptr += 2 * bytes_ret;
        bcc_ptr += 2; /* account for null termination */
@@ -246,16 +246,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
        /* copy user */
        /* BB what about null user mounts - check that we do this BB */
        /* copy user */
-       if (ses->user_name != NULL)
+       if (ses->user_name != NULL) {
                strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
+               bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
+       }
        /* else null user mount */
-
-       bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
        *bcc_ptr = 0;
        bcc_ptr++; /* account for null termination */
 
        /* copy domain */
-
        if (ses->domainName != NULL) {
                strncpy(bcc_ptr, ses->domainName, 256);
                bcc_ptr += strnlen(ses->domainName, 256);
@@ -287,7 +286,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
        cFYI(1, "bleft %d", bleft);
 
        kfree(ses->serverOS);
-       ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+       ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
        cFYI(1, "serverOS=%s", ses->serverOS);
        len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
        data += len;
@@ -296,7 +295,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
                return;
 
        kfree(ses->serverNOS);
-       ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+       ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
        cFYI(1, "serverNOS=%s", ses->serverNOS);
        len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
        data += len;
@@ -305,7 +304,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
                return;
 
        kfree(ses->serverDomain);
-       ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+       ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
        cFYI(1, "serverDomain=%s", ses->serverDomain);
 
        return;
@@ -395,6 +394,10 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
        ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
        tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
        tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
+       if (tioffset > blob_len || tioffset + tilen > blob_len) {
+               cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen);
+               return -EINVAL;
+       }
        if (tilen) {
                ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
                if (!ses->auth_key.response) {
@@ -502,8 +505,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
                tmp += 2;
        } else {
                int len;
-               len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
-                                   MAX_USERNAME_SIZE, nls_cp);
+               len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
+                                     MAX_USERNAME_SIZE, nls_cp);
                len *= 2; /* unicode is 2 bytes each */
                sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
                sec_blob->DomainName.Length = cpu_to_le16(len);
@@ -518,8 +521,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
                tmp += 2;
        } else {
                int len;
-               len = cifs_strtoUCS((__le16 *)tmp, ses->user_name,
-                                   MAX_USERNAME_SIZE, nls_cp);
+               len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
+                                     MAX_USERNAME_SIZE, nls_cp);
                len *= 2; /* unicode is 2 bytes each */
                sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
                sec_blob->UserName.Length = cpu_to_le16(len);
index 80d850881938d0c0950addc4d97ae4855dadfa4a..d5cd9aa7eacc1cc8f0413b401ae69cf7b959d690 100644 (file)
@@ -213,7 +213,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16,
 
        /* Password cannot be longer than 128 characters */
        if (passwd) /* Password must be converted to NT unicode */
-               len = cifs_strtoUCS(wpwd, passwd, 128, codepage);
+               len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
        else {
                len = 0;
                *wpwd = 0; /* Ensure string is null terminated */
index fa9d721ecfee57f8f3b4c2f3b37f2b4e52182ffc..07880bae28a9fa2128eb5df60c6193c39e099fb8 100644 (file)
@@ -131,41 +131,35 @@ asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_tim
 
 static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
 {
-       compat_ino_t ino = stat->ino;
-       typeof(ubuf->st_uid) uid = 0;
-       typeof(ubuf->st_gid) gid = 0;
-       int err;
+       struct compat_stat tmp;
 
-       SET_UID(uid, stat->uid);
-       SET_GID(gid, stat->gid);
+       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
+               return -EOVERFLOW;
 
-       if ((u64) stat->size > MAX_NON_LFS ||
-           !old_valid_dev(stat->dev) ||
-           !old_valid_dev(stat->rdev))
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.st_dev = old_encode_dev(stat->dev);
+       tmp.st_ino = stat->ino;
+       if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
                return -EOVERFLOW;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
+       tmp.st_mode = stat->mode;
+       tmp.st_nlink = stat->nlink;
+       if (tmp.st_nlink != stat->nlink)
                return -EOVERFLOW;
-
-       if (clear_user(ubuf, sizeof(*ubuf)))
-               return -EFAULT;
-
-       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
-       err |= __put_user(ino, &ubuf->st_ino);
-       err |= __put_user(stat->mode, &ubuf->st_mode);
-       err |= __put_user(stat->nlink, &ubuf->st_nlink);
-       err |= __put_user(uid, &ubuf->st_uid);
-       err |= __put_user(gid, &ubuf->st_gid);
-       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
-       err |= __put_user(stat->size, &ubuf->st_size);
-       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
-       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
-       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
-       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
-       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
-       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
-       err |= __put_user(stat->blksize, &ubuf->st_blksize);
-       err |= __put_user(stat->blocks, &ubuf->st_blocks);
-       return err;
+       SET_UID(tmp.st_uid, stat->uid);
+       SET_GID(tmp.st_gid, stat->gid);
+       tmp.st_rdev = old_encode_dev(stat->rdev);
+       if ((u64) stat->size > MAX_NON_LFS)
+               return -EOVERFLOW;
+       tmp.st_size = stat->size;
+       tmp.st_atime = stat->atime.tv_sec;
+       tmp.st_atime_nsec = stat->atime.tv_nsec;
+       tmp.st_mtime = stat->mtime.tv_sec;
+       tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+       tmp.st_ctime = stat->ctime.tv_sec;
+       tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+       tmp.st_blocks = stat->blocks;
+       tmp.st_blksize = stat->blksize;
+       return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage long compat_sys_newstat(const char __user * filename,
index 16a53cc2cc02e079554742bfcd95c1f92d3608d4..fe19ac13f75f5c4e65ed1afaecd1c5d1ae34ffb6 100644 (file)
@@ -2968,7 +2968,7 @@ __setup("dhash_entries=", set_dhash_entries);
 
 static void __init dcache_init_early(void)
 {
-       int loop;
+       unsigned int loop;
 
        /* If hashes are distributed across NUMA nodes, defer
         * hash allocation until vmalloc space is available.
@@ -2986,13 +2986,13 @@ static void __init dcache_init_early(void)
                                        &d_hash_mask,
                                        0);
 
-       for (loop = 0; loop < (1 << d_hash_shift); loop++)
+       for (loop = 0; loop < (1U << d_hash_shift); loop++)
                INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 static void __init dcache_init(void)
 {
-       int loop;
+       unsigned int loop;
 
        /* 
         * A constructor could be added for stable state like the lists,
@@ -3016,7 +3016,7 @@ static void __init dcache_init(void)
                                        &d_hash_mask,
                                        0);
 
-       for (loop = 0; loop < (1 << d_hash_shift); loop++)
+       for (loop = 0; loop < (1U << d_hash_shift); loop++)
                INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
index f65d4455c5e521dbde1a41407f740a2371848046..ef023eef0464c90e2619de6b7978b537270a54e9 100644 (file)
@@ -540,7 +540,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_blob);
  * debugfs_print_regs32 - use seq_print to describe a set of registers
  * @s: the seq_file structure being used to generate output
  * @regs: an array if struct debugfs_reg32 structures
- * @mregs: the length of the above array
+ * @nregs: the length of the above array
  * @base: the base address to be used in reading the registers
  * @prefix: a string to be prefixed to every output line
  *
index 2a834255c75de911b7e1f8eb10026972913e14b4..ea9931281557ad8d3ed4049b48c66110df5f0811 100644 (file)
@@ -417,17 +417,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
                        (unsigned long long)(extent_base + extent_offset), rc);
                goto out;
        }
-       if (unlikely(ecryptfs_verbosity > 0)) {
-               ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
-                               "with iv:\n");
-               ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
-               ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
-                               "encryption:\n");
-               ecryptfs_dump_hex((char *)
-                                 (page_address(page)
-                                  + (extent_offset * crypt_stat->extent_size)),
-                                 8);
-       }
        rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
                                          page, (extent_offset
                                                 * crypt_stat->extent_size),
@@ -440,14 +429,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
                goto out;
        }
        rc = 0;
-       if (unlikely(ecryptfs_verbosity > 0)) {
-               ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; "
-                       "rc = [%d]\n",
-                       (unsigned long long)(extent_base + extent_offset), rc);
-               ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
-                               "encryption:\n");
-               ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
-       }
 out:
        return rc;
 }
@@ -543,17 +524,6 @@ static int ecryptfs_decrypt_extent(struct page *page,
                        (unsigned long long)(extent_base + extent_offset), rc);
                goto out;
        }
-       if (unlikely(ecryptfs_verbosity > 0)) {
-               ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
-                               "with iv:\n");
-               ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
-               ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
-                               "decryption:\n");
-               ecryptfs_dump_hex((char *)
-                                 (page_address(enc_extent_page)
-                                  + (extent_offset * crypt_stat->extent_size)),
-                                 8);
-       }
        rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
                                          (extent_offset
                                           * crypt_stat->extent_size),
@@ -567,16 +537,6 @@ static int ecryptfs_decrypt_extent(struct page *page,
                goto out;
        }
        rc = 0;
-       if (unlikely(ecryptfs_verbosity > 0)) {
-               ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; "
-                       "rc = [%d]\n",
-                       (unsigned long long)(extent_base + extent_offset), rc);
-               ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
-                               "decryption:\n");
-               ecryptfs_dump_hex((char *)(page_address(page)
-                                          + (extent_offset
-                                             * crypt_stat->extent_size)), 8);
-       }
 out:
        return rc;
 }
@@ -1590,8 +1550,8 @@ int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry,
  */
 int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
 {
-       int rc = 0;
-       char *page_virt = NULL;
+       int rc;
+       char *page_virt;
        struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
        struct ecryptfs_crypt_stat *crypt_stat =
            &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
@@ -1616,11 +1576,13 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
                                                ecryptfs_dentry,
                                                ECRYPTFS_VALIDATE_HEADER_SIZE);
        if (rc) {
+               /* metadata is not in the file header, so try xattrs */
                memset(page_virt, 0, PAGE_CACHE_SIZE);
                rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
                if (rc) {
                        printk(KERN_DEBUG "Valid eCryptfs headers not found in "
-                              "file header region or xattr region\n");
+                              "file header region or xattr region, inode %lu\n",
+                               ecryptfs_inode->i_ino);
                        rc = -EINVAL;
                        goto out;
                }
@@ -1629,7 +1591,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
                                                ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
                if (rc) {
                        printk(KERN_DEBUG "Valid eCryptfs headers not found in "
-                              "file xattr region either\n");
+                              "file xattr region either, inode %lu\n",
+                               ecryptfs_inode->i_ino);
                        rc = -EINVAL;
                }
                if (crypt_stat->mount_crypt_stat->flags
@@ -1640,7 +1603,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
                               "crypto metadata only in the extended attribute "
                               "region, but eCryptfs was mounted without "
                               "xattr support enabled. eCryptfs will not treat "
-                              "this like an encrypted file.\n");
+                              "this like an encrypted file, inode %lu\n",
+                               ecryptfs_inode->i_ino);
                        rc = -EINVAL;
                }
        }
@@ -2026,6 +1990,17 @@ out:
        return;
 }
 
+static size_t ecryptfs_max_decoded_size(size_t encoded_size)
+{
+       /* Not exact; conservatively long. Every block of 4
+        * encoded characters decodes into a block of 3
+        * decoded characters. This segment of code provides
+        * the caller with the maximum amount of allocated
+        * space that @dst will need to point to in a
+        * subsequent call. */
+       return ((encoded_size + 1) * 3) / 4;
+}
+
 /**
  * ecryptfs_decode_from_filename
  * @dst: If NULL, this function only sets @dst_size and returns. If
@@ -2044,13 +2019,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
        size_t dst_byte_offset = 0;
 
        if (dst == NULL) {
-               /* Not exact; conservatively long. Every block of 4
-                * encoded characters decodes into a block of 3
-                * decoded characters. This segment of code provides
-                * the caller with the maximum amount of allocated
-                * space that @dst will need to point to in a
-                * subsequent call. */
-               (*dst_size) = (((src_size + 1) * 3) / 4);
+               (*dst_size) = ecryptfs_max_decoded_size(src_size);
                goto out;
        }
        while (src_byte_offset < src_size) {
@@ -2275,3 +2244,52 @@ out_free:
 out:
        return rc;
 }
+
+#define ENC_NAME_MAX_BLOCKLEN_8_OR_16  143
+
+int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
+                          struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+       struct blkcipher_desc desc;
+       struct mutex *tfm_mutex;
+       size_t cipher_blocksize;
+       int rc;
+
+       if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
+               (*namelen) = lower_namelen;
+               return 0;
+       }
+
+       rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex,
+                       mount_crypt_stat->global_default_fn_cipher_name);
+       if (unlikely(rc)) {
+               (*namelen) = 0;
+               return rc;
+       }
+
+       mutex_lock(tfm_mutex);
+       cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm);
+       mutex_unlock(tfm_mutex);
+
+       /* Return an exact amount for the common cases */
+       if (lower_namelen == NAME_MAX
+           && (cipher_blocksize == 8 || cipher_blocksize == 16)) {
+               (*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16;
+               return 0;
+       }
+
+       /* Return a safe estimate for the uncommon cases */
+       (*namelen) = lower_namelen;
+       (*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
+       /* Since this is the max decoded size, subtract 1 "decoded block" len */
+       (*namelen) = ecryptfs_max_decoded_size(*namelen) - 3;
+       (*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE;
+       (*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES;
+       /* Worst case is that the filename is padded nearly a full block size */
+       (*namelen) -= cipher_blocksize - 1;
+
+       if ((*namelen) < 0)
+               (*namelen) = 0;
+
+       return 0;
+}
index a9f29b12fbf290ba4987f778e582357d38ae1258..867b64c5d84f9f2892e182baa89c888224b99418 100644 (file)
@@ -151,12 +151,21 @@ ecryptfs_get_key_payload_data(struct key *key)
                                          * dentry name */
 #define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as
                                          * metadata */
+#define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */
+#define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to
+                                    * ecryptfs_parse_packet_length() and
+                                    * ecryptfs_write_packet_length()
+                                    */
 /* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >=
  * ECRYPTFS_MAX_IV_BYTES */
 #define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16
 #define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */
 #define MD5_DIGEST_SIZE 16
 #define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE
+#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \
+                                          + ECRYPTFS_SIG_SIZE + 1 + 1)
+#define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (1 + ECRYPTFS_MAX_PKT_LEN_SIZE \
+                                          + ECRYPTFS_SIG_SIZE + 1 + 1)
 #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED."
 #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23
 #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
@@ -696,6 +705,8 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
                             size_t *packet_size,
                             struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
                             char *data, size_t max_packet_size);
+int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
+                          struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
 int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
                       loff_t offset);
 
index 19a8ca4ab1ddc54bf4c8f389ef0dfcf8ce52a824..ab35b113003b900ad3592217d64e6cef82fe8f9d 100644 (file)
@@ -822,18 +822,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
                size_t num_zeros = (PAGE_CACHE_SIZE
                                    - (ia->ia_size & ~PAGE_CACHE_MASK));
 
-
-               /*
-                * XXX(truncate) this should really happen at the begginning
-                * of ->setattr.  But the code is too messy to that as part
-                * of a larger patch.  ecryptfs is also totally missing out
-                * on the inode_change_ok check at the beginning of
-                * ->setattr while would include this.
-                */
-               rc = inode_newsize_ok(inode, ia->ia_size);
-               if (rc)
-                       goto out;
-
                if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
                        truncate_setsize(inode, ia->ia_size);
                        lower_ia->ia_size = ia->ia_size;
@@ -883,6 +871,28 @@ out:
        return rc;
 }
 
+static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
+{
+       struct ecryptfs_crypt_stat *crypt_stat;
+       loff_t lower_oldsize, lower_newsize;
+
+       crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+       lower_oldsize = upper_size_to_lower_size(crypt_stat,
+                                                i_size_read(inode));
+       lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
+       if (lower_newsize > lower_oldsize) {
+               /*
+                * The eCryptfs inode and the new *lower* size are mixed here
+                * because we may not have the lower i_mutex held and/or it may
+                * not be appropriate to call inode_newsize_ok() with inodes
+                * from other filesystems.
+                */
+               return inode_newsize_ok(inode, lower_newsize);
+       }
+
+       return 0;
+}
+
 /**
  * ecryptfs_truncate
  * @dentry: The ecryptfs layer dentry
@@ -899,6 +909,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
        struct iattr lower_ia = { .ia_valid = 0 };
        int rc;
 
+       rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length);
+       if (rc)
+               return rc;
+
        rc = truncate_upper(dentry, &ia, &lower_ia);
        if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
                struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
@@ -978,6 +992,16 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
                }
        }
        mutex_unlock(&crypt_stat->cs_mutex);
+
+       rc = inode_change_ok(inode, ia);
+       if (rc)
+               goto out;
+       if (ia->ia_valid & ATTR_SIZE) {
+               rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
+               if (rc)
+                       goto out;
+       }
+
        if (S_ISREG(inode->i_mode)) {
                rc = filemap_write_and_wait(inode->i_mapping);
                if (rc)
@@ -1061,6 +1085,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        }
 
        rc = vfs_setxattr(lower_dentry, name, value, size, flags);
+       if (!rc)
+               fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode);
 out:
        return rc;
 }
index ac1ad48c2376df4b3061e55a973b27b42388f510..2333203a120b3b853f71ef011a0755a3be04fd6a 100644 (file)
@@ -109,7 +109,7 @@ int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
                (*size) += ((unsigned char)(data[1]) + 192);
                (*length_size) = 2;
        } else if (data[0] == 255) {
-               /* Five-byte length; we're not supposed to see this */
+               /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
                ecryptfs_printk(KERN_ERR, "Five-byte packet length not "
                                "supported\n");
                rc = -EINVAL;
@@ -126,7 +126,7 @@ out:
 /**
  * ecryptfs_write_packet_length
  * @dest: The byte array target into which to write the length. Must
- *        have at least 5 bytes allocated.
+ *        have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated.
  * @size: The length to write.
  * @packet_size_length: The number of bytes used to encode the packet
  *                      length is written to this address.
@@ -146,6 +146,7 @@ int ecryptfs_write_packet_length(char *dest, size_t size,
                dest[1] = ((size - 192) % 256);
                (*packet_size_length) = 2;
        } else {
+               /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
                rc = -EINVAL;
                ecryptfs_printk(KERN_WARNING,
                                "Unsupported packet size: [%zd]\n", size);
@@ -678,10 +679,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
         * Octets N3-N4: Block-aligned encrypted filename
         *  - Consists of a minimum number of random characters, a \0
         *    separator, and then the filename */
-       s->max_packet_size = (1                   /* Tag 70 identifier */
-                             + 3                 /* Max Tag 70 packet size */
-                             + ECRYPTFS_SIG_SIZE /* FNEK sig */
-                             + 1                 /* Cipher identifier */
+       s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE
                              + s->block_aligned_filename_size);
        if (dest == NULL) {
                (*packet_size) = s->max_packet_size;
@@ -933,10 +931,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
                goto out;
        }
        s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-       if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) {
+       if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {
                printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "
                       "at least [%d]\n", __func__, max_packet_size,
-                       (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1));
+                      ECRYPTFS_TAG_70_MIN_METADATA_SIZE);
                rc = -EINVAL;
                goto out;
        }
index 940a82e63dc3fcdc52797f9176842fdbf391d272..349209dc6a9162d18b7da50c891a389aa9c648d8 100644 (file)
@@ -218,6 +218,29 @@ out_unlock:
        return rc;
 }
 
+/*
+ * miscdevfs packet format:
+ *  Octet 0: Type
+ *  Octets 1-4: network byte order msg_ctx->counter
+ *  Octets 5-N0: Size of struct ecryptfs_message to follow
+ *  Octets N0-N1: struct ecryptfs_message (including data)
+ *
+ *  Octets 5-N1 not written if the packet type does not include a message
+ */
+#define PKT_TYPE_SIZE          1
+#define PKT_CTR_SIZE           4
+#define MIN_NON_MSG_PKT_SIZE   (PKT_TYPE_SIZE + PKT_CTR_SIZE)
+#define MIN_MSG_PKT_SIZE       (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+                                + ECRYPTFS_MIN_PKT_LEN_SIZE)
+/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */
+#define MAX_MSG_PKT_SIZE       (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+                                + ECRYPTFS_MAX_PKT_LEN_SIZE \
+                                + sizeof(struct ecryptfs_message) \
+                                + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)
+#define PKT_TYPE_OFFSET                0
+#define PKT_CTR_OFFSET         PKT_TYPE_SIZE
+#define PKT_LEN_OFFSET         (PKT_TYPE_SIZE + PKT_CTR_SIZE)
+
 /**
  * ecryptfs_miscdev_read - format and send message from queue
  * @file: fs/ecryptfs/euid miscdevfs handle (ignored)
@@ -237,7 +260,7 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
        struct ecryptfs_daemon *daemon;
        struct ecryptfs_msg_ctx *msg_ctx;
        size_t packet_length_size;
-       char packet_length[3];
+       char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
        size_t i;
        size_t total_length;
        uid_t euid = current_euid();
@@ -305,15 +328,8 @@ check_list:
                packet_length_size = 0;
                msg_ctx->msg_size = 0;
        }
-       /* miscdevfs packet format:
-        *  Octet 0: Type
-        *  Octets 1-4: network byte order msg_ctx->counter
-        *  Octets 5-N0: Size of struct ecryptfs_message to follow
-        *  Octets N0-N1: struct ecryptfs_message (including data)
-        *
-        *  Octets 5-N1 not written if the packet type does not
-        *  include a message */
-       total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
+       total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
+                       + msg_ctx->msg_size);
        if (count < total_length) {
                rc = 0;
                printk(KERN_WARNING "%s: Only given user buffer of "
@@ -324,9 +340,10 @@ check_list:
        rc = -EFAULT;
        if (put_user(msg_ctx->type, buf))
                goto out_unlock_msg_ctx;
-       if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1)))
+       if (put_user(cpu_to_be32(msg_ctx->counter),
+                    (__be32 __user *)(&buf[PKT_CTR_OFFSET])))
                goto out_unlock_msg_ctx;
-       i = 5;
+       i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
        if (msg_ctx->msg) {
                if (copy_to_user(&buf[i], packet_length, packet_length_size))
                        goto out_unlock_msg_ctx;
@@ -391,12 +408,6 @@ out:
  * @count: Amount of data in @buf
  * @ppos: Pointer to offset in file (ignored)
  *
- * miscdevfs packet format:
- *  Octet 0: Type
- *  Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
- *  Octets 5-N0: Size of struct ecryptfs_message to follow
- *  Octets N0-N1: struct ecryptfs_message (including data)
- *
  * Returns the number of bytes read from @buf
  */
 static ssize_t
@@ -405,60 +416,78 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
 {
        __be32 counter_nbo;
        u32 seq;
-       size_t packet_size, packet_size_length, i;
-       ssize_t sz = 0;
+       size_t packet_size, packet_size_length;
        char *data;
        uid_t euid = current_euid();
-       int rc;
+       unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE];
+       ssize_t rc;
 
-       if (count == 0)
-               goto out;
+       if (count == 0) {
+               return 0;
+       } else if (count == MIN_NON_MSG_PKT_SIZE) {
+               /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
+               goto memdup;
+       } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) {
+               printk(KERN_WARNING "%s: Acceptable packet size range is "
+                      "[%d-%lu], but amount of data written is [%zu].",
+                      __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count);
+               return -EINVAL;
+       }
+
+       if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET],
+                          sizeof(packet_size_peek))) {
+               printk(KERN_WARNING "%s: Error while inspecting packet size\n",
+                      __func__);
+               return -EFAULT;
+       }
 
+       rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
+                                         &packet_size_length);
+       if (rc) {
+               printk(KERN_WARNING "%s: Error parsing packet length; "
+                      "rc = [%zd]\n", __func__, rc);
+               return rc;
+       }
+
+       if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size)
+           != count) {
+               printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
+                      packet_size);
+               return -EINVAL;
+       }
+
+memdup:
        data = memdup_user(buf, count);
        if (IS_ERR(data)) {
                printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
                       __func__, PTR_ERR(data));
-               goto out;
+               return PTR_ERR(data);
        }
-       sz = count;
-       i = 0;
-       switch (data[i++]) {
+       switch (data[PKT_TYPE_OFFSET]) {
        case ECRYPTFS_MSG_RESPONSE:
-               if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
+               if (count < (MIN_MSG_PKT_SIZE
+                            + sizeof(struct ecryptfs_message))) {
                        printk(KERN_WARNING "%s: Minimum acceptable packet "
                               "size is [%zd], but amount of data written is "
                               "only [%zd]. Discarding response packet.\n",
                               __func__,
-                              (1 + 4 + 1 + sizeof(struct ecryptfs_message)),
-                              count);
+                              (MIN_MSG_PKT_SIZE
+                               + sizeof(struct ecryptfs_message)), count);
+                       rc = -EINVAL;
                        goto out_free;
                }
-               memcpy(&counter_nbo, &data[i], 4);
+               memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);
                seq = be32_to_cpu(counter_nbo);
-               i += 4;
-               rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
-                                                 &packet_size_length);
+               rc = ecryptfs_miscdev_response(
+                               &data[PKT_LEN_OFFSET + packet_size_length],
+                               packet_size, euid, current_user_ns(),
+                               task_pid(current), seq);
                if (rc) {
-                       printk(KERN_WARNING "%s: Error parsing packet length; "
-                              "rc = [%d]\n", __func__, rc);
-                       goto out_free;
-               }
-               i += packet_size_length;
-               if ((1 + 4 + packet_size_length + packet_size) != count) {
-                       printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
-                              " + packet_size([%zd]))([%zd]) != "
-                              "count([%zd]). Invalid packet format.\n",
-                              __func__, packet_size_length, packet_size,
-                              (1 + packet_size_length + packet_size), count);
-                       goto out_free;
-               }
-               rc = ecryptfs_miscdev_response(&data[i], packet_size,
-                                              euid, current_user_ns(),
-                                              task_pid(current), seq);
-               if (rc)
                        printk(KERN_WARNING "%s: Failed to deliver miscdev "
-                              "response to requesting operation; rc = [%d]\n",
+                              "response to requesting operation; rc = [%zd]\n",
                               __func__, rc);
+                       goto out_free;
+               }
                break;
        case ECRYPTFS_MSG_HELO:
        case ECRYPTFS_MSG_QUIT:
@@ -467,12 +496,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
                ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
                                "message of unrecognized type [%d]\n",
                                data[0]);
-               break;
+               rc = -EINVAL;
+               goto out_free;
        }
+       rc = count;
 out_free:
        kfree(data);
-out:
-       return sz;
+       return rc;
 }
 
 
index 6a44148c5fb97e3cfb866a024de27dbea2fbff39..a46b3a8fee1ed246703d158c18834cb5cd22eb19 100644 (file)
@@ -57,6 +57,10 @@ struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index)
  * @page: Page that is locked before this call is made
  *
  * Returns zero on success; non-zero otherwise
+ *
+ * This is where we encrypt the data and pass the encrypted data to
+ * the lower filesystem.  In OpenPGP-compatible mode, we operate on
+ * entire underlying packets.
  */
 static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
 {
@@ -146,7 +150,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        /* This is a header extent */
                        char *page_virt;
 
-                       page_virt = kmap_atomic(page, KM_USER0);
+                       page_virt = kmap_atomic(page);
                        memset(page_virt, 0, PAGE_CACHE_SIZE);
                        /* TODO: Support more than one header extent */
                        if (view_extent_num == 0) {
@@ -159,7 +163,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                                                               crypt_stat,
                                                               &written);
                        }
-                       kunmap_atomic(page_virt, KM_USER0);
+                       kunmap_atomic(page_virt);
                        flush_dcache_page(page);
                        if (rc) {
                                printk(KERN_ERR "%s: Error reading xattr "
@@ -481,10 +485,6 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
  * @copied: The amount of data copied
  * @page: The eCryptfs page
  * @fsdata: The fsdata (unused)
- *
- * This is where we encrypt the data and pass the encrypted data to
- * the lower filesystem.  In OpenPGP-compatible mode, we operate on
- * entire underlying packets.
  */
 static int ecryptfs_write_end(struct file *file,
                        struct address_space *mapping,
index 3745f7c2b9c214756b778ab40a00af325c0e9e99..b2a34a192f4f50f23c6ea8658926afbbb8d2fcb8 100644 (file)
@@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
                pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
                size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
                size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
-               size_t total_remaining_bytes = ((offset + size) - pos);
+               loff_t total_remaining_bytes = ((offset + size) - pos);
+
+               if (fatal_signal_pending(current)) {
+                       rc = -EINTR;
+                       break;
+               }
 
                if (num_bytes > total_remaining_bytes)
                        num_bytes = total_remaining_bytes;
                if (pos < offset) {
                        /* remaining zeros to write, up to destination offset */
-                       size_t total_remaining_zeros = (offset - pos);
+                       loff_t total_remaining_zeros = (offset - pos);
 
                        if (num_bytes > total_remaining_zeros)
                                num_bytes = total_remaining_zeros;
@@ -151,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
                               ecryptfs_page_idx, rc);
                        goto out;
                }
-               ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+               ecryptfs_page_virt = kmap_atomic(ecryptfs_page);
 
                /*
                 * pos: where we're now writing, offset: where the request was
@@ -174,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
                               (data + data_offset), num_bytes);
                        data_offset += num_bytes;
                }
-               kunmap_atomic(ecryptfs_page_virt, KM_USER0);
+               kunmap_atomic(ecryptfs_page_virt);
                flush_dcache_page(ecryptfs_page);
                SetPageUptodate(ecryptfs_page);
                unlock_page(ecryptfs_page);
@@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
                }
                pos += num_bytes;
        }
-       if ((offset + size) > ecryptfs_file_size) {
-               i_size_write(ecryptfs_inode, (offset + size));
+       if (pos > ecryptfs_file_size) {
+               i_size_write(ecryptfs_inode, pos);
                if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
-                       rc = ecryptfs_write_inode_size_to_metadata(
+                       int rc2;
+
+                       rc2 = ecryptfs_write_inode_size_to_metadata(
                                                                ecryptfs_inode);
-                       if (rc) {
+                       if (rc2) {
                                printk(KERN_ERR "Problem with "
                                       "ecryptfs_write_inode_size_to_metadata; "
-                                      "rc = [%d]\n", rc);
+                                      "rc = [%d]\n", rc2);
+                               if (!rc)
+                                       rc = rc2;
                                goto out;
                        }
                }
@@ -273,76 +282,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
        flush_dcache_page(page_for_ecryptfs);
        return rc;
 }
-
-#if 0
-/**
- * ecryptfs_read
- * @data: The virtual address into which to write the data read (and
- *        possibly decrypted) from the lower file
- * @offset: The offset in the decrypted view of the file from which to
- *          read into @data
- * @size: The number of bytes to read into @data
- * @ecryptfs_file: The eCryptfs file from which to read
- *
- * Read an arbitrary amount of data from an arbitrary location in the
- * eCryptfs page cache. This is done on an extent-by-extent basis;
- * individual extents are decrypted and read from the lower page
- * cache (via VFS reads). This function takes care of all the
- * address translation to locations in the lower filesystem.
- *
- * Returns zero on success; non-zero otherwise
- */
-int ecryptfs_read(char *data, loff_t offset, size_t size,
-                 struct file *ecryptfs_file)
-{
-       struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode;
-       struct page *ecryptfs_page;
-       char *ecryptfs_page_virt;
-       loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
-       loff_t data_offset = 0;
-       loff_t pos;
-       int rc = 0;
-
-       if ((offset + size) > ecryptfs_file_size) {
-               rc = -EINVAL;
-               printk(KERN_ERR "%s: Attempt to read data past the end of the "
-                       "file; offset = [%lld]; size = [%td]; "
-                      "ecryptfs_file_size = [%lld]\n",
-                      __func__, offset, size, ecryptfs_file_size);
-               goto out;
-       }
-       pos = offset;
-       while (pos < (offset + size)) {
-               pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
-               size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
-               size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
-               size_t total_remaining_bytes = ((offset + size) - pos);
-
-               if (num_bytes > total_remaining_bytes)
-                       num_bytes = total_remaining_bytes;
-               ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode,
-                                                        ecryptfs_page_idx);
-               if (IS_ERR(ecryptfs_page)) {
-                       rc = PTR_ERR(ecryptfs_page);
-                       printk(KERN_ERR "%s: Error getting page at "
-                              "index [%ld] from eCryptfs inode "
-                              "mapping; rc = [%d]\n", __func__,
-                              ecryptfs_page_idx, rc);
-                       goto out;
-               }
-               ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
-               memcpy((data + data_offset),
-                      ((char *)ecryptfs_page_virt + start_offset_in_page),
-                      num_bytes);
-               kunmap_atomic(ecryptfs_page_virt, KM_USER0);
-               flush_dcache_page(ecryptfs_page);
-               SetPageUptodate(ecryptfs_page);
-               unlock_page(ecryptfs_page);
-               page_cache_release(ecryptfs_page);
-               pos += num_bytes;
-               data_offset += num_bytes;
-       }
-out:
-       return rc;
-}
-#endif  /*  0  */
index 9df7fd6e0c398d91a42c5c5627ea1e88ec868412..cf152823bbf42bcdb17fd6e8fadfdea048641593 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/seq_file.h>
 #include <linux/file.h>
 #include <linux/crypto.h>
+#include <linux/statfs.h>
+#include <linux/magic.h>
 #include "ecryptfs_kernel.h"
 
 struct kmem_cache *ecryptfs_inode_info_cache;
@@ -102,10 +104,20 @@ static void ecryptfs_destroy_inode(struct inode *inode)
 static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+       int rc;
 
        if (!lower_dentry->d_sb->s_op->statfs)
                return -ENOSYS;
-       return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
+
+       rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
+       if (rc)
+               return rc;
+
+       buf->f_type = ECRYPTFS_SUPER_MAGIC;
+       rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen,
+              &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat);
+
+       return rc;
 }
 
 /**
index aeb135c7ff5c0c1a6f1a1dfe3b5f2018dfbd6731..92ce83a11e90acbb0bceda45b682a83535089342 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf)
        perf_event_comm(tsk);
 }
 
+static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len)
+{
+       int i, ch;
+
+       /* Copies the binary name from after last slash */
+       for (i = 0; (ch = *(fn++)) != '\0';) {
+               if (ch == '/')
+                       i = 0; /* overwrite what we wrote */
+               else
+                       if (i < len - 1)
+                               tcomm[i++] = ch;
+       }
+       tcomm[i] = '\0';
+}
+
 int flush_old_exec(struct linux_binprm * bprm)
 {
        int retval;
@@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 
        set_mm_exe_file(bprm->mm, bprm->file);
 
+       filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm));
        /*
         * Release all of the old mmap stuff
         */
@@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump);
 
 void setup_new_exec(struct linux_binprm * bprm)
 {
-       int i, ch;
-       const char *name;
-       char tcomm[sizeof(current->comm)];
-
        arch_pick_mmap_layout(current->mm);
 
        /* This is the point of no return */
@@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm)
        else
                set_dumpable(current->mm, suid_dumpable);
 
-       name = bprm->filename;
-
-       /* Copies the binary name from after last slash */
-       for (i=0; (ch = *(name++)) != '\0';) {
-               if (ch == '/')
-                       i = 0; /* overwrite what we wrote */
-               else
-                       if (i < (sizeof(tcomm) - 1))
-                               tcomm[i++] = ch;
-       }
-       tcomm[i] = '\0';
-       set_task_comm(current, tcomm);
+       set_task_comm(current, bprm->tcomm);
 
        /* Set the new mm task size. We have to do that late because it may
         * depend on TIF_32BIT which is only updated in flush_thread() on
index 1089f760c8470f25c0cac5744c880de9377775d5..2de655f5d625365a3aed996d00c0a73d4052559d 100644 (file)
@@ -77,10 +77,11 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                flags = flags & EXT2_FL_USER_MODIFIABLE;
                flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
                ei->i_flags = flags;
-               mutex_unlock(&inode->i_mutex);
 
                ext2_set_inode_flags(inode);
                inode->i_ctime = CURRENT_TIME_SEC;
+               mutex_unlock(&inode->i_mutex);
+
                mark_inode_dirty(inode);
 setflags_out:
                mnt_drop_write_file(filp);
@@ -88,20 +89,29 @@ setflags_out:
        }
        case EXT2_IOC_GETVERSION:
                return put_user(inode->i_generation, (int __user *) arg);
-       case EXT2_IOC_SETVERSION:
+       case EXT2_IOC_SETVERSION: {
+               __u32 generation;
+
                if (!inode_owner_or_capable(inode))
                        return -EPERM;
                ret = mnt_want_write_file(filp);
                if (ret)
                        return ret;
-               if (get_user(inode->i_generation, (int __user *) arg)) {
+               if (get_user(generation, (int __user *) arg)) {
                        ret = -EFAULT;
-               } else {
-                       inode->i_ctime = CURRENT_TIME_SEC;
-                       mark_inode_dirty(inode);
+                       goto setversion_out;
                }
+
+               mutex_lock(&inode->i_mutex);
+               inode->i_ctime = CURRENT_TIME_SEC;
+               inode->i_generation = generation;
+               mutex_unlock(&inode->i_mutex);
+
+               mark_inode_dirty(inode);
+setversion_out:
                mnt_drop_write_file(filp);
                return ret;
+       }
        case EXT2_IOC_GETRSVSZ:
                if (test_opt(inode->i_sb, RESERVATION)
                        && S_ISREG(inode->i_mode)
index f855916657ba910f676eeb72ad795317c62fcbd5..5b4a9362d5aafd7568605b5ec99f862458811ac4 100644 (file)
@@ -52,14 +52,6 @@ struct wb_writeback_work {
        struct completion *done;        /* set if the caller waits */
 };
 
-/*
- * Include the creation of the trace points after defining the
- * wb_writeback_work structure so that the definition remains local to this
- * file.
- */
-#define CREATE_TRACE_POINTS
-#include <trace/events/writeback.h>
-
 /*
  * We don't actually have pdflush, but this one is exported though /proc...
  */
@@ -92,6 +84,14 @@ static inline struct inode *wb_inode(struct list_head *head)
        return list_entry(head, struct inode, i_wb_list);
 }
 
+/*
+ * Include the creation of the trace points after defining the
+ * wb_writeback_work structure and inline functions so that the definition
+ * remains local to this file.
+ */
+#define CREATE_TRACE_POINTS
+#include <trace/events/writeback.h>
+
 /* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */
 static void bdi_wakeup_flusher(struct backing_dev_info *bdi)
 {
index 4fa4f0916af9047ef57d8db43315244d92fef427..d3ebdbe723d0d252358d23a75674d184e639dcb0 100644 (file)
@@ -322,9 +322,6 @@ EXPORT_SYMBOL(clear_nlink);
 void set_nlink(struct inode *inode, unsigned int nlink)
 {
        if (!nlink) {
-               printk_ratelimited(KERN_INFO
-                       "set_nlink() clearing i_nlink on %s inode %li\n",
-                       inode->i_sb->s_type->name, inode->i_ino);
                clear_nlink(inode);
        } else {
                /* Yes, some filesystems do change nlink from zero to one */
@@ -1654,7 +1651,7 @@ __setup("ihash_entries=", set_ihash_entries);
  */
 void __init inode_init_early(void)
 {
-       int loop;
+       unsigned int loop;
 
        /* If hashes are distributed across NUMA nodes, defer
         * hash allocation until vmalloc space is available.
@@ -1672,13 +1669,13 @@ void __init inode_init_early(void)
                                        &i_hash_mask,
                                        0);
 
-       for (loop = 0; loop < (1 << i_hash_shift); loop++)
+       for (loop = 0; loop < (1U << i_hash_shift); loop++)
                INIT_HLIST_HEAD(&inode_hashtable[loop]);
 }
 
 void __init inode_init(void)
 {
-       int loop;
+       unsigned int loop;
 
        /* inode slab cache */
        inode_cachep = kmem_cache_create("inode_cache",
@@ -1702,7 +1699,7 @@ void __init inode_init(void)
                                        &i_hash_mask,
                                        0);
 
-       for (loop = 0; loop < (1 << i_hash_shift); loop++)
+       for (loop = 0; loop < (1U << i_hash_shift); loop++)
                INIT_HLIST_HEAD(&inode_hashtable[loop]);
 }
 
index f84b380d65e5d1a1898248bdb7a77dd3bc8b5aa4..0f1b9515213b14e5f4c2e8606efea4ff1a8c2fc4 100644 (file)
@@ -51,7 +51,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
        ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
        if (ioc) {
                ioc_ioprio_changed(ioc, ioprio);
-               put_io_context(ioc, NULL);
+               put_io_context(ioc);
        }
 
        return err;
index 5d1a00a5041b35b34fced354b5bdd98f508d0dd9..05f0754f2b466f1446b8501331bc5b698f34f8a3 100644 (file)
@@ -453,8 +453,6 @@ out:
  *
  * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
  *
- * Called with the journal lock held.
- *
  * This is the only part of the journaling code which really needs to be
  * aware of transaction aborts.  Checkpointing involves writing to the
  * main filesystem area rather than to the journal, so it can proceed
@@ -472,13 +470,14 @@ int cleanup_journal_tail(journal_t *journal)
        if (is_journal_aborted(journal))
                return 1;
 
-       /* OK, work out the oldest transaction remaining in the log, and
+       /*
+        * OK, work out the oldest transaction remaining in the log, and
         * the log block it starts at.
         *
         * If the log is now empty, we need to work out which is the
         * next transaction ID we will write, and where it will
-        * start. */
-
+        * start.
+        */
        spin_lock(&journal->j_state_lock);
        spin_lock(&journal->j_list_lock);
        transaction = journal->j_checkpoint_transactions;
@@ -504,7 +503,25 @@ int cleanup_journal_tail(journal_t *journal)
                spin_unlock(&journal->j_state_lock);
                return 1;
        }
+       spin_unlock(&journal->j_state_lock);
+
+       /*
+        * We need to make sure that any blocks that were recently written out
+        * --- perhaps by log_do_checkpoint() --- are flushed out before we
+        * drop the transactions from the journal. It's unlikely this will be
+        * necessary, especially with an appropriately sized journal, but we
+        * need this to guarantee correctness.  Fortunately
+        * cleanup_journal_tail() doesn't get called all that often.
+        */
+       if (journal->j_flags & JFS_BARRIER)
+               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
 
+       spin_lock(&journal->j_state_lock);
+       if (!tid_gt(first_tid, journal->j_tail_sequence)) {
+               spin_unlock(&journal->j_state_lock);
+               /* Someone else cleaned up journal so return 0 */
+               return 0;
+       }
        /* OK, update the superblock to recover the freed space.
         * Physical blocks come first: have we wrapped beyond the end of
         * the log?  */
index 5b43e96788e6553ec0a716baa45e1a1ac509e838..008bf062fd26e1bdfe0de195159c66aeb9fa1aab 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
+#include <linux/blkdev.h>
 #endif
 
 /*
@@ -263,6 +264,9 @@ int journal_recover(journal_t *journal)
        err2 = sync_blockdev(journal->j_fs_dev);
        if (!err)
                err = err2;
+       /* Flush disk caches to get replayed data on the permanent storage */
+       if (journal->j_flags & JFS_BARRIER)
+               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
 
        return err;
 }
index a01cdad6aad1810f0323d6494865f7540d50421c..eafb8d37a6fb89173d26ecf527a3f69433a2565f 100644 (file)
@@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
        void *ebuf;
        uint32_t ofs;
        size_t retlen;
-       int ret = -EIO;
+       int ret;
        unsigned long *wordebuf;
 
        ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen,
index e97404d611e0abf4f627d6c080aea0c0739422f0..9c501449450dc9be6891e5d9c1a035ca31b5687b 100644 (file)
@@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs)
        filler_t *filler = logfs_mtd_readpage;
        struct mtd_info *mtd = super->s_mtd;
 
-       if (!mtd_can_have_bb(mtd))
-               return NULL;
-
        *ofs = 0;
        while (mtd_block_isbad(mtd, *ofs)) {
                *ofs += mtd->erasesize;
@@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs)
        filler_t *filler = logfs_mtd_readpage;
        struct mtd_info *mtd = super->s_mtd;
 
-       if (!mtd_can_have_bb(mtd))
-               return NULL;
-
        *ofs = mtd->size - mtd->erasesize;
        while (mtd_block_isbad(mtd, *ofs)) {
                *ofs -= mtd->erasesize;
index 501043e8966ce010bd77412c767461e99da411e8..3de7a32cadbe109fb7d270235f20df1314e663de 100644 (file)
@@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
 
 static int write_inode(struct inode *inode)
 {
-       return __logfs_write_inode(inode, WF_LOCK);
+       return __logfs_write_inode(inode, NULL, WF_LOCK);
 }
 
 static s64 dir_seek_data(struct inode *inode, s64 pos)
index b548c87a86f1dbe6ff3b15b185fa432697ea0096..3886cded283c4f355f1533712efc12c5e3798c61 100644 (file)
@@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
                return ret;
 
        mutex_lock(&inode->i_mutex);
+       logfs_get_wblocks(sb, NULL, WF_LOCK);
        logfs_write_anchor(sb);
+       logfs_put_wblocks(sb, NULL, WF_LOCK);
        mutex_unlock(&inode->i_mutex);
 
        return 0;
index caa4419285dcac78e1743a0e2e602eadd57b19bb..d4efb061bdc5d1dd62ecddcb7575cf891e3b792e 100644 (file)
@@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb)
        int i, max_dist;
        struct gc_candidate *cand = NULL, *this;
 
-       max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
+       max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
 
        for (i = max_dist; i >= 0; i--) {
                this = first_in_list(&super->s_low_list[i]);
index 388df1aa35e583f728d0a085db9fc7b810635438..a422f42238b250764011fa421d24a1a0858dd153 100644 (file)
@@ -286,7 +286,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
        if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
                return 0;
 
-       ret = __logfs_write_inode(inode, flags);
+       ret = __logfs_write_inode(inode, NULL, flags);
        LOGFS_BUG_ON(ret, inode->i_sb);
        return ret;
 }
@@ -363,7 +363,9 @@ static void logfs_init_once(void *_li)
 
 static int logfs_sync_fs(struct super_block *sb, int wait)
 {
+       logfs_get_wblocks(sb, NULL, WF_LOCK);
        logfs_write_anchor(sb);
+       logfs_put_wblocks(sb, NULL, WF_LOCK);
        return 0;
 }
 
index 9da29706f91cd74772169e6391333ae877a1fa05..1e1c369df22bb085f62519b1100eb300053aaae8 100644 (file)
@@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
        if (len == 0)
                return logfs_write_header(super, header, 0, type);
 
-       BUG_ON(len > sb->s_blocksize);
        compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
        if (compr_len < 0 || type == JE_ANCHOR) {
                memcpy(data, buf, len);
index 926373866a5510c310936c0d6cc52140a335f645..5f09376094651c76c7ded9f52535fe1a1351ed6b 100644 (file)
@@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void);
 void logfs_set_blocks(struct inode *inode, u64 no);
 /* these logically belong into inode.c but actually reside in readwrite.c */
 int logfs_read_inode(struct inode *inode);
-int __logfs_write_inode(struct inode *inode, long flags);
+int __logfs_write_inode(struct inode *inode, struct page *, long flags);
 void logfs_evict_inode(struct inode *inode);
 
 /* journal.c */
@@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block,
                __be64 *array, int page_is_empty);
 int logfs_exist_block(struct inode *inode, u64 bix);
 int get_page_reserve(struct inode *inode, struct page *page);
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
 extern struct logfs_block_ops indirect_block_ops;
 
 /* segment.c */
@@ -594,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb);
 void logfs_sync_area(struct logfs_area *area);
 void logfs_sync_segments(struct super_block *sb);
 void freeseg(struct super_block *sb, u32 segno);
+void free_areas(struct super_block *sb);
 
 /* area handling */
 int logfs_init_areas(struct super_block *sb);
index 2ac4217b7901cb60b726986fc964f29b3e09168f..4153e65b01488b55d6a5646cee01689b26afc6a3 100644 (file)
@@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock)
  * is waiting for s_write_mutex.  We annotate this fact by setting PG_pre_locked
  * in addition to PG_locked.
  */
-static void logfs_get_wblocks(struct super_block *sb, struct page *page,
-               int lock)
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
 {
        struct logfs_super *super = logfs_super(sb);
 
@@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page,
        }
 }
 
-static void logfs_put_wblocks(struct super_block *sb, struct page *page,
-               int lock)
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
 {
        struct logfs_super *super = logfs_super(sb);
 
@@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)
        if (inode->i_ino == LOGFS_INO_MASTER)
                logfs_write_anchor(inode->i_sb);
        else {
-               ret = __logfs_write_inode(inode, 0);
+               ret = __logfs_write_inode(inode, NULL, 0);
                /* see indirect_write_block comment */
                BUG_ON(ret);
        }
@@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block)
 static void indirect_free_block(struct super_block *sb,
                struct logfs_block *block)
 {
-       ClearPagePrivate(block->page);
-       block->page->private = 0;
+       struct page *page = block->page;
+
+       if (PagePrivate(page)) {
+               ClearPagePrivate(page);
+               page_cache_release(page);
+               set_page_private(page, 0);
+       }
        __free_block(sb, block);
 }
 
@@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page)
        logfs_unpack_index(page->index, &bix, &level);
        block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
        block->page = page;
+
        SetPagePrivate(page);
-       page->private = (unsigned long)block;
+       page_cache_get(page);
+       set_page_private(page, (unsigned long) block);
+
        block->ops = &indirect_block_ops;
 }
 
@@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags)
 static int __logfs_delete(struct inode *inode, struct page *page)
 {
        long flags = WF_DELETE;
+       int err;
 
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 
        if (page->index < I0_BLOCKS)
                return logfs_write_direct(inode, page, flags);
+       err = grow_inode(inode, page->index, 0);
+       if (err)
+               return err;
        return logfs_write_rec(inode, page, page->index, 0, flags);
 }
 
@@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
                        if (inode->i_ino == LOGFS_INO_MASTER)
                                logfs_write_anchor(inode->i_sb);
                        else {
-                               err = __logfs_write_inode(inode, flags);
+                               err = __logfs_write_inode(inode, page, flags);
                        }
                }
        }
@@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target)
                logfs_get_wblocks(sb, NULL, 1);
                err = __logfs_truncate(inode, size);
                if (!err)
-                       err = __logfs_write_inode(inode, 0);
+                       err = __logfs_write_inode(inode, NULL, 0);
                logfs_put_wblocks(sb, NULL, 1);
        }
 
@@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page)
        li->li_block = block;
 
        block->page = NULL;
-       page->private = 0;
-       ClearPagePrivate(page);
+       if (PagePrivate(page)) {
+               ClearPagePrivate(page);
+               page_cache_release(page);
+               set_page_private(page, 0);
+       }
 }
 
 static void move_inode_to_page(struct page *page, struct inode *inode)
@@ -1918,8 +1931,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode)
        BUG_ON(PagePrivate(page));
        block->ops = &indirect_block_ops;
        block->page = page;
-       page->private = (unsigned long)block;
-       SetPagePrivate(page);
+
+       if (!PagePrivate(page)) {
+               SetPagePrivate(page);
+               page_cache_get(page);
+               set_page_private(page, (unsigned long) block);
+       }
 
        block->inode = NULL;
        li->li_block = NULL;
@@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
                        ec_level);
 }
 
-int __logfs_write_inode(struct inode *inode, long flags)
+int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
 {
        struct super_block *sb = inode->i_sb;
        int ret;
 
-       logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
+       logfs_get_wblocks(sb, page, flags & WF_LOCK);
        ret = do_write_inode(inode);
-       logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
+       logfs_put_wblocks(sb, page, flags & WF_LOCK);
        return ret;
 }
 
index 9d5187353255ddf630a44afcb5e7d020dc8dd25c..ab798ed1cc8839e2c9c97eb87d7bedff64693fa4 100644 (file)
@@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
                BUG_ON(!page); /* FIXME: reserve a pool */
                SetPageUptodate(page);
                memcpy(page_address(page) + offset, buf, copylen);
-               SetPagePrivate(page);
+
+               if (!PagePrivate(page)) {
+                       SetPagePrivate(page);
+                       page_cache_get(page);
+               }
                page_cache_release(page);
 
                buf += copylen;
@@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area)
                page = get_mapping_page(sb, index, 0);
                BUG_ON(!page); /* FIXME: reserve a pool */
                memset(page_address(page) + offset, 0xff, len);
-               SetPagePrivate(page);
+               if (!PagePrivate(page)) {
+                       SetPagePrivate(page);
+                       page_cache_get(page);
+               }
                page_cache_release(page);
        }
 }
@@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area)
                BUG_ON(!page); /* FIXME: reserve a pool */
                SetPageUptodate(page);
                memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
-               SetPagePrivate(page);
+               if (!PagePrivate(page)) {
+                       SetPagePrivate(page);
+                       page_cache_get(page);
+               }
                page_cache_release(page);
                index++;
                no_indizes--;
@@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page,
                mempool_free(item, super->s_alias_pool);
        }
        block->page = page;
-       SetPagePrivate(page);
-       page->private = (unsigned long)block;
+
+       if (!PagePrivate(page)) {
+               SetPagePrivate(page);
+               page_cache_get(page);
+               set_page_private(page, (unsigned long) block);
+       }
        block->ops = &indirect_block_ops;
        initialize_block_counters(page, block, data, 0);
 }
@@ -536,8 +550,12 @@ void move_page_to_btree(struct page *page)
                list_add(&item->list, &block->item_list);
        }
        block->page = NULL;
-       ClearPagePrivate(page);
-       page->private = 0;
+
+       if (PagePrivate(page)) {
+               ClearPagePrivate(page);
+               page_cache_release(page);
+               set_page_private(page, 0);
+       }
        block->ops = &btree_block_ops;
        err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
                        block);
@@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno)
                page = find_get_page(mapping, ofs >> PAGE_SHIFT);
                if (!page)
                        continue;
-               ClearPagePrivate(page);
+               if (PagePrivate(page)) {
+                       ClearPagePrivate(page);
+                       page_cache_release(page);
+               }
                page_cache_release(page);
        }
 }
@@ -841,6 +862,16 @@ static void free_area(struct logfs_area *area)
        kfree(area);
 }
 
+void free_areas(struct super_block *sb)
+{
+       struct logfs_super *super = logfs_super(sb);
+       int i;
+
+       for_each_area(i)
+               free_area(super->s_area[i]);
+       free_area(super->s_journal_area);
+}
+
 static struct logfs_area *alloc_area(struct super_block *sb)
 {
        struct logfs_area *area;
@@ -923,10 +954,6 @@ err:
 void logfs_cleanup_areas(struct super_block *sb)
 {
        struct logfs_super *super = logfs_super(sb);
-       int i;
 
        btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
-       for_each_area(i)
-               free_area(super->s_area[i]);
-       free_area(super->s_journal_area);
 }
index e795c234ea33592e12cb264c0c8c84d2146f29c3..c9ee7f5d1cafe2c66bd5edab9dc0240feb6f68ff 100644 (file)
@@ -486,14 +486,15 @@ static void logfs_kill_sb(struct super_block *sb)
        /* Alias entries slow down mount, so evict as many as possible */
        sync_filesystem(sb);
        logfs_write_anchor(sb);
+       free_areas(sb);
 
        /*
         * From this point on alias entries are simply dropped - and any
         * writes to the object store are considered bugs.
         */
-       super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
        log_super("LogFS: Now in shutdown\n");
        generic_shutdown_super(sb);
+       super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
 
        BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
 
index c283a1ec008ee3cd40bb7a6bb106ac5df9f52f41..a780ea515c47988623fc4954b734562182ed24c5 100644 (file)
@@ -140,21 +140,19 @@ static int do_getname(const char __user *filename, char *page)
 
 static char *getname_flags(const char __user *filename, int flags, int *empty)
 {
-       char *tmp, *result;
-
-       result = ERR_PTR(-ENOMEM);
-       tmp = __getname();
-       if (tmp)  {
-               int retval = do_getname(filename, tmp);
-
-               result = tmp;
-               if (retval < 0) {
-                       if (retval == -ENOENT && empty)
-                               *empty = 1;
-                       if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
-                               __putname(tmp);
-                               result = ERR_PTR(retval);
-                       }
+       char *result = __getname();
+       int retval;
+
+       if (!result)
+               return ERR_PTR(-ENOMEM);
+
+       retval = do_getname(filename, result);
+       if (retval < 0) {
+               if (retval == -ENOENT && empty)
+                       *empty = 1;
+               if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
+                       __putname(result);
+                       return ERR_PTR(retval);
                }
        }
        audit_getname(result);
@@ -1097,8 +1095,10 @@ static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentr
        struct dentry *old;
 
        /* Don't create child dentry for a dead directory. */
-       if (unlikely(IS_DEADDIR(inode)))
+       if (unlikely(IS_DEADDIR(inode))) {
+               dput(dentry);
                return ERR_PTR(-ENOENT);
+       }
 
        old = inode->i_op->lookup(inode, dentry, nd);
        if (unlikely(old)) {
index f0c849c98fe4bfb49208ed6a34f0714257431e75..ec9f6ef6c5dd596889c8f48f7dd91d3ff8a734e5 100644 (file)
@@ -3575,8 +3575,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        }
        if (npages > 1) {
                /* for decoding across pages */
-               args.acl_scratch = alloc_page(GFP_KERNEL);
-               if (!args.acl_scratch)
+               res.acl_scratch = alloc_page(GFP_KERNEL);
+               if (!res.acl_scratch)
                        goto out_free;
        }
        args.acl_len = npages * PAGE_SIZE;
@@ -3612,8 +3612,8 @@ out_free:
        for (i = 0; i < npages; i++)
                if (pages[i])
                        __free_page(pages[i]);
-       if (args.acl_scratch)
-               __free_page(args.acl_scratch);
+       if (res.acl_scratch)
+               __free_page(res.acl_scratch);
        return ret;
 }
 
@@ -4883,8 +4883,10 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                                clp->cl_rpcclient->cl_auth->au_flavor);
 
        res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL);
-       if (unlikely(!res.server_scope))
-               return -ENOMEM;
+       if (unlikely(!res.server_scope)) {
+               status = -ENOMEM;
+               goto out;
+       }
 
        status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (!status)
@@ -4901,12 +4903,13 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                        clp->server_scope = NULL;
                }
 
-               if (!clp->server_scope)
+               if (!clp->server_scope) {
                        clp->server_scope = res.server_scope;
-               else
-                       kfree(res.server_scope);
+                       goto out;
+               }
        }
-
+       kfree(res.server_scope);
+out:
        dprintk("<-- %s status= %d\n", __func__, status);
        return status;
 }
@@ -5008,37 +5011,53 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
        return status;
 }
 
+static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags)
+{
+       return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags);
+}
+
+static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
+               struct nfs4_slot *new,
+               u32 max_slots,
+               u32 ivalue)
+{
+       struct nfs4_slot *old = NULL;
+       u32 i;
+
+       spin_lock(&tbl->slot_tbl_lock);
+       if (new) {
+               old = tbl->slots;
+               tbl->slots = new;
+               tbl->max_slots = max_slots;
+       }
+       tbl->highest_used_slotid = -1;  /* no slot is currently used */
+       for (i = 0; i < tbl->max_slots; i++)
+               tbl->slots[i].seq_nr = ivalue;
+       spin_unlock(&tbl->slot_tbl_lock);
+       kfree(old);
+}
+
 /*
- * Reset a slot table
+ * (re)Initialise a slot table
  */
-static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
-                                int ivalue)
+static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
+                                u32 ivalue)
 {
        struct nfs4_slot *new = NULL;
-       int i;
-       int ret = 0;
+       int ret = -ENOMEM;
 
        dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
                max_reqs, tbl->max_slots);
 
        /* Does the newly negotiated max_reqs match the existing slot table? */
        if (max_reqs != tbl->max_slots) {
-               ret = -ENOMEM;
-               new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
-                             GFP_NOFS);
+               new = nfs4_alloc_slots(max_reqs, GFP_NOFS);
                if (!new)
                        goto out;
-               ret = 0;
-               kfree(tbl->slots);
        }
-       spin_lock(&tbl->slot_tbl_lock);
-       if (new) {
-               tbl->slots = new;
-               tbl->max_slots = max_reqs;
-       }
-       for (i = 0; i < tbl->max_slots; ++i)
-               tbl->slots[i].seq_nr = ivalue;
-       spin_unlock(&tbl->slot_tbl_lock);
+       ret = 0;
+
+       nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue);
        dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
                tbl, tbl->slots, tbl->max_slots);
 out:
@@ -5060,36 +5079,6 @@ static void nfs4_destroy_slot_tables(struct nfs4_session *session)
        return;
 }
 
-/*
- * Initialize slot table
- */
-static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
-               int max_slots, int ivalue)
-{
-       struct nfs4_slot *slot;
-       int ret = -ENOMEM;
-
-       BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE);
-
-       dprintk("--> %s: max_reqs=%u\n", __func__, max_slots);
-
-       slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_NOFS);
-       if (!slot)
-               goto out;
-       ret = 0;
-
-       spin_lock(&tbl->slot_tbl_lock);
-       tbl->max_slots = max_slots;
-       tbl->slots = slot;
-       tbl->highest_used_slotid = -1;  /* no slot is currently used */
-       spin_unlock(&tbl->slot_tbl_lock);
-       dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
-               tbl, tbl->slots, tbl->max_slots);
-out:
-       dprintk("<-- %s: return %d\n", __func__, ret);
-       return ret;
-}
-
 /*
  * Initialize or reset the forechannel and backchannel tables
  */
@@ -5101,25 +5090,16 @@ static int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
        dprintk("--> %s\n", __func__);
        /* Fore channel */
        tbl = &ses->fc_slot_table;
-       if (tbl->slots == NULL) {
-               status = nfs4_init_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
-               if (status) /* -ENOMEM */
-                       return status;
-       } else {
-               status = nfs4_reset_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
-               if (status)
-                       return status;
-       }
+       status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
+       if (status) /* -ENOMEM */
+               return status;
        /* Back channel */
        tbl = &ses->bc_slot_table;
-       if (tbl->slots == NULL) {
-               status = nfs4_init_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
-               if (status)
-                       /* Fore and back channel share a connection so get
-                        * both slot tables or neither */
-                       nfs4_destroy_slot_tables(ses);
-       } else
-               status = nfs4_reset_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
+       status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
+       if (status && tbl->slots == NULL)
+               /* Fore and back channel share a connection so get
+                * both slot tables or neither */
+               nfs4_destroy_slot_tables(ses);
        return status;
 }
 
index a53f33b4ac3a5cf333afe80b358f27fe4130289f..45392032e7bd60b85b00fb74f86ca99a603e31d4 100644 (file)
@@ -1132,6 +1132,8 @@ void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4
 {
        struct nfs_client *clp = server->nfs_client;
 
+       if (test_and_clear_bit(NFS_DELEGATED_STATE, &state->flags))
+               nfs_async_inode_return_delegation(state->inode, &state->stateid);
        nfs4_state_mark_reclaim_nograce(clp, state);
        nfs4_schedule_state_manager(clp);
 }
index 95e92e438407c8ea39d2a6a717faeb919dd14819..33bd8d0f745d8baaa11b41fc3fcffde52ee3f02a 100644 (file)
@@ -2522,7 +2522,6 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
 
        xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
                args->acl_pages, args->acl_pgbase, args->acl_len);
-       xdr_set_scratch_buffer(xdr, page_address(args->acl_scratch), PAGE_SIZE);
 
        encode_nops(&hdr);
 }
@@ -6032,6 +6031,10 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        struct compound_hdr hdr;
        int status;
 
+       if (res->acl_scratch != NULL) {
+               void *p = page_address(res->acl_scratch);
+               xdr_set_scratch_buffer(xdr, p, PAGE_SIZE);
+       }
        status = decode_compound_hdr(xdr, &hdr);
        if (status)
                goto out;
index 886649627c3d68d568914ee3d88983cbebcf08a5..2a70fce70c65be1151783e3aba3c221e39642ba7 100644 (file)
@@ -603,6 +603,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
        nsegs = argv[4].v_nmembs;
        if (argv[4].v_size != argsz[4])
                goto out;
+       if (nsegs > UINT_MAX / sizeof(__u64))
+               goto out;
 
        /*
         * argv[4] points to segment numbers this ioctl cleans.  We
index be244692550db3e18cf05987ff577717e1f33173..a9856e3eaaf09753b4921d56ccdfb172db5cad7b 100644 (file)
@@ -1053,7 +1053,7 @@ static int ocfs2_rename(struct inode *old_dir,
        handle_t *handle = NULL;
        struct buffer_head *old_dir_bh = NULL;
        struct buffer_head *new_dir_bh = NULL;
-       nlink_t old_dir_nlink = old_dir->i_nlink;
+       u32 old_dir_nlink = old_dir->i_nlink;
        struct ocfs2_dinode *old_di;
        struct ocfs2_dir_lookup_result old_inode_dot_dot_res = { NULL, };
        struct ocfs2_dir_lookup_result target_lookup_res = { NULL, };
index 5485a5388ecb2919ecb5033cbf99d1d22916a72b..d4548dd49b028fbdc180ef679f20f0952319c4c3 100644 (file)
@@ -198,82 +198,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
        return result;
 }
 
-static struct mm_struct *__check_mem_permission(struct task_struct *task)
-{
-       struct mm_struct *mm;
-
-       mm = get_task_mm(task);
-       if (!mm)
-               return ERR_PTR(-EINVAL);
-
-       /*
-        * A task can always look at itself, in case it chooses
-        * to use system calls instead of load instructions.
-        */
-       if (task == current)
-               return mm;
-
-       /*
-        * If current is actively ptrace'ing, and would also be
-        * permitted to freshly attach with ptrace now, permit it.
-        */
-       if (task_is_stopped_or_traced(task)) {
-               int match;
-               rcu_read_lock();
-               match = (ptrace_parent(task) == current);
-               rcu_read_unlock();
-               if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
-                       return mm;
-       }
-
-       /*
-        * No one else is allowed.
-        */
-       mmput(mm);
-       return ERR_PTR(-EPERM);
-}
-
-/*
- * If current may access user memory in @task return a reference to the
- * corresponding mm, otherwise ERR_PTR.
- */
-static struct mm_struct *check_mem_permission(struct task_struct *task)
-{
-       struct mm_struct *mm;
-       int err;
-
-       /*
-        * Avoid racing if task exec's as we might get a new mm but validate
-        * against old credentials.
-        */
-       err = mutex_lock_killable(&task->signal->cred_guard_mutex);
-       if (err)
-               return ERR_PTR(err);
-
-       mm = __check_mem_permission(task);
-       mutex_unlock(&task->signal->cred_guard_mutex);
-
-       return mm;
-}
-
 struct mm_struct *mm_for_maps(struct task_struct *task)
 {
-       struct mm_struct *mm;
-       int err;
-
-       err =  mutex_lock_killable(&task->signal->cred_guard_mutex);
-       if (err)
-               return ERR_PTR(err);
-
-       mm = get_task_mm(task);
-       if (mm && mm != current->mm &&
-                       !ptrace_may_access(task, PTRACE_MODE_READ)) {
-               mmput(mm);
-               mm = ERR_PTR(-EACCES);
-       }
-       mutex_unlock(&task->signal->cred_guard_mutex);
-
-       return mm;
+       return mm_access(task, PTRACE_MODE_READ);
 }
 
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
@@ -751,134 +678,97 @@ static const struct file_operations proc_single_file_operations = {
 };
 
 static int mem_open(struct inode* inode, struct file* file)
-{
-       file->private_data = (void*)((long)current->self_exec_id);
-       /* OK to pass negative loff_t, we can catch out-of-range */
-       file->f_mode |= FMODE_UNSIGNED_OFFSET;
-       return 0;
-}
-
-static ssize_t mem_read(struct file * file, char __user * buf,
-                       size_t count, loff_t *ppos)
 {
        struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
-       char *page;
-       unsigned long src = *ppos;
-       int ret = -ESRCH;
        struct mm_struct *mm;
 
        if (!task)
-               goto out_no_task;
+               return -ESRCH;
 
-       ret = -ENOMEM;
-       page = (char *)__get_free_page(GFP_TEMPORARY);
-       if (!page)
-               goto out;
+       mm = mm_access(task, PTRACE_MODE_ATTACH);
+       put_task_struct(task);
 
-       mm = check_mem_permission(task);
-       ret = PTR_ERR(mm);
        if (IS_ERR(mm))
-               goto out_free;
-
-       ret = -EIO;
-       if (file->private_data != (void*)((long)current->self_exec_id))
-               goto out_put;
-
-       ret = 0;
-       while (count > 0) {
-               int this_len, retval;
-
-               this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-               retval = access_remote_vm(mm, src, page, this_len, 0);
-               if (!retval) {
-                       if (!ret)
-                               ret = -EIO;
-                       break;
-               }
+               return PTR_ERR(mm);
 
-               if (copy_to_user(buf, page, retval)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               ret += retval;
-               src += retval;
-               buf += retval;
-               count -= retval;
+       if (mm) {
+               /* ensure this mm_struct can't be freed */
+               atomic_inc(&mm->mm_count);
+               /* but do not pin its memory */
+               mmput(mm);
        }
-       *ppos = src;
 
-out_put:
-       mmput(mm);
-out_free:
-       free_page((unsigned long) page);
-out:
-       put_task_struct(task);
-out_no_task:
-       return ret;
+       /* OK to pass negative loff_t, we can catch out-of-range */
+       file->f_mode |= FMODE_UNSIGNED_OFFSET;
+       file->private_data = mm;
+
+       return 0;
 }
 
-static ssize_t mem_write(struct file * file, const char __user *buf,
-                        size_t count, loff_t *ppos)
+static ssize_t mem_rw(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos, int write)
 {
-       int copied;
+       struct mm_struct *mm = file->private_data;
+       unsigned long addr = *ppos;
+       ssize_t copied;
        char *page;
-       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
-       unsigned long dst = *ppos;
-       struct mm_struct *mm;
 
-       copied = -ESRCH;
-       if (!task)
-               goto out_no_task;
+       if (!mm)
+               return 0;
 
-       copied = -ENOMEM;
        page = (char *)__get_free_page(GFP_TEMPORARY);
        if (!page)
-               goto out_task;
-
-       mm = check_mem_permission(task);
-       copied = PTR_ERR(mm);
-       if (IS_ERR(mm))
-               goto out_free;
-
-       copied = -EIO;
-       if (file->private_data != (void *)((long)current->self_exec_id))
-               goto out_mm;
+               return -ENOMEM;
 
        copied = 0;
+       if (!atomic_inc_not_zero(&mm->mm_users))
+               goto free;
+
        while (count > 0) {
-               int this_len, retval;
+               int this_len = min_t(int, count, PAGE_SIZE);
 
-               this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-               if (copy_from_user(page, buf, this_len)) {
+               if (write && copy_from_user(page, buf, this_len)) {
                        copied = -EFAULT;
                        break;
                }
-               retval = access_remote_vm(mm, dst, page, this_len, 1);
-               if (!retval) {
+
+               this_len = access_remote_vm(mm, addr, page, this_len, write);
+               if (!this_len) {
                        if (!copied)
                                copied = -EIO;
                        break;
                }
-               copied += retval;
-               buf += retval;
-               dst += retval;
-               count -= retval;                        
+
+               if (!write && copy_to_user(buf, page, this_len)) {
+                       copied = -EFAULT;
+                       break;
+               }
+
+               buf += this_len;
+               addr += this_len;
+               copied += this_len;
+               count -= this_len;
        }
-       *ppos = dst;
+       *ppos = addr;
 
-out_mm:
        mmput(mm);
-out_free:
+free:
        free_page((unsigned long) page);
-out_task:
-       put_task_struct(task);
-out_no_task:
        return copied;
 }
 
+static ssize_t mem_read(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       return mem_rw(file, buf, count, ppos, 0);
+}
+
+static ssize_t mem_write(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       return mem_rw(file, (char __user*)buf, count, ppos, 1);
+}
+
 loff_t mem_lseek(struct file *file, loff_t offset, int orig)
 {
        switch (orig) {
@@ -895,11 +785,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
        return file->f_pos;
 }
 
+static int mem_release(struct inode *inode, struct file *file)
+{
+       struct mm_struct *mm = file->private_data;
+       if (mm)
+               mmdrop(mm);
+       return 0;
+}
+
 static const struct file_operations proc_mem_operations = {
        .llseek         = mem_lseek,
        .read           = mem_read,
        .write          = mem_write,
        .open           = mem_open,
+       .release        = mem_release,
 };
 
 static ssize_t environ_read(struct file *file, char __user *buf,
@@ -1199,9 +1098,6 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
        ssize_t length;
        uid_t loginuid;
 
-       if (!capable(CAP_AUDIT_CONTROL))
-               return -EPERM;
-
        rcu_read_lock();
        if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
                rcu_read_unlock();
@@ -1230,7 +1126,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
                goto out_free_page;
 
        }
-       length = audit_set_loginuid(current, loginuid);
+       length = audit_set_loginuid(loginuid);
        if (likely(length == 0))
                length = count;
 
index d76ca6ae2b1b0bd91becd9a80b9a5480e2abb478..121f77cfef76ce0da7b96d8ae475db38943e4f8b 100644 (file)
@@ -77,6 +77,8 @@ static int show_stat(struct seq_file *p, void *v)
                steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL];
                guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST];
                guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE];
+               sum += kstat_cpu_irqs_sum(i);
+               sum += arch_irq_stat_cpu(i);
 
                for (j = 0; j < NR_SOFTIRQS; j++) {
                        unsigned int softirq_stat = kstat_softirqs_cpu(j, i);
index e418c5abdb0ef954eed21771ca0ff1fe9958077d..7dcd2a250495d9a1777e6d7992637fb0a4897a81 100644 (file)
@@ -518,6 +518,9 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
                if (!page)
                        continue;
 
+               if (PageReserved(page))
+                       continue;
+
                /* Clear accessed and referenced bits. */
                ptep_test_and_clear_young(vma, addr, pte);
                ClearPageReferenced(page);
index 2bfd987f4853407be1027ede89bc940460346bf8..6b009548d2e0380dbbbd8c061570f2805371bf4d 100644 (file)
@@ -179,47 +179,33 @@ static const char *qnx4_checkroot(struct super_block *sb)
        struct qnx4_inode_entry *rootdir;
        int rd, rl;
        int i, j;
-       int found = 0;
 
-       if (*(qnx4_sb(sb)->sb->RootDir.di_fname) != '/') {
+       if (*(qnx4_sb(sb)->sb->RootDir.di_fname) != '/')
                return "no qnx4 filesystem (no root dir).";
-       } else {
-               QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id));
-               rd = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
-               rl = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_size);
-               for (j = 0; j < rl; j++) {
-                       bh = sb_bread(sb, rd + j);      /* root dir, first block */
-                       if (bh == NULL) {
-                               return "unable to read root entry.";
-                       }
-                       for (i = 0; i < QNX4_INODES_PER_BLOCK; i++) {
-                               rootdir = (struct qnx4_inode_entry *) (bh->b_data + i * QNX4_DIR_ENTRY_SIZE);
-                               if (rootdir->di_fname != NULL) {
-                                       QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname));
-                                       if (!strcmp(rootdir->di_fname,
-                                                   QNX4_BMNAME)) {
-                                               found = 1;
-                                               qnx4_sb(sb)->BitMap = kmemdup(rootdir,
-                                                                             sizeof(struct qnx4_inode_entry),
-                                                                             GFP_KERNEL);
-                                               if (!qnx4_sb(sb)->BitMap) {
-                                                       brelse (bh);
-                                                       return "not enough memory for bitmap inode";
-                                               }/* keep bitmap inode known */
-                                               break;
-                                       }
-                               }
-                       }
+       QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id));
+       rd = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
+       rl = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_size);
+       for (j = 0; j < rl; j++) {
+               bh = sb_bread(sb, rd + j);      /* root dir, first block */
+               if (bh == NULL)
+                       return "unable to read root entry.";
+               rootdir = (struct qnx4_inode_entry *) bh->b_data;
+               for (i = 0; i < QNX4_INODES_PER_BLOCK; i++, rootdir++) {
+                       QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname));
+                       if (strcmp(rootdir->di_fname, QNX4_BMNAME) != 0)
+                               continue;
+                       qnx4_sb(sb)->BitMap = kmemdup(rootdir,
+                                                     sizeof(struct qnx4_inode_entry),
+                                                     GFP_KERNEL);
                        brelse(bh);
-                       if (found != 0) {
-                               break;
-                       }
-               }
-               if (found == 0) {
-                       return "bitmap file not found.";
+                       if (!qnx4_sb(sb)->BitMap)
+                               return "not enough memory for bitmap inode";
+                       /* keep bitmap inode known */
+                       return NULL;
                }
+               brelse(bh);
        }
-       return NULL;
+       return "bitmap file not found.";
 }
 
 static int qnx4_fill_super(struct super_block *s, void *data, int silent)
@@ -270,7 +256,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
        if (IS_ERR(root)) {
                printk(KERN_ERR "qnx4: get inode failed\n");
                ret = PTR_ERR(root);
-               goto out;
+               goto outb;
        }
 
        ret = -ENOMEM;
@@ -283,6 +269,8 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
 
       outi:
        iput(root);
+      outb:
+       kfree(qs->BitMap);
       out:
        brelse(bh);
       outnobh:
index 5ec59b20cf761732f57e5eb76231579ab7c03b97..46741970371b3c720d554a7da92e9fd39d2d0cbe 100644 (file)
@@ -2125,6 +2125,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
                mutex_unlock(&dqopt->dqio_mutex);
                goto out_file_init;
        }
+       if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
+               dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
        mutex_unlock(&dqopt->dqio_mutex);
        spin_lock(&dq_state_lock);
        dqopt->flags |= dquot_state_flag(flags, type);
@@ -2464,7 +2466,7 @@ int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
        spin_lock(&dq_data_lock);
        ii->dqi_bgrace = mi->dqi_bgrace;
        ii->dqi_igrace = mi->dqi_igrace;
-       ii->dqi_flags = mi->dqi_flags & DQF_MASK;
+       ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
        ii->dqi_valid = IIF_ALL;
        spin_unlock(&dq_data_lock);
        mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
@@ -2490,8 +2492,8 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
        if (ii->dqi_valid & IIF_IGRACE)
                mi->dqi_igrace = ii->dqi_igrace;
        if (ii->dqi_valid & IIF_FLAGS)
-               mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) |
-                               (ii->dqi_flags & DQF_MASK);
+               mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) |
+                               (ii->dqi_flags & DQF_SETINFO_MASK);
        spin_unlock(&dq_data_lock);
        mark_info_dirty(sb, type);
        /* Force write to disk */
index 7898cd688a0073b8caf6c193fc3deb1dc8722f5f..fc2c4388d1262a1771d27acb7c55507369cf0dba 100644 (file)
@@ -292,11 +292,26 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
        }
 }
 
+/* Return 1 if 'cmd' will block on frozen filesystem */
+static int quotactl_cmd_write(int cmd)
+{
+       switch (cmd) {
+       case Q_GETFMT:
+       case Q_GETINFO:
+       case Q_SYNC:
+       case Q_XGETQSTAT:
+       case Q_XGETQUOTA:
+       case Q_XQUOTASYNC:
+               return 0;
+       }
+       return 1;
+}
+
 /*
  * look up a superblock on which quota ops will be performed
  * - use the name of a block device to find the superblock thereon
  */
-static struct super_block *quotactl_block(const char __user *special)
+static struct super_block *quotactl_block(const char __user *special, int cmd)
 {
 #ifdef CONFIG_BLOCK
        struct block_device *bdev;
@@ -309,7 +324,10 @@ static struct super_block *quotactl_block(const char __user *special)
        putname(tmp);
        if (IS_ERR(bdev))
                return ERR_CAST(bdev);
-       sb = get_super(bdev);
+       if (quotactl_cmd_write(cmd))
+               sb = get_super_thawed(bdev);
+       else
+               sb = get_super(bdev);
        bdput(bdev);
        if (!sb)
                return ERR_PTR(-ENODEV);
@@ -361,7 +379,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
                        pathp = &path;
        }
 
-       sb = quotactl_block(special);
+       sb = quotactl_block(special, cmds);
        if (IS_ERR(sb)) {
                ret = PTR_ERR(sb);
                goto out;
index d33418fdc858fbbe7f929d692dae1533c2e9a271..e782258d0de3cec01c6767aa5cb2b2684e1077ac 100644 (file)
@@ -912,7 +912,7 @@ static long do_restart_poll(struct restart_block *restart_block)
 }
 
 SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
-               long, timeout_msecs)
+               int, timeout_msecs)
 {
        struct timespec end_time, *to = NULL;
        int ret;
index de41e1e46f0970b3c262fb577e0b6f332c6a59e5..6277ec6cb60a65e71b2c590260c67a057a1748ca 100644 (file)
@@ -633,6 +633,28 @@ rescan:
 
 EXPORT_SYMBOL(get_super);
 
+/**
+ *     get_super_thawed - get thawed superblock of a device
+ *     @bdev: device to get the superblock for
+ *
+ *     Scans the superblock list and finds the superblock of the file system
+ *     mounted on the device. The superblock is returned once it is thawed
+ *     (or immediately if it was not frozen). %NULL is returned if no match
+ *     is found.
+ */
+struct super_block *get_super_thawed(struct block_device *bdev)
+{
+       while (1) {
+               struct super_block *s = get_super(bdev);
+               if (!s || s->s_frozen == SB_UNFROZEN)
+                       return s;
+               up_read(&s->s_umount);
+               vfs_check_frozen(s, SB_FREEZE_WRITE);
+               put_super(s);
+       }
+}
+EXPORT_SYMBOL(get_super_thawed);
+
 /**
  * get_active_super - get an active reference to the superblock of a device
  * @bdev: device to get the superblock for
@@ -1186,6 +1208,8 @@ int freeze_super(struct super_block *sb)
                        printk(KERN_ERR
                                "VFS:Filesystem freeze failed\n");
                        sb->s_frozen = SB_UNFROZEN;
+                       smp_wmb();
+                       wake_up(&sb->s_wait_unfrozen);
                        deactivate_locked_super(sb);
                        return ret;
                }
index 62f4fb37789e0f5b634c44b7adc782d1c04c67fd..00012e31829d111fbd002461b7086a70c85d29f6 100644 (file)
@@ -493,6 +493,12 @@ int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
        const void *ns = NULL;
        int err;
 
+       if (!dir_sd) {
+               WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
+                       kobject_name(kobj));
+               return -ENOENT;
+       }
+
        err = 0;
        if (!sysfs_ns_type(dir_sd))
                goto out;
index 4a802b4a90566aaf45e4e0c710faf870085caf6a..85eb81683a29ec3e06f74c5fe71a3a254acdedd8 100644 (file)
@@ -318,8 +318,11 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha
        struct sysfs_addrm_cxt acxt;
        struct sysfs_dirent *sd;
 
-       if (!dir_sd)
+       if (!dir_sd) {
+               WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
+                       name);
                return -ENOENT;
+       }
 
        sysfs_addrm_start(&acxt, dir_sd);
 
index 292eff1980309a7c31ea1081650cc170a2c72a0d..ab7c53fe346e2273311a1b73bee866ab8c4f8d7f 100644 (file)
@@ -110,10 +110,4 @@ kmem_zone_destroy(kmem_zone_t *zone)
 extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
 extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
 
-static inline int
-kmem_shake_allow(gfp_t gfp_mask)
-{
-       return ((gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS));
-}
-
 #endif /* __XFS_SUPPORT_KMEM_H__ */
index 574d4ee9b6253ea3d589f23288aa7385907642bb..74b9baf36ac39038f827c8e262ea62aa33d81de8 100644 (file)
@@ -111,8 +111,7 @@ xfs_ioend_new_eof(
        xfs_fsize_t             bsize;
 
        bsize = ioend->io_offset + ioend->io_size;
-       isize = MAX(ip->i_size, ip->i_new_size);
-       isize = MIN(isize, bsize);
+       isize = MIN(i_size_read(VFS_I(ip)), bsize);
        return isize > ip->i_d.di_size ? isize : 0;
 }
 
@@ -126,11 +125,7 @@ static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend)
 }
 
 /*
- * Update on-disk file size now that data has been written to disk.  The
- * current in-memory file size is i_size.  If a write is beyond eof i_new_size
- * will be the intended file size until i_size is updated.  If this write does
- * not extend all the way to the valid file size then restrict this update to
- * the end of the write.
+ * Update on-disk file size now that data has been written to disk.
  *
  * This function does not block as blocking on the inode lock in IO completion
  * can lead to IO completion order dependency deadlocks.. If it can't get the
@@ -1278,6 +1273,15 @@ xfs_end_io_direct_write(
 {
        struct xfs_ioend        *ioend = iocb->private;
 
+       /*
+        * While the generic direct I/O code updates the inode size, it does
+        * so only after the end_io handler is called, which means our
+        * end_io handler thinks the on-disk size is outside the in-core
+        * size.  To prevent this just update it a little bit earlier here.
+        */
+       if (offset + size > i_size_read(ioend->io_inode))
+               i_size_write(ioend->io_inode, offset + size);
+
        /*
         * blockdev_direct_IO can return an error even after the I/O
         * completion handler was called.  Thus we need to protect
@@ -1340,12 +1344,11 @@ xfs_vm_write_failed(
 
        if (to > inode->i_size) {
                /*
-                * punch out the delalloc blocks we have already allocated. We
-                * don't call xfs_setattr() to do this as we may be in the
-                * middle of a multi-iovec write and so the vfs inode->i_size
-                * will not match the xfs ip->i_size and so it will zero too
-                * much. Hence we jus truncate the page cache to zero what is
-                * necessary and punch the delalloc blocks directly.
+                * Punch out the delalloc blocks we have already allocated.
+                *
+                * Don't bother with xfs_setattr given that nothing can have
+                * made it to disk yet as the page is still locked at this
+                * point.
                 */
                struct xfs_inode        *ip = XFS_I(inode);
                xfs_fileoff_t           start_fsb;
index 1e5d97f86ea819493b9acfd1584696fc7ce5d733..08b9ac644c3140f6f6cc007f6f3eab05331ff35b 100644 (file)
@@ -827,10 +827,6 @@ xfs_attr_inactive(xfs_inode_t *dp)
        if (error)
                goto out;
 
-       /*
-        * Commit the last in the sequence of transactions.
-        */
-       xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
        error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
index c1b55e5965517a9407f678610b62f29fdabf33b3..d25eafd4d28de31d326078dbfdc21140c69b5acb 100644 (file)
@@ -271,10 +271,6 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
        dp = args->dp;
        mp = dp->i_mount;
        dp->i_d.di_forkoff = forkoff;
-       dp->i_df.if_ext_max =
-               XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
-       dp->i_afp->if_ext_max =
-               XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
 
        ifp = dp->i_afp;
        ASSERT(ifp->if_flags & XFS_IFINLINE);
@@ -326,7 +322,6 @@ xfs_attr_fork_reset(
        ASSERT(ip->i_d.di_anextents == 0);
        ASSERT(ip->i_afp == NULL);
 
-       ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
 
@@ -389,10 +384,6 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
                                (args->op_flags & XFS_DA_OP_ADDNAME) ||
                                !(mp->m_flags & XFS_MOUNT_ATTR2) ||
                                dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
-               dp->i_afp->if_ext_max =
-                       XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
-               dp->i_df.if_ext_max =
-                       XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
                xfs_trans_log_inode(args->trans, dp,
                                        XFS_ILOG_CORE | XFS_ILOG_ADATA);
        }
index d0ab78837057815f17605150d31a633c2eeb2739..188ef2fbd62880614a29ea0432e20707d5cf45a2 100644 (file)
@@ -249,7 +249,27 @@ xfs_bmbt_lookup_ge(
 }
 
 /*
-* Update the record referred to by cur to the value given
+ * Check if the inode needs to be converted to btree format.
+ */
+static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
+{
+       return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
+               XFS_IFORK_NEXTENTS(ip, whichfork) >
+                       XFS_IFORK_MAXEXT(ip, whichfork);
+}
+
+/*
+ * Check if the inode should be converted to extent format.
+ */
+static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
+{
+       return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
+               XFS_IFORK_NEXTENTS(ip, whichfork) <=
+                       XFS_IFORK_MAXEXT(ip, whichfork);
+}
+
+/*
+ * Update the record referred to by cur to the value given
  * by [off, bno, len, state].
  * This either works (return 0) or gets an EFSCORRUPTED error.
  */
@@ -683,8 +703,8 @@ xfs_bmap_add_extent_delay_real(
                                goto done;
                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
                }
-               if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-                   bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) {
+
+               if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
                        error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
                                        bma->firstblock, bma->flist,
                                        &bma->cur, 1, &tmp_rval, XFS_DATA_FORK);
@@ -767,8 +787,8 @@ xfs_bmap_add_extent_delay_real(
                                goto done;
                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
                }
-               if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-                   bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) {
+
+               if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
                        error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
                                bma->firstblock, bma->flist, &bma->cur, 1,
                                &tmp_rval, XFS_DATA_FORK);
@@ -836,8 +856,8 @@ xfs_bmap_add_extent_delay_real(
                                goto done;
                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
                }
-               if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-                   bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) {
+
+               if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
                        error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
                                        bma->firstblock, bma->flist, &bma->cur,
                                        1, &tmp_rval, XFS_DATA_FORK);
@@ -884,8 +904,7 @@ xfs_bmap_add_extent_delay_real(
        }
 
        /* convert to a btree if necessary */
-       if (XFS_IFORK_FORMAT(bma->ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(bma->ip, XFS_DATA_FORK) > ifp->if_ext_max) {
+       if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
                int     tmp_logflags;   /* partial log flag return val */
 
                ASSERT(bma->cur == NULL);
@@ -1421,8 +1440,7 @@ xfs_bmap_add_extent_unwritten_real(
        }
 
        /* convert to a btree if necessary */
-       if (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > ifp->if_ext_max) {
+       if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) {
                int     tmp_logflags;   /* partial log flag return val */
 
                ASSERT(cur == NULL);
@@ -1812,8 +1830,7 @@ xfs_bmap_add_extent_hole_real(
        }
 
        /* convert to a btree if necessary */
-       if (XFS_IFORK_FORMAT(bma->ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(bma->ip, whichfork) > ifp->if_ext_max) {
+       if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
                int     tmp_logflags;   /* partial log flag return val */
 
                ASSERT(bma->cur == NULL);
@@ -3037,8 +3054,7 @@ xfs_bmap_extents_to_btree(
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
+
        /*
         * Make space in the inode incore.
         */
@@ -3184,13 +3200,8 @@ xfs_bmap_forkoff_reset(
            ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
                uint    dfl_forkoff = xfs_default_attroffset(ip) >> 3;
 
-               if (dfl_forkoff > ip->i_d.di_forkoff) {
+               if (dfl_forkoff > ip->i_d.di_forkoff)
                        ip->i_d.di_forkoff = dfl_forkoff;
-                       ip->i_df.if_ext_max =
-                               XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
-                       ip->i_afp->if_ext_max =
-                               XFS_IFORK_ASIZE(ip) / sizeof(xfs_bmbt_rec_t);
-               }
        }
 }
 
@@ -3430,8 +3441,6 @@ xfs_bmap_add_attrfork(
        int                     error;          /* error return value */
 
        ASSERT(XFS_IFORK_Q(ip) == 0);
-       ASSERT(ip->i_df.if_ext_max ==
-              XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
 
        mp = ip->i_mount;
        ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
@@ -3486,12 +3495,9 @@ xfs_bmap_add_attrfork(
                error = XFS_ERROR(EINVAL);
                goto error1;
        }
-       ip->i_df.if_ext_max =
-               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
+
        ASSERT(ip->i_afp == NULL);
        ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
-       ip->i_afp->if_ext_max =
-               XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
        ip->i_afp->if_flags = XFS_IFEXTENTS;
        logflags = 0;
        xfs_bmap_init(&flist, &firstblock);
@@ -3535,20 +3541,17 @@ xfs_bmap_add_attrfork(
                } else
                        spin_unlock(&mp->m_sb_lock);
        }
-       if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
+
+       error = xfs_bmap_finish(&tp, &flist, &committed);
+       if (error)
                goto error2;
-       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-       ASSERT(ip->i_df.if_ext_max ==
-              XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
-       return error;
+       return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 error2:
        xfs_bmap_cancel(&flist);
 error1:
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 error0:
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
-       ASSERT(ip->i_df.if_ext_max ==
-              XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
        return error;
 }
 
@@ -3994,11 +3997,8 @@ xfs_bmap_one_block(
        xfs_bmbt_irec_t s;              /* internal version of extent */
 
 #ifndef DEBUG
-       if (whichfork == XFS_DATA_FORK) {
-               return S_ISREG(ip->i_d.di_mode) ?
-                       (ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
-                       (ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
-       }
+       if (whichfork == XFS_DATA_FORK)
+               return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize;
 #endif /* !DEBUG */
        if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
                return 0;
@@ -4010,7 +4010,7 @@ xfs_bmap_one_block(
        xfs_bmbt_get_all(ep, &s);
        rval = s.br_startoff == 0 && s.br_blockcount == 1;
        if (rval && whichfork == XFS_DATA_FORK)
-               ASSERT(ip->i_size == ip->i_mount->m_sb.sb_blocksize);
+               ASSERT(XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize);
        return rval;
 }
 
@@ -4379,8 +4379,6 @@ xfs_bmapi_read(
        XFS_STATS_INC(xs_blk_mapr);
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
                error = xfs_iread_extents(NULL, ip, whichfork);
@@ -4871,8 +4869,6 @@ xfs_bmapi_write(
                return XFS_ERROR(EIO);
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
        XFS_STATS_INC(xs_blk_mapw);
 
@@ -4981,8 +4977,7 @@ xfs_bmapi_write(
        /*
         * Transform from btree to extents, give it cur.
         */
-       if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
-           XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
+       if (xfs_bmap_wants_extents(ip, whichfork)) {
                int             tmp_logflags = 0;
 
                ASSERT(bma.cur);
@@ -4992,10 +4987,10 @@ xfs_bmapi_write(
                if (error)
                        goto error0;
        }
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
+
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
-              XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
+              XFS_IFORK_NEXTENTS(ip, whichfork) >
+               XFS_IFORK_MAXEXT(ip, whichfork));
        error = 0;
 error0:
        /*
@@ -5095,8 +5090,7 @@ xfs_bunmapi(
 
        ASSERT(len > 0);
        ASSERT(nexts >= 0);
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
+
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
            (error = xfs_iread_extents(tp, ip, whichfork)))
                return error;
@@ -5322,7 +5316,8 @@ xfs_bunmapi(
                 */
                if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
                    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-                   XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
+                   XFS_IFORK_NEXTENTS(ip, whichfork) >= /* Note the >= */
+                       XFS_IFORK_MAXEXT(ip, whichfork) &&
                    del.br_startoff > got.br_startoff &&
                    del.br_startoff + del.br_blockcount <
                    got.br_startoff + got.br_blockcount) {
@@ -5353,13 +5348,11 @@ nodelete:
                }
        }
        *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
+
        /*
         * Convert to a btree if necessary.
         */
-       if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
+       if (xfs_bmap_needs_btree(ip, whichfork)) {
                ASSERT(cur == NULL);
                error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
                        &cur, 0, &tmp_logflags, whichfork);
@@ -5370,8 +5363,7 @@ nodelete:
        /*
         * transform from btree to extents, give it cur
         */
-       else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
-                XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
+       else if (xfs_bmap_wants_extents(ip, whichfork)) {
                ASSERT(cur != NULL);
                error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
                        whichfork);
@@ -5382,8 +5374,6 @@ nodelete:
        /*
         * transform from extents to local?
         */
-       ASSERT(ifp->if_ext_max ==
-              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
        error = 0;
 error0:
        /*
@@ -5434,7 +5424,7 @@ xfs_getbmapx_fix_eof_hole(
        if (startblock == HOLESTARTBLOCK) {
                mp = ip->i_mount;
                out->bmv_block = -1;
-               fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
+               fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, XFS_ISIZE(ip)));
                fixlen -= out->bmv_offset;
                if (prealloced && out->bmv_offset + out->bmv_length == end) {
                        /* Came to hole at EOF. Trim it. */
@@ -5522,7 +5512,7 @@ xfs_getbmap(
                        fixlen = XFS_MAXIOFFSET(mp);
                } else {
                        prealloced = 0;
-                       fixlen = ip->i_size;
+                       fixlen = XFS_ISIZE(ip);
                }
        }
 
@@ -5551,7 +5541,7 @@ xfs_getbmap(
 
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
        if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
-               if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) {
+               if (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size) {
                        error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF);
                        if (error)
                                goto out_unlock_iolock;
index 654dc6f05bac7781f288f63fbcb1a5a970b06faa..dd974a55c77daee6de56a44c527e871d7cfe7fca 100644 (file)
@@ -163,12 +163,14 @@ xfs_swap_extents_check_format(
 
        /* Check temp in extent form to max in target */
        if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) > ip->i_df.if_ext_max)
+           XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) >
+                       XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
                return EINVAL;
 
        /* Check target in extent form to max in temp */
        if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > tip->i_df.if_ext_max)
+           XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) >
+                       XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
                return EINVAL;
 
        /*
@@ -180,18 +182,25 @@ xfs_swap_extents_check_format(
         * (a common defrag case) which will occur when the temp inode is in
         * extent format...
         */
-       if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
-           ((XFS_IFORK_BOFF(ip) &&
-             tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip)) ||
-            XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <= ip->i_df.if_ext_max))
-               return EINVAL;
+       if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
+               if (XFS_IFORK_BOFF(ip) &&
+                   tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip))
+                       return EINVAL;
+               if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
+                   XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
+                       return EINVAL;
+       }
 
        /* Reciprocal target->temp btree format checks */
-       if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
-           ((XFS_IFORK_BOFF(tip) &&
-             ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip)) ||
-            XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <= tip->i_df.if_ext_max))
-               return EINVAL;
+       if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
+               if (XFS_IFORK_BOFF(tip) &&
+                   ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip))
+                       return EINVAL;
+
+               if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
+                   XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
+                       return EINVAL;
+       }
 
        return 0;
 }
@@ -348,16 +357,6 @@ xfs_swap_extents(
        *ifp = *tifp;           /* struct copy */
        *tifp = *tempifp;       /* struct copy */
 
-       /*
-        * Fix the in-memory data fork values that are dependent on the fork
-        * offset in the inode. We can't assume they remain the same as attr2
-        * has dynamic fork offsets.
-        */
-       ifp->if_ext_max = XFS_IFORK_SIZE(ip, XFS_DATA_FORK) /
-                                       (uint)sizeof(xfs_bmbt_rec_t);
-       tifp->if_ext_max = XFS_IFORK_SIZE(tip, XFS_DATA_FORK) /
-                                       (uint)sizeof(xfs_bmbt_rec_t);
-
        /*
         * Fix the on-disk inode values
         */
index b4ff40b5f918f2462ed1482d1b8f3446bc0a18d0..53db20ee3e774fab3f643f8c280e018086dffa10 100644 (file)
@@ -62,82 +62,6 @@ int xfs_dqerror_mod = 33;
 
 static struct lock_class_key xfs_dquot_other_class;
 
-/*
- * Allocate and initialize a dquot. We don't always allocate fresh memory;
- * we try to reclaim a free dquot if the number of incore dquots are above
- * a threshold.
- * The only field inside the core that gets initialized at this point
- * is the d_id field. The idea is to fill in the entire q_core
- * when we read in the on disk dquot.
- */
-STATIC xfs_dquot_t *
-xfs_qm_dqinit(
-       xfs_mount_t  *mp,
-       xfs_dqid_t   id,
-       uint         type)
-{
-       xfs_dquot_t     *dqp;
-       boolean_t       brandnewdquot;
-
-       brandnewdquot = xfs_qm_dqalloc_incore(&dqp);
-       dqp->dq_flags = type;
-       dqp->q_core.d_id = cpu_to_be32(id);
-       dqp->q_mount = mp;
-
-       /*
-        * No need to re-initialize these if this is a reclaimed dquot.
-        */
-       if (brandnewdquot) {
-               INIT_LIST_HEAD(&dqp->q_freelist);
-               mutex_init(&dqp->q_qlock);
-               init_waitqueue_head(&dqp->q_pinwait);
-
-               /*
-                * Because we want to use a counting completion, complete
-                * the flush completion once to allow a single access to
-                * the flush completion without blocking.
-                */
-               init_completion(&dqp->q_flush);
-               complete(&dqp->q_flush);
-
-               trace_xfs_dqinit(dqp);
-       } else {
-               /*
-                * Only the q_core portion was zeroed in dqreclaim_one().
-                * So, we need to reset others.
-                */
-               dqp->q_nrefs = 0;
-               dqp->q_blkno = 0;
-               INIT_LIST_HEAD(&dqp->q_mplist);
-               INIT_LIST_HEAD(&dqp->q_hashlist);
-               dqp->q_bufoffset = 0;
-               dqp->q_fileoffset = 0;
-               dqp->q_transp = NULL;
-               dqp->q_gdquot = NULL;
-               dqp->q_res_bcount = 0;
-               dqp->q_res_icount = 0;
-               dqp->q_res_rtbcount = 0;
-               atomic_set(&dqp->q_pincount, 0);
-               dqp->q_hash = NULL;
-               ASSERT(list_empty(&dqp->q_freelist));
-
-               trace_xfs_dqreuse(dqp);
-       }
-
-       /*
-        * In either case we need to make sure group quotas have a different
-        * lock class than user quotas, to make sure lockdep knows we can
-        * locks of one of each at the same time.
-        */
-       if (!(type & XFS_DQ_USER))
-               lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class);
-
-       /*
-        * log item gets initialized later
-        */
-       return (dqp);
-}
-
 /*
  * This is called to free all the memory associated with a dquot
  */
@@ -215,10 +139,10 @@ xfs_qm_adjust_dqtimers(
 
        if (!d->d_btimer) {
                if ((d->d_blk_softlimit &&
-                    (be64_to_cpu(d->d_bcount) >=
+                    (be64_to_cpu(d->d_bcount) >
                      be64_to_cpu(d->d_blk_softlimit))) ||
                    (d->d_blk_hardlimit &&
-                    (be64_to_cpu(d->d_bcount) >=
+                    (be64_to_cpu(d->d_bcount) >
                      be64_to_cpu(d->d_blk_hardlimit)))) {
                        d->d_btimer = cpu_to_be32(get_seconds() +
                                        mp->m_quotainfo->qi_btimelimit);
@@ -227,10 +151,10 @@ xfs_qm_adjust_dqtimers(
                }
        } else {
                if ((!d->d_blk_softlimit ||
-                    (be64_to_cpu(d->d_bcount) <
+                    (be64_to_cpu(d->d_bcount) <=
                      be64_to_cpu(d->d_blk_softlimit))) &&
                    (!d->d_blk_hardlimit ||
-                   (be64_to_cpu(d->d_bcount) <
+                   (be64_to_cpu(d->d_bcount) <=
                     be64_to_cpu(d->d_blk_hardlimit)))) {
                        d->d_btimer = 0;
                }
@@ -238,10 +162,10 @@ xfs_qm_adjust_dqtimers(
 
        if (!d->d_itimer) {
                if ((d->d_ino_softlimit &&
-                    (be64_to_cpu(d->d_icount) >=
+                    (be64_to_cpu(d->d_icount) >
                      be64_to_cpu(d->d_ino_softlimit))) ||
                    (d->d_ino_hardlimit &&
-                    (be64_to_cpu(d->d_icount) >=
+                    (be64_to_cpu(d->d_icount) >
                      be64_to_cpu(d->d_ino_hardlimit)))) {
                        d->d_itimer = cpu_to_be32(get_seconds() +
                                        mp->m_quotainfo->qi_itimelimit);
@@ -250,10 +174,10 @@ xfs_qm_adjust_dqtimers(
                }
        } else {
                if ((!d->d_ino_softlimit ||
-                    (be64_to_cpu(d->d_icount) <
+                    (be64_to_cpu(d->d_icount) <=
                      be64_to_cpu(d->d_ino_softlimit)))  &&
                    (!d->d_ino_hardlimit ||
-                    (be64_to_cpu(d->d_icount) <
+                    (be64_to_cpu(d->d_icount) <=
                      be64_to_cpu(d->d_ino_hardlimit)))) {
                        d->d_itimer = 0;
                }
@@ -261,10 +185,10 @@ xfs_qm_adjust_dqtimers(
 
        if (!d->d_rtbtimer) {
                if ((d->d_rtb_softlimit &&
-                    (be64_to_cpu(d->d_rtbcount) >=
+                    (be64_to_cpu(d->d_rtbcount) >
                      be64_to_cpu(d->d_rtb_softlimit))) ||
                    (d->d_rtb_hardlimit &&
-                    (be64_to_cpu(d->d_rtbcount) >=
+                    (be64_to_cpu(d->d_rtbcount) >
                      be64_to_cpu(d->d_rtb_hardlimit)))) {
                        d->d_rtbtimer = cpu_to_be32(get_seconds() +
                                        mp->m_quotainfo->qi_rtbtimelimit);
@@ -273,10 +197,10 @@ xfs_qm_adjust_dqtimers(
                }
        } else {
                if ((!d->d_rtb_softlimit ||
-                    (be64_to_cpu(d->d_rtbcount) <
+                    (be64_to_cpu(d->d_rtbcount) <=
                      be64_to_cpu(d->d_rtb_softlimit))) &&
                    (!d->d_rtb_hardlimit ||
-                    (be64_to_cpu(d->d_rtbcount) <
+                    (be64_to_cpu(d->d_rtbcount) <=
                      be64_to_cpu(d->d_rtb_hardlimit)))) {
                        d->d_rtbtimer = 0;
                }
@@ -567,7 +491,32 @@ xfs_qm_dqread(
        int                     error;
        int                     cancelflags = 0;
 
-       dqp = xfs_qm_dqinit(mp, id, type);
+
+       dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP);
+
+       dqp->dq_flags = type;
+       dqp->q_core.d_id = cpu_to_be32(id);
+       dqp->q_mount = mp;
+       INIT_LIST_HEAD(&dqp->q_freelist);
+       mutex_init(&dqp->q_qlock);
+       init_waitqueue_head(&dqp->q_pinwait);
+
+       /*
+        * Because we want to use a counting completion, complete
+        * the flush completion once to allow a single access to
+        * the flush completion without blocking.
+        */
+       init_completion(&dqp->q_flush);
+       complete(&dqp->q_flush);
+
+       /*
+        * Make sure group quotas have a different lock class than user
+        * quotas.
+        */
+       if (!(type & XFS_DQ_USER))
+               lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class);
+
+       atomic_inc(&xfs_Gqm->qm_totaldquots);
 
        trace_xfs_dqread(dqp);
 
index f675f3d9d7b3b3693cfabc0437d52ca31a4f598a..7e5bc872f2b4fb12d67f3da3796f3c5b86ac162c 100644 (file)
@@ -327,7 +327,7 @@ xfs_file_aio_read(
                                mp->m_rtdev_targp : mp->m_ddev_targp;
                if ((iocb->ki_pos & target->bt_smask) ||
                    (size & target->bt_smask)) {
-                       if (iocb->ki_pos == ip->i_size)
+                       if (iocb->ki_pos == i_size_read(inode))
                                return 0;
                        return -XFS_ERROR(EINVAL);
                }
@@ -412,51 +412,6 @@ xfs_file_splice_read(
        return ret;
 }
 
-STATIC void
-xfs_aio_write_isize_update(
-       struct inode    *inode,
-       loff_t          *ppos,
-       ssize_t         bytes_written)
-{
-       struct xfs_inode        *ip = XFS_I(inode);
-       xfs_fsize_t             isize = i_size_read(inode);
-
-       if (bytes_written > 0)
-               XFS_STATS_ADD(xs_write_bytes, bytes_written);
-
-       if (unlikely(bytes_written < 0 && bytes_written != -EFAULT &&
-                                       *ppos > isize))
-               *ppos = isize;
-
-       if (*ppos > ip->i_size) {
-               xfs_rw_ilock(ip, XFS_ILOCK_EXCL);
-               if (*ppos > ip->i_size)
-                       ip->i_size = *ppos;
-               xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
-       }
-}
-
-/*
- * If this was a direct or synchronous I/O that failed (such as ENOSPC) then
- * part of the I/O may have been written to disk before the error occurred.  In
- * this case the on-disk file size may have been adjusted beyond the in-memory
- * file size and now needs to be truncated back.
- */
-STATIC void
-xfs_aio_write_newsize_update(
-       struct xfs_inode        *ip,
-       xfs_fsize_t             new_size)
-{
-       if (new_size == ip->i_new_size) {
-               xfs_rw_ilock(ip, XFS_ILOCK_EXCL);
-               if (new_size == ip->i_new_size)
-                       ip->i_new_size = 0;
-               if (ip->i_d.di_size > ip->i_size)
-                       ip->i_d.di_size = ip->i_size;
-               xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
-       }
-}
-
 /*
  * xfs_file_splice_write() does not use xfs_rw_ilock() because
  * generic_file_splice_write() takes the i_mutex itself. This, in theory,
@@ -475,7 +430,6 @@ xfs_file_splice_write(
 {
        struct inode            *inode = outfilp->f_mapping->host;
        struct xfs_inode        *ip = XFS_I(inode);
-       xfs_fsize_t             new_size;
        int                     ioflags = 0;
        ssize_t                 ret;
 
@@ -489,19 +443,12 @@ xfs_file_splice_write(
 
        xfs_ilock(ip, XFS_IOLOCK_EXCL);
 
-       new_size = *ppos + count;
-
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-       if (new_size > ip->i_size)
-               ip->i_new_size = new_size;
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
        trace_xfs_file_splice_write(ip, count, *ppos, ioflags);
 
        ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
+       if (ret > 0)
+               XFS_STATS_ADD(xs_write_bytes, ret);
 
-       xfs_aio_write_isize_update(inode, ppos, ret);
-       xfs_aio_write_newsize_update(ip, new_size);
        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
        return ret;
 }
@@ -689,28 +636,26 @@ out_lock:
 /*
  * Common pre-write limit and setup checks.
  *
- * Returns with iolock held according to @iolock.
+ * Called with the iolocked held either shared and exclusive according to
+ * @iolock, and returns with it held.  Might upgrade the iolock to exclusive
+ * if called for a direct write beyond i_size.
  */
 STATIC ssize_t
 xfs_file_aio_write_checks(
        struct file             *file,
        loff_t                  *pos,
        size_t                  *count,
-       xfs_fsize_t             *new_sizep,
        int                     *iolock)
 {
        struct inode            *inode = file->f_mapping->host;
        struct xfs_inode        *ip = XFS_I(inode);
-       xfs_fsize_t             new_size;
        int                     error = 0;
 
        xfs_rw_ilock(ip, XFS_ILOCK_EXCL);
-       *new_sizep = 0;
 restart:
        error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode));
        if (error) {
-               xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
-               *iolock = 0;
+               xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
                return error;
        }
 
@@ -720,36 +665,21 @@ restart:
        /*
         * If the offset is beyond the size of the file, we need to zero any
         * blocks that fall between the existing EOF and the start of this
-        * write. There is no need to issue zeroing if another in-flght IO ends
-        * at or before this one If zeronig is needed and we are currently
-        * holding the iolock shared, we need to update it to exclusive which
-        * involves dropping all locks and relocking to maintain correct locking
-        * order. If we do this, restart the function to ensure all checks and
-        * values are still valid.
+        * write.  If zeroing is needed and we are currently holding the
+        * iolock shared, we need to update it to exclusive which involves
+        * dropping all locks and relocking to maintain correct locking order.
+        * If we do this, restart the function to ensure all checks and values
+        * are still valid.
         */
-       if ((ip->i_new_size && *pos > ip->i_new_size) ||
-           (!ip->i_new_size && *pos > ip->i_size)) {
+       if (*pos > i_size_read(inode)) {
                if (*iolock == XFS_IOLOCK_SHARED) {
                        xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
                        *iolock = XFS_IOLOCK_EXCL;
                        xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock);
                        goto restart;
                }
-               error = -xfs_zero_eof(ip, *pos, ip->i_size);
+               error = -xfs_zero_eof(ip, *pos, i_size_read(inode));
        }
-
-       /*
-        * If this IO extends beyond EOF, we may need to update ip->i_new_size.
-        * We have already zeroed space beyond EOF (if necessary).  Only update
-        * ip->i_new_size if this IO ends beyond any other in-flight writes.
-        */
-       new_size = *pos + *count;
-       if (new_size > ip->i_size) {
-               if (new_size > ip->i_new_size)
-                       ip->i_new_size = new_size;
-               *new_sizep = new_size;
-       }
-
        xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
        if (error)
                return error;
@@ -794,9 +724,7 @@ xfs_file_dio_aio_write(
        const struct iovec      *iovp,
        unsigned long           nr_segs,
        loff_t                  pos,
-       size_t                  ocount,
-       xfs_fsize_t             *new_size,
-       int                     *iolock)
+       size_t                  ocount)
 {
        struct file             *file = iocb->ki_filp;
        struct address_space    *mapping = file->f_mapping;
@@ -806,10 +734,10 @@ xfs_file_dio_aio_write(
        ssize_t                 ret = 0;
        size_t                  count = ocount;
        int                     unaligned_io = 0;
+       int                     iolock;
        struct xfs_buftarg      *target = XFS_IS_REALTIME_INODE(ip) ?
                                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
-       *iolock = 0;
        if ((pos & target->bt_smask) || (count & target->bt_smask))
                return -XFS_ERROR(EINVAL);
 
@@ -824,31 +752,31 @@ xfs_file_dio_aio_write(
         * EOF zeroing cases and fill out the new inode size as appropriate.
         */
        if (unaligned_io || mapping->nrpages)
-               *iolock = XFS_IOLOCK_EXCL;
+               iolock = XFS_IOLOCK_EXCL;
        else
-               *iolock = XFS_IOLOCK_SHARED;
-       xfs_rw_ilock(ip, *iolock);
+               iolock = XFS_IOLOCK_SHARED;
+       xfs_rw_ilock(ip, iolock);
 
        /*
         * Recheck if there are cached pages that need invalidate after we got
         * the iolock to protect against other threads adding new pages while
         * we were waiting for the iolock.
         */
-       if (mapping->nrpages && *iolock == XFS_IOLOCK_SHARED) {
-               xfs_rw_iunlock(ip, *iolock);
-               *iolock = XFS_IOLOCK_EXCL;
-               xfs_rw_ilock(ip, *iolock);
+       if (mapping->nrpages && iolock == XFS_IOLOCK_SHARED) {
+               xfs_rw_iunlock(ip, iolock);
+               iolock = XFS_IOLOCK_EXCL;
+               xfs_rw_ilock(ip, iolock);
        }
 
-       ret = xfs_file_aio_write_checks(file, &pos, &count, new_size, iolock);
+       ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
        if (ret)
-               return ret;
+               goto out;
 
        if (mapping->nrpages) {
                ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1,
                                                        FI_REMAPF_LOCKED);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        /*
@@ -857,15 +785,18 @@ xfs_file_dio_aio_write(
         */
        if (unaligned_io)
                inode_dio_wait(inode);
-       else if (*iolock == XFS_IOLOCK_EXCL) {
+       else if (iolock == XFS_IOLOCK_EXCL) {
                xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
-               *iolock = XFS_IOLOCK_SHARED;
+               iolock = XFS_IOLOCK_SHARED;
        }
 
        trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0);
        ret = generic_file_direct_write(iocb, iovp,
                        &nr_segs, pos, &iocb->ki_pos, count, ocount);
 
+out:
+       xfs_rw_iunlock(ip, iolock);
+
        /* No fallback to buffered IO on errors for XFS. */
        ASSERT(ret < 0 || ret == count);
        return ret;
@@ -877,9 +808,7 @@ xfs_file_buffered_aio_write(
        const struct iovec      *iovp,
        unsigned long           nr_segs,
        loff_t                  pos,
-       size_t                  ocount,
-       xfs_fsize_t             *new_size,
-       int                     *iolock)
+       size_t                  ocount)
 {
        struct file             *file = iocb->ki_filp;
        struct address_space    *mapping = file->f_mapping;
@@ -887,14 +816,14 @@ xfs_file_buffered_aio_write(
        struct xfs_inode        *ip = XFS_I(inode);
        ssize_t                 ret;
        int                     enospc = 0;
+       int                     iolock = XFS_IOLOCK_EXCL;
        size_t                  count = ocount;
 
-       *iolock = XFS_IOLOCK_EXCL;
-       xfs_rw_ilock(ip, *iolock);
+       xfs_rw_ilock(ip, iolock);
 
-       ret = xfs_file_aio_write_checks(file, &pos, &count, new_size, iolock);
+       ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
        if (ret)
-               return ret;
+               goto out;
 
        /* We can write back this queue in page reclaim */
        current->backing_dev_info = mapping->backing_dev_info;
@@ -908,13 +837,15 @@ write_retry:
         * page locks and retry *once*
         */
        if (ret == -ENOSPC && !enospc) {
-               ret = -xfs_flush_pages(ip, 0, -1, 0, FI_NONE);
-               if (ret)
-                       return ret;
                enospc = 1;
-               goto write_retry;
+               ret = -xfs_flush_pages(ip, 0, -1, 0, FI_NONE);
+               if (!ret)
+                       goto write_retry;
        }
+
        current->backing_dev_info = NULL;
+out:
+       xfs_rw_iunlock(ip, iolock);
        return ret;
 }
 
@@ -930,9 +861,7 @@ xfs_file_aio_write(
        struct inode            *inode = mapping->host;
        struct xfs_inode        *ip = XFS_I(inode);
        ssize_t                 ret;
-       int                     iolock;
        size_t                  ocount = 0;
-       xfs_fsize_t             new_size = 0;
 
        XFS_STATS_INC(xs_write_calls);
 
@@ -951,33 +880,22 @@ xfs_file_aio_write(
                return -EIO;
 
        if (unlikely(file->f_flags & O_DIRECT))
-               ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos,
-                                               ocount, &new_size, &iolock);
+               ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount);
        else
                ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos,
-                                               ocount, &new_size, &iolock);
-
-       xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret);
+                                                 ocount);
 
-       if (ret <= 0)
-               goto out_unlock;
+       if (ret > 0) {
+               ssize_t err;
 
-       /* Handle various SYNC-type writes */
-       if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
-               loff_t end = pos + ret - 1;
-               int error;
+               XFS_STATS_ADD(xs_write_bytes, ret);
 
-               xfs_rw_iunlock(ip, iolock);
-               error = xfs_file_fsync(file, pos, end,
-                                     (file->f_flags & __O_SYNC) ? 0 : 1);
-               xfs_rw_ilock(ip, iolock);
-               if (error)
-                       ret = error;
+               /* Handle various SYNC-type writes */
+               err = generic_write_sync(file, pos, ret);
+               if (err < 0)
+                       ret = err;
        }
 
-out_unlock:
-       xfs_aio_write_newsize_update(ip, new_size);
-       xfs_rw_iunlock(ip, iolock);
        return ret;
 }
 
index ed88ed16811c6ba33c1d211b3195bd1dcea18484..652b875a9d4c441bd3c759df185c153dfee0e8f5 100644 (file)
@@ -90,7 +90,7 @@ xfs_wait_on_pages(
 
        if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) {
                return -filemap_fdatawait_range(mapping, first,
-                                       last == -1 ? ip->i_size - 1 : last);
+                                       last == -1 ? XFS_ISIZE(ip) - 1 : last);
        }
        return 0;
 }
index 3960a066d7ffcb06a02aadaa34d874a92c0b643b..8c3e46394d484c3fbd798913c6862d90b3f820e7 100644 (file)
@@ -77,7 +77,7 @@ xfs_inode_alloc(
 
        ASSERT(atomic_read(&ip->i_pincount) == 0);
        ASSERT(!spin_is_locked(&ip->i_flags_lock));
-       ASSERT(completion_done(&ip->i_flush));
+       ASSERT(!xfs_isiflocked(ip));
        ASSERT(ip->i_ino == 0);
 
        mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
@@ -94,8 +94,6 @@ xfs_inode_alloc(
        ip->i_update_core = 0;
        ip->i_delayed_blks = 0;
        memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
-       ip->i_size = 0;
-       ip->i_new_size = 0;
 
        return ip;
 }
@@ -150,7 +148,7 @@ xfs_inode_free(
        /* asserts to verify all state is correct here */
        ASSERT(atomic_read(&ip->i_pincount) == 0);
        ASSERT(!spin_is_locked(&ip->i_flags_lock));
-       ASSERT(completion_done(&ip->i_flush));
+       ASSERT(!xfs_isiflocked(ip));
 
        /*
         * Because we use RCU freeing we need to ensure the inode always
@@ -450,8 +448,6 @@ again:
 
        *ipp = ip;
 
-       ASSERT(ip->i_df.if_ext_max ==
-              XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
        /*
         * If we have a real type for an on-disk inode, we can set ops(&unlock)
         * now.  If it's a new inode being created, xfs_ialloc will handle it.
@@ -715,3 +711,19 @@ xfs_isilocked(
        return 0;
 }
 #endif
+
+void
+__xfs_iflock(
+       struct xfs_inode        *ip)
+{
+       wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IFLOCK_BIT);
+       DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IFLOCK_BIT);
+
+       do {
+               prepare_to_wait_exclusive(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
+               if (xfs_isiflocked(ip))
+                       io_schedule();
+       } while (!xfs_iflock_nowait(ip));
+
+       finish_wait(wq, &wait.wait);
+}
index 9dda7cc328485014eb86baf48a013f3833faf27f..b21022499c2e8f302699f80ca2af344301fee941 100644 (file)
@@ -299,11 +299,8 @@ xfs_iformat(
 {
        xfs_attr_shortform_t    *atp;
        int                     size;
-       int                     error;
+       int                     error = 0;
        xfs_fsize_t             di_size;
-       ip->i_df.if_ext_max =
-               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
-       error = 0;
 
        if (unlikely(be32_to_cpu(dip->di_nextents) +
                     be16_to_cpu(dip->di_anextents) >
@@ -350,7 +347,6 @@ xfs_iformat(
                        return XFS_ERROR(EFSCORRUPTED);
                }
                ip->i_d.di_size = 0;
-               ip->i_size = 0;
                ip->i_df.if_u2.if_rdev = xfs_dinode_get_rdev(dip);
                break;
 
@@ -409,10 +405,10 @@ xfs_iformat(
        }
        if (!XFS_DFORK_Q(dip))
                return 0;
+
        ASSERT(ip->i_afp == NULL);
        ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP | KM_NOFS);
-       ip->i_afp->if_ext_max =
-               XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
+
        switch (dip->di_aformat) {
        case XFS_DINODE_FMT_LOCAL:
                atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
@@ -604,10 +600,11 @@ xfs_iformat_btree(
         * or the number of extents is greater than the number of
         * blocks.
         */
-       if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
-           || XFS_BMDR_SPACE_CALC(nrecs) >
-                       XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
-           || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
+       if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
+                       XFS_IFORK_MAXEXT(ip, whichfork) ||
+                    XFS_BMDR_SPACE_CALC(nrecs) >
+                       XFS_DFORK_SIZE(dip, ip->i_mount, whichfork) ||
+                    XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
                xfs_warn(ip->i_mount, "corrupt inode %Lu (btree).",
                        (unsigned long long) ip->i_ino);
                XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
@@ -835,12 +832,6 @@ xfs_iread(
                 * with the uninitialized part of it.
                 */
                ip->i_d.di_mode = 0;
-               /*
-                * Initialize the per-fork minima and maxima for a new
-                * inode here.  xfs_iformat will do it for old inodes.
-                */
-               ip->i_df.if_ext_max =
-                       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
        }
 
        /*
@@ -861,7 +852,6 @@ xfs_iread(
        }
 
        ip->i_delayed_blks = 0;
-       ip->i_size = ip->i_d.di_size;
 
        /*
         * Mark the buffer containing the inode as something to keep
@@ -1051,7 +1041,6 @@ xfs_ialloc(
        }
 
        ip->i_d.di_size = 0;
-       ip->i_size = 0;
        ip->i_d.di_nextents = 0;
        ASSERT(ip->i_d.di_nblocks == 0);
 
@@ -1165,52 +1154,6 @@ xfs_ialloc(
        return 0;
 }
 
-/*
- * Check to make sure that there are no blocks allocated to the
- * file beyond the size of the file.  We don't check this for
- * files with fixed size extents or real time extents, but we
- * at least do it for regular files.
- */
-#ifdef DEBUG
-STATIC void
-xfs_isize_check(
-       struct xfs_inode        *ip,
-       xfs_fsize_t             isize)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-       xfs_fileoff_t           map_first;
-       int                     nimaps;
-       xfs_bmbt_irec_t         imaps[2];
-       int                     error;
-
-       if (!S_ISREG(ip->i_d.di_mode))
-               return;
-
-       if (XFS_IS_REALTIME_INODE(ip))
-               return;
-
-       if (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
-               return;
-
-       nimaps = 2;
-       map_first = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
-       /*
-        * The filesystem could be shutting down, so bmapi may return
-        * an error.
-        */
-       error = xfs_bmapi_read(ip, map_first,
-                        (XFS_B_TO_FSB(mp,
-                              (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - map_first),
-                        imaps, &nimaps, XFS_BMAPI_ENTIRE);
-       if (error)
-               return;
-       ASSERT(nimaps == 1);
-       ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
-}
-#else  /* DEBUG */
-#define xfs_isize_check(ip, isize)
-#endif /* DEBUG */
-
 /*
  * Free up the underlying blocks past new_size.  The new size must be smaller
  * than the current size.  This routine can be used both for the attribute and
@@ -1252,12 +1195,14 @@ xfs_itruncate_extents(
        int                     done = 0;
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
-       ASSERT(new_size <= ip->i_size);
+       ASSERT(new_size <= XFS_ISIZE(ip));
        ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
        ASSERT(ip->i_itemp != NULL);
        ASSERT(ip->i_itemp->ili_lock_flags == 0);
        ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
 
+       trace_xfs_itruncate_extents_start(ip, new_size);
+
        /*
         * Since it is possible for space to become allocated beyond
         * the end of the file (in a crash where the space is allocated
@@ -1325,6 +1270,14 @@ xfs_itruncate_extents(
                        goto out;
        }
 
+       /*
+        * Always re-log the inode so that our permanent transaction can keep
+        * on rolling it forward in the log.
+        */
+       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+       trace_xfs_itruncate_extents_end(ip, new_size);
+
 out:
        *tpp = tp;
        return error;
@@ -1338,74 +1291,6 @@ out_bmap_cancel:
        goto out;
 }
 
-int
-xfs_itruncate_data(
-       struct xfs_trans        **tpp,
-       struct xfs_inode        *ip,
-       xfs_fsize_t             new_size)
-{
-       int                     error;
-
-       trace_xfs_itruncate_data_start(ip, new_size);
-
-       /*
-        * The first thing we do is set the size to new_size permanently on
-        * disk.  This way we don't have to worry about anyone ever being able
-        * to look at the data being freed even in the face of a crash.
-        * What we're getting around here is the case where we free a block, it
-        * is allocated to another file, it is written to, and then we crash.
-        * If the new data gets written to the file but the log buffers
-        * containing the free and reallocation don't, then we'd end up with
-        * garbage in the blocks being freed.  As long as we make the new_size
-        * permanent before actually freeing any blocks it doesn't matter if
-        * they get written to.
-        */
-       if (ip->i_d.di_nextents > 0) {
-               /*
-                * If we are not changing the file size then do not update
-                * the on-disk file size - we may be called from
-                * xfs_inactive_free_eofblocks().  If we update the on-disk
-                * file size and then the system crashes before the contents
-                * of the file are flushed to disk then the files may be
-                * full of holes (ie NULL files bug).
-                */
-               if (ip->i_size != new_size) {
-                       ip->i_d.di_size = new_size;
-                       ip->i_size = new_size;
-                       xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
-               }
-       }
-
-       error = xfs_itruncate_extents(tpp, ip, XFS_DATA_FORK, new_size);
-       if (error)
-               return error;
-
-       /*
-        * If we are not changing the file size then do not update the on-disk
-        * file size - we may be called from xfs_inactive_free_eofblocks().
-        * If we update the on-disk file size and then the system crashes
-        * before the contents of the file are flushed to disk then the files
-        * may be full of holes (ie NULL files bug).
-        */
-       xfs_isize_check(ip, new_size);
-       if (ip->i_size != new_size) {
-               ip->i_d.di_size = new_size;
-               ip->i_size = new_size;
-       }
-
-       ASSERT(new_size != 0 || ip->i_delayed_blks == 0);
-       ASSERT(new_size != 0 || ip->i_d.di_nextents == 0);
-
-       /*
-        * Always re-log the inode so that our permanent transaction can keep
-        * on rolling it forward in the log.
-        */
-       xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
-
-       trace_xfs_itruncate_data_end(ip, new_size);
-       return 0;
-}
-
 /*
  * This is called when the inode's link count goes to 0.
  * We place the on-disk inode on a list in the AGI.  It
@@ -1824,8 +1709,7 @@ xfs_ifree(
        ASSERT(ip->i_d.di_nlink == 0);
        ASSERT(ip->i_d.di_nextents == 0);
        ASSERT(ip->i_d.di_anextents == 0);
-       ASSERT((ip->i_d.di_size == 0 && ip->i_size == 0) ||
-              (!S_ISREG(ip->i_d.di_mode)));
+       ASSERT(ip->i_d.di_size == 0 || !S_ISREG(ip->i_d.di_mode));
        ASSERT(ip->i_d.di_nblocks == 0);
 
        /*
@@ -1844,8 +1728,6 @@ xfs_ifree(
        ip->i_d.di_flags = 0;
        ip->i_d.di_dmevmask = 0;
        ip->i_d.di_forkoff = 0;         /* mark the attr fork not in use */
-       ip->i_df.if_ext_max =
-               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
        ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
        ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
        /*
@@ -2151,7 +2033,7 @@ xfs_idestroy_fork(
  * once someone is waiting for it to be unpinned.
  */
 static void
-xfs_iunpin_nowait(
+xfs_iunpin(
        struct xfs_inode        *ip)
 {
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
@@ -2163,14 +2045,29 @@ xfs_iunpin_nowait(
 
 }
 
+static void
+__xfs_iunpin_wait(
+       struct xfs_inode        *ip)
+{
+       wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IPINNED_BIT);
+       DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IPINNED_BIT);
+
+       xfs_iunpin(ip);
+
+       do {
+               prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
+               if (xfs_ipincount(ip))
+                       io_schedule();
+       } while (xfs_ipincount(ip));
+       finish_wait(wq, &wait.wait);
+}
+
 void
 xfs_iunpin_wait(
        struct xfs_inode        *ip)
 {
-       if (xfs_ipincount(ip)) {
-               xfs_iunpin_nowait(ip);
-               wait_event(ip->i_ipin_wait, (xfs_ipincount(ip) == 0));
-       }
+       if (xfs_ipincount(ip))
+               __xfs_iunpin_wait(ip);
 }
 
 /*
@@ -2510,9 +2407,9 @@ xfs_iflush(
        XFS_STATS_INC(xs_iflush_count);
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-       ASSERT(!completion_done(&ip->i_flush));
+       ASSERT(xfs_isiflocked(ip));
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
-              ip->i_d.di_nextents > ip->i_df.if_ext_max);
+              ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
 
        iip = ip->i_itemp;
        mp = ip->i_mount;
@@ -2529,7 +2426,7 @@ xfs_iflush(
         * out for us if they occur after the log force completes.
         */
        if (!(flags & SYNC_WAIT) && xfs_ipincount(ip)) {
-               xfs_iunpin_nowait(ip);
+               xfs_iunpin(ip);
                xfs_ifunlock(ip);
                return EAGAIN;
        }
@@ -2626,9 +2523,9 @@ xfs_iflush_int(
 #endif
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-       ASSERT(!completion_done(&ip->i_flush));
+       ASSERT(xfs_isiflocked(ip));
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
-              ip->i_d.di_nextents > ip->i_df.if_ext_max);
+              ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
 
        iip = ip->i_itemp;
        mp = ip->i_mount;
index f0e6b151ba37e4d0c8cc92f12a84ac03848dd0a1..2f27b745408520b73bab9bd8a1a2ca4ed1f96ea0 100644 (file)
@@ -66,7 +66,6 @@ typedef struct xfs_ifork {
        struct xfs_btree_block  *if_broot;      /* file's incore btree root */
        short                   if_broot_bytes; /* bytes allocated for root */
        unsigned char           if_flags;       /* per-fork flags */
-       unsigned char           if_ext_max;     /* max # of extent records */
        union {
                xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */
                xfs_ext_irec_t  *if_ext_irec;   /* irec map file exts */
@@ -206,12 +205,12 @@ typedef struct xfs_icdinode {
        ((w) == XFS_DATA_FORK ? \
                ((ip)->i_d.di_nextents = (n)) : \
                ((ip)->i_d.di_anextents = (n)))
-
+#define XFS_IFORK_MAXEXT(ip, w) \
+       (XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t))
 
 
 #ifdef __KERNEL__
 
-struct bhv_desc;
 struct xfs_buf;
 struct xfs_bmap_free;
 struct xfs_bmbt_irec;
@@ -220,12 +219,6 @@ struct xfs_mount;
 struct xfs_trans;
 struct xfs_dquot;
 
-typedef struct dm_attrs_s {
-       __uint32_t      da_dmevmask;    /* DMIG event mask */
-       __uint16_t      da_dmstate;     /* DMIG state info */
-       __uint16_t      da_pad;         /* DMIG extra padding */
-} dm_attrs_t;
-
 typedef struct xfs_inode {
        /* Inode linking and identification information. */
        struct xfs_mount        *i_mount;       /* fs mount struct ptr */
@@ -244,27 +237,19 @@ typedef struct xfs_inode {
        struct xfs_inode_log_item *i_itemp;     /* logging information */
        mrlock_t                i_lock;         /* inode lock */
        mrlock_t                i_iolock;       /* inode IO lock */
-       struct completion       i_flush;        /* inode flush completion q */
        atomic_t                i_pincount;     /* inode pin count */
-       wait_queue_head_t       i_ipin_wait;    /* inode pinning wait queue */
        spinlock_t              i_flags_lock;   /* inode i_flags lock */
        /* Miscellaneous state. */
-       unsigned short          i_flags;        /* see defined flags below */
+       unsigned long           i_flags;        /* see defined flags below */
        unsigned char           i_update_core;  /* timestamps/size is dirty */
        unsigned int            i_delayed_blks; /* count of delay alloc blks */
 
        xfs_icdinode_t          i_d;            /* most of ondisk inode */
 
-       xfs_fsize_t             i_size;         /* in-memory size */
-       xfs_fsize_t             i_new_size;     /* size when write completes */
-
        /* VFS inode */
        struct inode            i_vnode;        /* embedded VFS inode */
 } xfs_inode_t;
 
-#define XFS_ISIZE(ip)  S_ISREG((ip)->i_d.di_mode) ? \
-                               (ip)->i_size : (ip)->i_d.di_size;
-
 /* Convert from vfs inode to xfs inode */
 static inline struct xfs_inode *XFS_I(struct inode *inode)
 {
@@ -277,6 +262,18 @@ static inline struct inode *VFS_I(struct xfs_inode *ip)
        return &ip->i_vnode;
 }
 
+/*
+ * For regular files we only update the on-disk filesize when actually
+ * writing data back to disk.  Until then only the copy in the VFS inode
+ * is uptodate.
+ */
+static inline xfs_fsize_t XFS_ISIZE(struct xfs_inode *ip)
+{
+       if (S_ISREG(ip->i_d.di_mode))
+               return i_size_read(VFS_I(ip));
+       return ip->i_d.di_size;
+}
+
 /*
  * i_flags helper functions
  */
@@ -331,6 +328,19 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
        return ret;
 }
 
+static inline int
+xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags)
+{
+       int ret;
+
+       spin_lock(&ip->i_flags_lock);
+       ret = ip->i_flags & flags;
+       if (!ret)
+               ip->i_flags |= flags;
+       spin_unlock(&ip->i_flags_lock);
+       return ret;
+}
+
 /*
  * Project quota id helpers (previously projid was 16bit only
  * and using two 16bit values to hold new 32bit projid was chosen
@@ -350,36 +360,20 @@ xfs_set_projid(struct xfs_inode *ip,
        ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff);
 }
 
-/*
- * Manage the i_flush queue embedded in the inode.  This completion
- * queue synchronizes processes attempting to flush the in-core
- * inode back to disk.
- */
-static inline void xfs_iflock(xfs_inode_t *ip)
-{
-       wait_for_completion(&ip->i_flush);
-}
-
-static inline int xfs_iflock_nowait(xfs_inode_t *ip)
-{
-       return try_wait_for_completion(&ip->i_flush);
-}
-
-static inline void xfs_ifunlock(xfs_inode_t *ip)
-{
-       complete(&ip->i_flush);
-}
-
 /*
  * In-core inode flags.
  */
-#define XFS_IRECLAIM           0x0001  /* started reclaiming this inode */
-#define XFS_ISTALE             0x0002  /* inode has been staled */
-#define XFS_IRECLAIMABLE       0x0004  /* inode can be reclaimed */
-#define XFS_INEW               0x0008  /* inode has just been allocated */
-#define XFS_IFILESTREAM                0x0010  /* inode is in a filestream directory */
-#define XFS_ITRUNCATED         0x0020  /* truncated down so flush-on-close */
-#define XFS_IDIRTY_RELEASE     0x0040  /* dirty release already seen */
+#define XFS_IRECLAIM           (1 << 0) /* started reclaiming this inode */
+#define XFS_ISTALE             (1 << 1) /* inode has been staled */
+#define XFS_IRECLAIMABLE       (1 << 2) /* inode can be reclaimed */
+#define XFS_INEW               (1 << 3) /* inode has just been allocated */
+#define XFS_IFILESTREAM                (1 << 4) /* inode is in a filestream dir. */
+#define XFS_ITRUNCATED         (1 << 5) /* truncated down so flush-on-close */
+#define XFS_IDIRTY_RELEASE     (1 << 6) /* dirty release already seen */
+#define __XFS_IFLOCK_BIT       7        /* inode is being flushed right now */
+#define XFS_IFLOCK             (1 << __XFS_IFLOCK_BIT)
+#define __XFS_IPINNED_BIT      8        /* wakeup key for zero pin count */
+#define XFS_IPINNED            (1 << __XFS_IPINNED_BIT)
 
 /*
  * Per-lifetime flags need to be reset when re-using a reclaimable inode during
@@ -391,6 +385,34 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
         XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \
         XFS_IFILESTREAM);
 
+/*
+ * Synchronize processes attempting to flush the in-core inode back to disk.
+ */
+
+extern void __xfs_iflock(struct xfs_inode *ip);
+
+static inline int xfs_iflock_nowait(struct xfs_inode *ip)
+{
+       return !xfs_iflags_test_and_set(ip, XFS_IFLOCK);
+}
+
+static inline void xfs_iflock(struct xfs_inode *ip)
+{
+       if (!xfs_iflock_nowait(ip))
+               __xfs_iflock(ip);
+}
+
+static inline void xfs_ifunlock(struct xfs_inode *ip)
+{
+       xfs_iflags_clear(ip, XFS_IFLOCK);
+       wake_up_bit(&ip->i_flags, __XFS_IFLOCK_BIT);
+}
+
+static inline int xfs_isiflocked(struct xfs_inode *ip)
+{
+       return xfs_iflags_test(ip, XFS_IFLOCK);
+}
+
 /*
  * Flags for inode locking.
  * Bit ranges: 1<<1  - 1<<16-1 -- iolock/ilock modes (bitfield)
@@ -491,8 +513,6 @@ int         xfs_ifree(struct xfs_trans *, xfs_inode_t *,
                           struct xfs_bmap_free *);
 int            xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *,
                                      int, xfs_fsize_t);
-int            xfs_itruncate_data(struct xfs_trans **, struct xfs_inode *,
-                                  xfs_fsize_t);
 int            xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
 
 void           xfs_iext_realloc(xfs_inode_t *, int, int);
index cfd6c7f8cc3c09450e1ad6dfff372f12938d1d42..91d71dcd4852eed6339bd1ceb54a8dbdf04cd27a 100644 (file)
@@ -79,8 +79,6 @@ xfs_inode_item_size(
                break;
 
        case XFS_DINODE_FMT_BTREE:
-               ASSERT(ip->i_df.if_ext_max ==
-                      XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
                iip->ili_format.ilf_fields &=
                        ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT |
                          XFS_ILOG_DEV | XFS_ILOG_UUID);
@@ -557,7 +555,7 @@ xfs_inode_item_unpin(
        trace_xfs_inode_unpin(ip, _RET_IP_);
        ASSERT(atomic_read(&ip->i_pincount) > 0);
        if (atomic_dec_and_test(&ip->i_pincount))
-               wake_up(&ip->i_ipin_wait);
+               wake_up_bit(&ip->i_flags, __XFS_IPINNED_BIT);
 }
 
 /*
@@ -719,7 +717,7 @@ xfs_inode_item_pushbuf(
         * If a flush is not in progress anymore, chances are that the
         * inode was taken off the AIL. So, just get out.
         */
-       if (completion_done(&ip->i_flush) ||
+       if (!xfs_isiflocked(ip) ||
            !(lip->li_flags & XFS_LI_IN_AIL)) {
                xfs_iunlock(ip, XFS_ILOCK_SHARED);
                return true;
@@ -752,7 +750,7 @@ xfs_inode_item_push(
        struct xfs_inode        *ip = iip->ili_inode;
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
-       ASSERT(!completion_done(&ip->i_flush));
+       ASSERT(xfs_isiflocked(ip));
 
        /*
         * Since we were able to lock the inode's flush lock and
index 9afa282aa937b473aad0d90fc6f2a0bfb659dd29..246c7d57c6f96c876778128e8d21c90fca692ce9 100644 (file)
@@ -57,26 +57,26 @@ xfs_iomap_eof_align_last_fsb(
        xfs_fileoff_t   *last_fsb)
 {
        xfs_fileoff_t   new_last_fsb = 0;
-       xfs_extlen_t    align;
+       xfs_extlen_t    align = 0;
        int             eof, error;
 
-       if (XFS_IS_REALTIME_INODE(ip))
-               ;
-       /*
-        * If mounted with the "-o swalloc" option, roundup the allocation
-        * request to a stripe width boundary if the file size is >=
-        * stripe width and we are allocating past the allocation eof.
-        */
-       else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) &&
-               (ip->i_size >= XFS_FSB_TO_B(mp, mp->m_swidth)))
-               new_last_fsb = roundup_64(*last_fsb, mp->m_swidth);
-       /*
-        * Roundup the allocation request to a stripe unit (m_dalign) boundary
-        * if the file size is >= stripe unit size, and we are allocating past
-        * the allocation eof.
-        */
-       else if (mp->m_dalign && (ip->i_size >= XFS_FSB_TO_B(mp, mp->m_dalign)))
-               new_last_fsb = roundup_64(*last_fsb, mp->m_dalign);
+       if (!XFS_IS_REALTIME_INODE(ip)) {
+               /*
+                * Round up the allocation request to a stripe unit
+                * (m_dalign) boundary if the file size is >= stripe unit
+                * size, and we are allocating past the allocation eof.
+                *
+                * If mounted with the "-o swalloc" option the alignment is
+                * increased from the strip unit size to the stripe width.
+                */
+               if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+                       align = mp->m_swidth;
+               else if (mp->m_dalign)
+                       align = mp->m_dalign;
+
+               if (align && XFS_ISIZE(ip) >= XFS_FSB_TO_B(mp, align))
+                       new_last_fsb = roundup_64(*last_fsb, align);
+       }
 
        /*
         * Always round up the allocation request to an extent boundary
@@ -154,7 +154,7 @@ xfs_iomap_write_direct(
 
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
        last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
-       if ((offset + count) > ip->i_size) {
+       if ((offset + count) > XFS_ISIZE(ip)) {
                error = xfs_iomap_eof_align_last_fsb(mp, ip, extsz, &last_fsb);
                if (error)
                        goto error_out;
@@ -211,7 +211,7 @@ xfs_iomap_write_direct(
        xfs_trans_ijoin(tp, ip, 0);
 
        bmapi_flag = 0;
-       if (offset < ip->i_size || extsz)
+       if (offset < XFS_ISIZE(ip) || extsz)
                bmapi_flag |= XFS_BMAPI_PREALLOC;
 
        /*
@@ -286,7 +286,7 @@ xfs_iomap_eof_want_preallocate(
        int             found_delalloc = 0;
 
        *prealloc = 0;
-       if ((offset + count) <= ip->i_size)
+       if (offset + count <= XFS_ISIZE(ip))
                return 0;
 
        /*
@@ -340,7 +340,7 @@ xfs_iomap_prealloc_size(
                 * if we pass in alloc_blocks = 0. Hence the "+ 1" to
                 * ensure we always pass in a non-zero value.
                 */
-               alloc_blocks = XFS_B_TO_FSB(mp, ip->i_size) + 1;
+               alloc_blocks = XFS_B_TO_FSB(mp, XFS_ISIZE(ip)) + 1;
                alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN,
                                        rounddown_pow_of_two(alloc_blocks));
 
@@ -564,7 +564,7 @@ xfs_iomap_write_allocate(
                         * back....
                         */
                        nimaps = 1;
-                       end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
+                       end_fsb = XFS_B_TO_FSB(mp, XFS_ISIZE(ip));
                        error = xfs_bmap_last_offset(NULL, ip, &last_block,
                                                        XFS_DATA_FORK);
                        if (error)
index f9babd17922377e422024ac07d9910cb78bc1708..ab302539e5b9603b8a67bb9f4399c03625fe1fd7 100644 (file)
@@ -750,6 +750,7 @@ xfs_setattr_size(
        struct xfs_mount        *mp = ip->i_mount;
        struct inode            *inode = VFS_I(ip);
        int                     mask = iattr->ia_valid;
+       xfs_off_t               oldsize, newsize;
        struct xfs_trans        *tp;
        int                     error;
        uint                    lock_flags;
@@ -777,11 +778,13 @@ xfs_setattr_size(
                lock_flags |= XFS_IOLOCK_EXCL;
        xfs_ilock(ip, lock_flags);
 
+       oldsize = inode->i_size;
+       newsize = iattr->ia_size;
+
        /*
         * Short circuit the truncate case for zero length files.
         */
-       if (iattr->ia_size == 0 &&
-           ip->i_size == 0 && ip->i_d.di_nextents == 0) {
+       if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
                if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
                        goto out_unlock;
 
@@ -807,14 +810,14 @@ xfs_setattr_size(
         * the inode to the transaction, because the inode cannot be unlocked
         * once it is a part of the transaction.
         */
-       if (iattr->ia_size > ip->i_size) {
+       if (newsize > oldsize) {
                /*
                 * Do the first part of growing a file: zero any data in the
                 * last block that is beyond the old EOF.  We need to do this
                 * before the inode is joined to the transaction to modify
                 * i_size.
                 */
-               error = xfs_zero_eof(ip, iattr->ia_size, ip->i_size);
+               error = xfs_zero_eof(ip, newsize, oldsize);
                if (error)
                        goto out_unlock;
        }
@@ -833,8 +836,8 @@ xfs_setattr_size(
         * here and prevents waiting for other data not within the range we
         * care about here.
         */
-       if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) {
-               error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size, 0,
+       if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) {
+               error = xfs_flush_pages(ip, ip->i_d.di_size, newsize, 0,
                                        FI_NONE);
                if (error)
                        goto out_unlock;
@@ -845,8 +848,7 @@ xfs_setattr_size(
         */
        inode_dio_wait(inode);
 
-       error = -block_truncate_page(inode->i_mapping, iattr->ia_size,
-                                    xfs_get_blocks);
+       error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks);
        if (error)
                goto out_unlock;
 
@@ -857,7 +859,7 @@ xfs_setattr_size(
        if (error)
                goto out_trans_cancel;
 
-       truncate_setsize(inode, iattr->ia_size);
+       truncate_setsize(inode, newsize);
 
        commit_flags = XFS_TRANS_RELEASE_LOG_RES;
        lock_flags |= XFS_ILOCK_EXCL;
@@ -876,19 +878,29 @@ xfs_setattr_size(
         * these flags set.  For all other operations the VFS set these flags
         * explicitly if it wants a timestamp update.
         */
-       if (iattr->ia_size != ip->i_size &&
-           (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+       if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
                iattr->ia_ctime = iattr->ia_mtime =
                        current_fs_time(inode->i_sb);
                mask |= ATTR_CTIME | ATTR_MTIME;
        }
 
-       if (iattr->ia_size > ip->i_size) {
-               ip->i_d.di_size = iattr->ia_size;
-               ip->i_size = iattr->ia_size;
-       } else if (iattr->ia_size <= ip->i_size ||
-                  (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
-               error = xfs_itruncate_data(&tp, ip, iattr->ia_size);
+       /*
+        * The first thing we do is set the size to new_size permanently on
+        * disk.  This way we don't have to worry about anyone ever being able
+        * to look at the data being freed even in the face of a crash.
+        * What we're getting around here is the case where we free a block, it
+        * is allocated to another file, it is written to, and then we crash.
+        * If the new data gets written to the file but the log buffers
+        * containing the free and reallocation don't, then we'd end up with
+        * garbage in the blocks being freed.  As long as we make the new size
+        * permanent before actually freeing any blocks it doesn't matter if
+        * they get written to.
+        */
+       ip->i_d.di_size = newsize;
+       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+       if (newsize <= oldsize) {
+               error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, newsize);
                if (error)
                        goto out_trans_abort;
 
index 541a508adea1818c8c9c07486e9908f7ddfa882f..0ed9ee77937c50470fdea8b7573ea738e4a1587c 100644 (file)
@@ -1489,7 +1489,7 @@ xlog_recover_add_to_cont_trans(
        old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
        old_len = item->ri_buf[item->ri_cnt-1].i_len;
 
-       ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u);
+       ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP);
        memcpy(&ptr[old_len], dp, len); /* d, s, l */
        item->ri_buf[item->ri_cnt-1].i_len += len;
        item->ri_buf[item->ri_cnt-1].i_addr = ptr;
@@ -1981,7 +1981,7 @@ xfs_qm_dqcheck(
 
        if (!errs && ddq->d_id) {
                if (ddq->d_blk_softlimit &&
-                   be64_to_cpu(ddq->d_bcount) >=
+                   be64_to_cpu(ddq->d_bcount) >
                                be64_to_cpu(ddq->d_blk_softlimit)) {
                        if (!ddq->d_btimer) {
                                if (flags & XFS_QMOPT_DOWARN)
@@ -1992,7 +1992,7 @@ xfs_qm_dqcheck(
                        }
                }
                if (ddq->d_ino_softlimit &&
-                   be64_to_cpu(ddq->d_icount) >=
+                   be64_to_cpu(ddq->d_icount) >
                                be64_to_cpu(ddq->d_ino_softlimit)) {
                        if (!ddq->d_itimer) {
                                if (flags & XFS_QMOPT_DOWARN)
@@ -2003,7 +2003,7 @@ xfs_qm_dqcheck(
                        }
                }
                if (ddq->d_rtb_softlimit &&
-                   be64_to_cpu(ddq->d_rtbcount) >=
+                   be64_to_cpu(ddq->d_rtbcount) >
                                be64_to_cpu(ddq->d_rtb_softlimit)) {
                        if (!ddq->d_rtbtimer) {
                                if (flags & XFS_QMOPT_DOWARN)
index 671f37eae1c7bbe3c9f89fd78b9c51b9195f4e32..c436def733bf892eb324603f688e6d92b92ffc61 100644 (file)
@@ -50,7 +50,6 @@
  */
 struct mutex   xfs_Gqm_lock;
 struct xfs_qm  *xfs_Gqm;
-uint           ndquot;
 
 kmem_zone_t    *qm_dqzone;
 kmem_zone_t    *qm_dqtrxzone;
@@ -93,7 +92,6 @@ xfs_Gqm_init(void)
                goto out_free_udqhash;
 
        hsize /= sizeof(xfs_dqhash_t);
-       ndquot = hsize << 8;
 
        xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
        xqm->qm_dqhashmask = hsize - 1;
@@ -137,7 +135,6 @@ xfs_Gqm_init(void)
                xqm->qm_dqtrxzone = qm_dqtrxzone;
 
        atomic_set(&xqm->qm_totaldquots, 0);
-       xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO;
        xqm->qm_nrefs = 0;
        return xqm;
 
@@ -1600,216 +1597,150 @@ xfs_qm_init_quotainos(
        return 0;
 }
 
+STATIC void
+xfs_qm_dqfree_one(
+       struct xfs_dquot        *dqp)
+{
+       struct xfs_mount        *mp = dqp->q_mount;
+       struct xfs_quotainfo    *qi = mp->m_quotainfo;
 
+       mutex_lock(&dqp->q_hash->qh_lock);
+       list_del_init(&dqp->q_hashlist);
+       dqp->q_hash->qh_version++;
+       mutex_unlock(&dqp->q_hash->qh_lock);
 
-/*
- * Pop the least recently used dquot off the freelist and recycle it.
- */
-STATIC struct xfs_dquot *
-xfs_qm_dqreclaim_one(void)
+       mutex_lock(&qi->qi_dqlist_lock);
+       list_del_init(&dqp->q_mplist);
+       qi->qi_dquots--;
+       qi->qi_dqreclaims++;
+       mutex_unlock(&qi->qi_dqlist_lock);
+
+       xfs_qm_dqdestroy(dqp);
+}
+
+STATIC void
+xfs_qm_dqreclaim_one(
+       struct xfs_dquot        *dqp,
+       struct list_head        *dispose_list)
 {
-       struct xfs_dquot        *dqp;
-       int                     restarts = 0;
+       struct xfs_mount        *mp = dqp->q_mount;
+       int                     error;
 
-       mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
-restart:
-       list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) {
-               struct xfs_mount *mp = dqp->q_mount;
+       if (!xfs_dqlock_nowait(dqp))
+               goto out_busy;
 
-               if (!xfs_dqlock_nowait(dqp))
-                       continue;
+       /*
+        * This dquot has acquired a reference in the meantime remove it from
+        * the freelist and try again.
+        */
+       if (dqp->q_nrefs) {
+               xfs_dqunlock(dqp);
 
-               /*
-                * This dquot has already been grabbed by dqlookup.
-                * Remove it from the freelist and try again.
-                */
-               if (dqp->q_nrefs) {
-                       trace_xfs_dqreclaim_want(dqp);
-                       XQM_STATS_INC(xqmstats.xs_qm_dqwants);
-
-                       list_del_init(&dqp->q_freelist);
-                       xfs_Gqm->qm_dqfrlist_cnt--;
-                       restarts++;
-                       goto dqunlock;
-               }
+               trace_xfs_dqreclaim_want(dqp);
+               XQM_STATS_INC(xqmstats.xs_qm_dqwants);
 
-               ASSERT(dqp->q_hash);
-               ASSERT(!list_empty(&dqp->q_mplist));
+               list_del_init(&dqp->q_freelist);
+               xfs_Gqm->qm_dqfrlist_cnt--;
+               return;
+       }
 
-               /*
-                * Try to grab the flush lock. If this dquot is in the process
-                * of getting flushed to disk, we don't want to reclaim it.
-                */
-               if (!xfs_dqflock_nowait(dqp))
-                       goto dqunlock;
+       ASSERT(dqp->q_hash);
+       ASSERT(!list_empty(&dqp->q_mplist));
 
-               /*
-                * We have the flush lock so we know that this is not in the
-                * process of being flushed. So, if this is dirty, flush it
-                * DELWRI so that we don't get a freelist infested with
-                * dirty dquots.
-                */
-               if (XFS_DQ_IS_DIRTY(dqp)) {
-                       int     error;
+       /*
+        * Try to grab the flush lock. If this dquot is in the process of
+        * getting flushed to disk, we don't want to reclaim it.
+        */
+       if (!xfs_dqflock_nowait(dqp))
+               goto out_busy;
 
-                       trace_xfs_dqreclaim_dirty(dqp);
+       /*
+        * We have the flush lock so we know that this is not in the
+        * process of being flushed. So, if this is dirty, flush it
+        * DELWRI so that we don't get a freelist infested with
+        * dirty dquots.
+        */
+       if (XFS_DQ_IS_DIRTY(dqp)) {
+               trace_xfs_dqreclaim_dirty(dqp);
 
-                       /*
-                        * We flush it delayed write, so don't bother
-                        * releasing the freelist lock.
-                        */
-                       error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK);
-                       if (error) {
-                               xfs_warn(mp, "%s: dquot %p flush failed",
-                                       __func__, dqp);
-                       }
-                       goto dqunlock;
+               /*
+                * We flush it delayed write, so don't bother releasing the
+                * freelist lock.
+                */
+               error = xfs_qm_dqflush(dqp, 0);
+               if (error) {
+                       xfs_warn(mp, "%s: dquot %p flush failed",
+                                __func__, dqp);
                }
-               xfs_dqfunlock(dqp);
 
                /*
-                * Prevent lookup now that we are going to reclaim the dquot.
-                * Once XFS_DQ_FREEING is set lookup won't touch the dquot,
-                * thus we can drop the lock now.
+                * Give the dquot another try on the freelist, as the
+                * flushing will take some time.
                 */
-               dqp->dq_flags |= XFS_DQ_FREEING;
-               xfs_dqunlock(dqp);
-
-               mutex_lock(&dqp->q_hash->qh_lock);
-               list_del_init(&dqp->q_hashlist);
-               dqp->q_hash->qh_version++;
-               mutex_unlock(&dqp->q_hash->qh_lock);
-
-               mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
-               list_del_init(&dqp->q_mplist);
-               mp->m_quotainfo->qi_dquots--;
-               mp->m_quotainfo->qi_dqreclaims++;
-               mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
+               goto out_busy;
+       }
+       xfs_dqfunlock(dqp);
 
-               ASSERT(dqp->q_nrefs == 0);
-               list_del_init(&dqp->q_freelist);
-               xfs_Gqm->qm_dqfrlist_cnt--;
+       /*
+        * Prevent lookups now that we are past the point of no return.
+        */
+       dqp->dq_flags |= XFS_DQ_FREEING;
+       xfs_dqunlock(dqp);
 
-               mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-               return dqp;
-dqunlock:
-               xfs_dqunlock(dqp);
-               if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
-                       break;
-               goto restart;
-       }
+       ASSERT(dqp->q_nrefs == 0);
+       list_move_tail(&dqp->q_freelist, dispose_list);
+       xfs_Gqm->qm_dqfrlist_cnt--;
 
-       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-       return NULL;
-}
+       trace_xfs_dqreclaim_done(dqp);
+       XQM_STATS_INC(xqmstats.xs_qm_dqreclaims);
+       return;
 
-/*
- * Traverse the freelist of dquots and attempt to reclaim a maximum of
- * 'howmany' dquots. This operation races with dqlookup(), and attempts to
- * favor the lookup function ...
- */
-STATIC int
-xfs_qm_shake_freelist(
-       int     howmany)
-{
-       int             nreclaimed = 0;
-       xfs_dquot_t     *dqp;
+out_busy:
+       xfs_dqunlock(dqp);
 
-       if (howmany <= 0)
-               return 0;
+       /*
+        * Move the dquot to the tail of the list so that we don't spin on it.
+        */
+       list_move_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
 
-       while (nreclaimed < howmany) {
-               dqp = xfs_qm_dqreclaim_one();
-               if (!dqp)
-                       return nreclaimed;
-               xfs_qm_dqdestroy(dqp);
-               nreclaimed++;
-       }
-       return nreclaimed;
+       trace_xfs_dqreclaim_busy(dqp);
+       XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses);
 }
 
-/*
- * The kmem_shake interface is invoked when memory is running low.
- */
-/* ARGSUSED */
 STATIC int
 xfs_qm_shake(
-       struct shrinker *shrink,
-       struct shrink_control *sc)
+       struct shrinker         *shrink,
+       struct shrink_control   *sc)
 {
-       int     ndqused, nfree, n;
-       gfp_t gfp_mask = sc->gfp_mask;
-
-       if (!kmem_shake_allow(gfp_mask))
-               return 0;
-       if (!xfs_Gqm)
-               return 0;
-
-       nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */
-       /* incore dquots in all f/s's */
-       ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree;
-
-       ASSERT(ndqused >= 0);
+       int                     nr_to_scan = sc->nr_to_scan;
+       LIST_HEAD               (dispose_list);
+       struct xfs_dquot        *dqp;
 
-       if (nfree <= ndqused && nfree < ndquot)
+       if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
                return 0;
+       if (!nr_to_scan)
+               goto out;
 
-       ndqused *= xfs_Gqm->qm_dqfree_ratio;    /* target # of free dquots */
-       n = nfree - ndqused - ndquot;           /* # over target */
-
-       return xfs_qm_shake_freelist(MAX(nfree, n));
-}
-
-
-/*------------------------------------------------------------------*/
-
-/*
- * Return a new incore dquot. Depending on the number of
- * dquots in the system, we either allocate a new one on the kernel heap,
- * or reclaim a free one.
- * Return value is B_TRUE if we allocated a new dquot, B_FALSE if we managed
- * to reclaim an existing one from the freelist.
- */
-boolean_t
-xfs_qm_dqalloc_incore(
-       xfs_dquot_t **O_dqpp)
-{
-       xfs_dquot_t     *dqp;
-
-       /*
-        * Check against high water mark to see if we want to pop
-        * a nincompoop dquot off the freelist.
-        */
-       if (atomic_read(&xfs_Gqm->qm_totaldquots) >= ndquot) {
-               /*
-                * Try to recycle a dquot from the freelist.
-                */
-               if ((dqp = xfs_qm_dqreclaim_one())) {
-                       XQM_STATS_INC(xqmstats.xs_qm_dqreclaims);
-                       /*
-                        * Just zero the core here. The rest will get
-                        * reinitialized by caller. XXX we shouldn't even
-                        * do this zero ...
-                        */
-                       memset(&dqp->q_core, 0, sizeof(dqp->q_core));
-                       *O_dqpp = dqp;
-                       return B_FALSE;
-               }
-               XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses);
+       mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
+       while (!list_empty(&xfs_Gqm->qm_dqfrlist)) {
+               if (nr_to_scan-- <= 0)
+                       break;
+               dqp = list_first_entry(&xfs_Gqm->qm_dqfrlist, struct xfs_dquot,
+                                      q_freelist);
+               xfs_qm_dqreclaim_one(dqp, &dispose_list);
        }
+       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
 
-       /*
-        * Allocate a brand new dquot on the kernel heap and return it
-        * to the caller to initialize.
-        */
-       ASSERT(xfs_Gqm->qm_dqzone != NULL);
-       *O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP);
-       atomic_inc(&xfs_Gqm->qm_totaldquots);
-
-       return B_TRUE;
+       while (!list_empty(&dispose_list)) {
+               dqp = list_first_entry(&dispose_list, struct xfs_dquot,
+                                      q_freelist);
+               list_del_init(&dqp->q_freelist);
+               xfs_qm_dqfree_one(dqp);
+       }
+out:
+       return (xfs_Gqm->qm_dqfrlist_cnt / 100) * sysctl_vfs_cache_pressure;
 }
 
-
 /*
  * Start a transaction and write the incore superblock changes to
  * disk. flags parameter indicates which fields have changed.
index 9b4f3adefbc5dca36d3157ca3f99b3ba92f22da8..9a9b997e1a0a294bd6f180ccaac011f2ec49a517 100644 (file)
 struct xfs_qm;
 struct xfs_inode;
 
-extern uint            ndquot;
 extern struct mutex    xfs_Gqm_lock;
 extern struct xfs_qm   *xfs_Gqm;
 extern kmem_zone_t     *qm_dqzone;
 extern kmem_zone_t     *qm_dqtrxzone;
 
-/*
- * Ditto, for xfs_qm_dqreclaim_one.
- */
-#define XFS_QM_RECLAIM_MAX_RESTARTS    4
-
-/*
- * Ideal ratio of free to in use dquots. Quota manager makes an attempt
- * to keep this balance.
- */
-#define XFS_QM_DQFREE_RATIO            2
-
 /*
  * Dquot hashtable constants/threshold values.
  */
@@ -74,7 +62,6 @@ typedef struct xfs_qm {
        int              qm_dqfrlist_cnt;
        atomic_t         qm_totaldquots; /* total incore dquots */
        uint             qm_nrefs;       /* file systems with quota on */
-       int              qm_dqfree_ratio;/* ratio of free to inuse dquots */
        kmem_zone_t     *qm_dqzone;      /* dquot mem-alloc zone */
        kmem_zone_t     *qm_dqtrxzone;   /* t_dqinfo of transactions */
 } xfs_qm_t;
@@ -143,7 +130,6 @@ extern int          xfs_qm_quotacheck(xfs_mount_t *);
 extern int             xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
 
 /* dquot stuff */
-extern boolean_t       xfs_qm_dqalloc_incore(xfs_dquot_t **);
 extern int             xfs_qm_dqpurge_all(xfs_mount_t *, uint);
 extern void            xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
 
index 8671a0b32644010a04e98f64518c63050add8048..5729ba570877f71fff899cfa0f373b581ed02866 100644 (file)
@@ -42,9 +42,9 @@ static int xqm_proc_show(struct seq_file *m, void *v)
 {
        /* maximum; incore; ratio free to inuse; freelist */
        seq_printf(m, "%d\t%d\t%d\t%u\n",
-                       ndquot,
+                       0,
                        xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
-                       xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
+                       0,
                        xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0);
        return 0;
 }
index 5cc3dde1bc9039de237a102c466b1fb4aa249cf8..711a86e39ff046d302a5ff14695882b65bcb3e25 100644 (file)
@@ -31,6 +31,7 @@
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_inode.h"
+#include "xfs_inode_item.h"
 #include "xfs_itable.h"
 #include "xfs_bmap.h"
 #include "xfs_rtalloc.h"
@@ -263,13 +264,18 @@ xfs_qm_scall_trunc_qfile(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
-       error = xfs_itruncate_data(&tp, ip, 0);
+       ip->i_d.di_size = 0;
+       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+       error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
        if (error) {
                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
                                     XFS_TRANS_ABORT);
                goto out_unlock;
        }
 
+       ASSERT(ip->i_d.di_nextents == 0);
+
        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 
@@ -807,11 +813,11 @@ xfs_qm_export_dquot(
             (XFS_IS_OQUOTA_ENFORCED(mp) &&
                        (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) &&
            dst->d_id != 0) {
-               if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) &&
+               if (((int) dst->d_bcount > (int) dst->d_blk_softlimit) &&
                    (dst->d_blk_softlimit > 0)) {
                        ASSERT(dst->d_btimer != 0);
                }
-               if (((int) dst->d_icount >= (int) dst->d_ino_softlimit) &&
+               if (((int) dst->d_icount > (int) dst->d_ino_softlimit) &&
                    (dst->d_ino_softlimit > 0)) {
                        ASSERT(dst->d_itimer != 0);
                }
index 281961c1d81a73df18ab8dcf31c39e6be3d94588..ee5b695c99a700275683d26ac78acd6351c9cc1f 100644 (file)
@@ -828,14 +828,6 @@ xfs_fs_inode_init_once(
        /* xfs inode */
        atomic_set(&ip->i_pincount, 0);
        spin_lock_init(&ip->i_flags_lock);
-       init_waitqueue_head(&ip->i_ipin_wait);
-       /*
-        * Because we want to use a counting completion, complete
-        * the flush completion once to allow a single access to
-        * the flush completion without blocking.
-        */
-       init_completion(&ip->i_flush);
-       complete(&ip->i_flush);
 
        mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
                     "xfsino", ip->i_ino);
index 72c01a1c16e7d16ca0a49e284addf7d884dbfea6..40b75eecd2b4b376253e0e9408e42bc475e63f9b 100644 (file)
@@ -707,14 +707,13 @@ xfs_reclaim_inode_grab(
                return 1;
 
        /*
-        * do some unlocked checks first to avoid unnecessary lock traffic.
-        * The first is a flush lock check, the second is a already in reclaim
-        * check. Only do these checks if we are not going to block on locks.
+        * If we are asked for non-blocking operation, do unlocked checks to
+        * see if the inode already is being flushed or in reclaim to avoid
+        * lock traffic.
         */
        if ((flags & SYNC_TRYLOCK) &&
-           (!ip->i_flush.done || __xfs_iflags_test(ip, XFS_IRECLAIM))) {
+           __xfs_iflags_test(ip, XFS_IFLOCK | XFS_IRECLAIM))
                return 1;
-       }
 
        /*
         * The radix tree lock here protects a thread in xfs_iget from racing
index a9d5b1e06efee95920e0bc0dd7b75c6f867b537b..bb134a819930c72448e37cc62de3fb98ec971835 100644 (file)
@@ -733,11 +733,10 @@ DEFINE_EVENT(xfs_dquot_class, name, \
 DEFINE_DQUOT_EVENT(xfs_dqadjust);
 DEFINE_DQUOT_EVENT(xfs_dqreclaim_want);
 DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty);
-DEFINE_DQUOT_EVENT(xfs_dqreclaim_unlink);
+DEFINE_DQUOT_EVENT(xfs_dqreclaim_busy);
+DEFINE_DQUOT_EVENT(xfs_dqreclaim_done);
 DEFINE_DQUOT_EVENT(xfs_dqattach_found);
 DEFINE_DQUOT_EVENT(xfs_dqattach_get);
-DEFINE_DQUOT_EVENT(xfs_dqinit);
-DEFINE_DQUOT_EVENT(xfs_dqreuse);
 DEFINE_DQUOT_EVENT(xfs_dqalloc);
 DEFINE_DQUOT_EVENT(xfs_dqtobp_read);
 DEFINE_DQUOT_EVENT(xfs_dqread);
@@ -891,7 +890,6 @@ DECLARE_EVENT_CLASS(xfs_file_class,
                __field(dev_t, dev)
                __field(xfs_ino_t, ino)
                __field(xfs_fsize_t, size)
-               __field(xfs_fsize_t, new_size)
                __field(loff_t, offset)
                __field(size_t, count)
                __field(int, flags)
@@ -900,17 +898,15 @@ DECLARE_EVENT_CLASS(xfs_file_class,
                __entry->dev = VFS_I(ip)->i_sb->s_dev;
                __entry->ino = ip->i_ino;
                __entry->size = ip->i_d.di_size;
-               __entry->new_size = ip->i_new_size;
                __entry->offset = offset;
                __entry->count = count;
                __entry->flags = flags;
        ),
-       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+       TP_printk("dev %d:%d ino 0x%llx size 0x%llx "
                  "offset 0x%llx count 0x%zx ioflags %s",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __entry->size,
-                 __entry->new_size,
                  __entry->offset,
                  __entry->count,
                  __print_flags(__entry->flags, "|", XFS_IO_FLAGS))
@@ -978,7 +974,6 @@ DECLARE_EVENT_CLASS(xfs_imap_class,
                __field(dev_t, dev)
                __field(xfs_ino_t, ino)
                __field(loff_t, size)
-               __field(loff_t, new_size)
                __field(loff_t, offset)
                __field(size_t, count)
                __field(int, type)
@@ -990,7 +985,6 @@ DECLARE_EVENT_CLASS(xfs_imap_class,
                __entry->dev = VFS_I(ip)->i_sb->s_dev;
                __entry->ino = ip->i_ino;
                __entry->size = ip->i_d.di_size;
-               __entry->new_size = ip->i_new_size;
                __entry->offset = offset;
                __entry->count = count;
                __entry->type = type;
@@ -998,13 +992,11 @@ DECLARE_EVENT_CLASS(xfs_imap_class,
                __entry->startblock = irec ? irec->br_startblock : 0;
                __entry->blockcount = irec ? irec->br_blockcount : 0;
        ),
-       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
-                 "offset 0x%llx count %zd type %s "
-                 "startoff 0x%llx startblock %lld blockcount 0x%llx",
+       TP_printk("dev %d:%d ino 0x%llx size 0x%llx offset 0x%llx count %zd "
+                 "type %s startoff 0x%llx startblock %lld blockcount 0x%llx",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __entry->size,
-                 __entry->new_size,
                  __entry->offset,
                  __entry->count,
                  __print_symbolic(__entry->type, XFS_IO_TYPES),
@@ -1031,26 +1023,23 @@ DECLARE_EVENT_CLASS(xfs_simple_io_class,
                __field(xfs_ino_t, ino)
                __field(loff_t, isize)
                __field(loff_t, disize)
-               __field(loff_t, new_size)
                __field(loff_t, offset)
                __field(size_t, count)
        ),
        TP_fast_assign(
                __entry->dev = VFS_I(ip)->i_sb->s_dev;
                __entry->ino = ip->i_ino;
-               __entry->isize = ip->i_size;
+               __entry->isize = VFS_I(ip)->i_size;
                __entry->disize = ip->i_d.di_size;
-               __entry->new_size = ip->i_new_size;
                __entry->offset = offset;
                __entry->count = count;
        ),
-       TP_printk("dev %d:%d ino 0x%llx isize 0x%llx disize 0x%llx new_size 0x%llx "
+       TP_printk("dev %d:%d ino 0x%llx isize 0x%llx disize 0x%llx "
                  "offset 0x%llx count %zd",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __entry->isize,
                  __entry->disize,
-                 __entry->new_size,
                  __entry->offset,
                  __entry->count)
 );
@@ -1090,8 +1079,8 @@ DECLARE_EVENT_CLASS(xfs_itrunc_class,
 DEFINE_EVENT(xfs_itrunc_class, name, \
        TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), \
        TP_ARGS(ip, new_size))
-DEFINE_ITRUNC_EVENT(xfs_itruncate_data_start);
-DEFINE_ITRUNC_EVENT(xfs_itruncate_data_end);
+DEFINE_ITRUNC_EVENT(xfs_itruncate_extents_start);
+DEFINE_ITRUNC_EVENT(xfs_itruncate_extents_end);
 
 TRACE_EVENT(xfs_pagecache_inval,
        TP_PROTO(struct xfs_inode *ip, xfs_off_t start, xfs_off_t finish),
@@ -1568,7 +1557,6 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
                __field(xfs_ino_t, ino)
                __field(int, format)
                __field(int, nex)
-               __field(int, max_nex)
                __field(int, broot_size)
                __field(int, fork_off)
        ),
@@ -1578,18 +1566,16 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
                __entry->ino = ip->i_ino;
                __entry->format = ip->i_d.di_format;
                __entry->nex = ip->i_d.di_nextents;
-               __entry->max_nex = ip->i_df.if_ext_max;
                __entry->broot_size = ip->i_df.if_broot_bytes;
                __entry->fork_off = XFS_IFORK_BOFF(ip);
        ),
        TP_printk("dev %d:%d ino 0x%llx (%s), %s format, num_extents %d, "
-                 "Max in-fork extents %d, broot size %d, fork offset %d",
+                 "broot size %d, fork offset %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __print_symbolic(__entry->which, XFS_SWAPEXT_INODES),
                  __print_symbolic(__entry->format, XFS_INODE_FORMAT_STR),
                  __entry->nex,
-                 __entry->max_nex,
                  __entry->broot_size,
                  __entry->fork_off)
 )
index 329b06aba1c2c59ab1b973a3a956a3af23c68abf..7adcdf15ae0ce563b32eb37582fbdd79a8fdba15 100644 (file)
@@ -1151,8 +1151,8 @@ xfs_trans_add_item(
 {
        struct xfs_log_item_desc *lidp;
 
-       ASSERT(lip->li_mountp = tp->t_mountp);
-       ASSERT(lip->li_ailp = tp->t_mountp->m_ail);
+       ASSERT(lip->li_mountp == tp->t_mountp);
+       ASSERT(lip->li_ailp == tp->t_mountp->m_ail);
 
        lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP | KM_NOFS);
 
index 4d00ee67792db020ed4cf46fdb5812322f9ec8d2..c4ba366d24e65c8fde43fa7a6ca32b4735bce331 100644 (file)
@@ -649,12 +649,12 @@ xfs_trans_dqresv(
                         * nblks.
                         */
                        if (hardlimit > 0ULL &&
-                           hardlimit <= nblks + *resbcountp) {
+                           hardlimit < nblks + *resbcountp) {
                                xfs_quota_warn(mp, dqp, QUOTA_NL_BHARDWARN);
                                goto error_return;
                        }
                        if (softlimit > 0ULL &&
-                           softlimit <= nblks + *resbcountp) {
+                           softlimit < nblks + *resbcountp) {
                                if ((timer != 0 && get_seconds() > timer) ||
                                    (warns != 0 && warns >= warnlimit)) {
                                        xfs_quota_warn(mp, dqp,
@@ -677,11 +677,13 @@ xfs_trans_dqresv(
                        if (!softlimit)
                                softlimit = q->qi_isoftlimit;
 
-                       if (hardlimit > 0ULL && count >= hardlimit) {
+                       if (hardlimit > 0ULL &&
+                           hardlimit < ninos + count) {
                                xfs_quota_warn(mp, dqp, QUOTA_NL_IHARDWARN);
                                goto error_return;
                        }
-                       if (softlimit > 0ULL && count >= softlimit) {
+                       if (softlimit > 0ULL &&
+                           softlimit < ninos + count) {
                                if  ((timer != 0 && get_seconds() > timer) ||
                                     (warns != 0 && warns >= warnlimit)) {
                                        xfs_quota_warn(mp, dqp,
index f2fea868d4db5da562804b2a0a9bd212608af058..ebdb88840a47817b5704df2aaa0fefb8b11fd96e 100644 (file)
@@ -131,7 +131,8 @@ xfs_readlink(
                         __func__, (unsigned long long) ip->i_ino,
                         (long long) pathlen);
                ASSERT(0);
-               return XFS_ERROR(EFSCORRUPTED);
+               error = XFS_ERROR(EFSCORRUPTED);
+               goto out;
        }
 
 
@@ -175,7 +176,7 @@ xfs_free_eofblocks(
         * Figure out if there are any blocks beyond the end
         * of the file.  If not, then there is nothing to do.
         */
-       end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size));
+       end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
        last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
        if (last_fsb <= end_fsb)
                return 0;
@@ -226,7 +227,14 @@ xfs_free_eofblocks(
                xfs_ilock(ip, XFS_ILOCK_EXCL);
                xfs_trans_ijoin(tp, ip, 0);
 
-               error = xfs_itruncate_data(&tp, ip, ip->i_size);
+               /*
+                * Do not update the on-disk file size.  If we update the
+                * on-disk file size and then the system crashes before the
+                * contents of the file are flushed to disk then the files
+                * may be full of holes (ie NULL files bug).
+                */
+               error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK,
+                                             XFS_ISIZE(ip));
                if (error) {
                        /*
                         * If we get an error at this point we simply don't
@@ -540,8 +548,8 @@ xfs_release(
                return 0;
 
        if ((S_ISREG(ip->i_d.di_mode) &&
-            ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
-              ip->i_delayed_blks > 0)) &&
+            (VFS_I(ip)->i_size > 0 ||
+             (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
             (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
            (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
 
@@ -618,7 +626,7 @@ xfs_inactive(
         * only one with a reference to the inode.
         */
        truncate = ((ip->i_d.di_nlink == 0) &&
-           ((ip->i_d.di_size != 0) || (ip->i_size != 0) ||
+           ((ip->i_d.di_size != 0) || XFS_ISIZE(ip) != 0 ||
             (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
            S_ISREG(ip->i_d.di_mode));
 
@@ -632,12 +640,12 @@ xfs_inactive(
 
        if (ip->i_d.di_nlink != 0) {
                if ((S_ISREG(ip->i_d.di_mode) &&
-                     ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
-                       ip->i_delayed_blks > 0)) &&
-                     (ip->i_df.if_flags & XFS_IFEXTENTS) &&
-                    (!(ip->i_d.di_flags &
+                   (VFS_I(ip)->i_size > 0 ||
+                    (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
+                   (ip->i_df.if_flags & XFS_IFEXTENTS) &&
+                   (!(ip->i_d.di_flags &
                                (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
-                     (ip->i_delayed_blks != 0)))) {
+                    ip->i_delayed_blks != 0))) {
                        error = xfs_free_eofblocks(mp, ip, 0);
                        if (error)
                                return VN_INACTIVE_CACHE;
@@ -670,13 +678,18 @@ xfs_inactive(
                xfs_ilock(ip, XFS_ILOCK_EXCL);
                xfs_trans_ijoin(tp, ip, 0);
 
-               error = xfs_itruncate_data(&tp, ip, 0);
+               ip->i_d.di_size = 0;
+               xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+               error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
                if (error) {
                        xfs_trans_cancel(tp,
                                XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
                        xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
                        return VN_INACTIVE_CACHE;
                }
+
+               ASSERT(ip->i_d.di_nextents == 0);
        } else if (S_ISLNK(ip->i_d.di_mode)) {
 
                /*
@@ -1961,11 +1974,11 @@ xfs_zero_remaining_bytes(
         * since nothing can read beyond eof.  The space will
         * be zeroed when the file is extended anyway.
         */
-       if (startoff >= ip->i_size)
+       if (startoff >= XFS_ISIZE(ip))
                return 0;
 
-       if (endoff > ip->i_size)
-               endoff = ip->i_size;
+       if (endoff > XFS_ISIZE(ip))
+               endoff = XFS_ISIZE(ip);
 
        bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ?
                                        mp->m_rtdev_targp : mp->m_ddev_targp,
@@ -2260,7 +2273,7 @@ xfs_change_file_space(
                bf->l_start += offset;
                break;
        case 2: /*SEEK_END*/
-               bf->l_start += ip->i_size;
+               bf->l_start += XFS_ISIZE(ip);
                break;
        default:
                return XFS_ERROR(EINVAL);
@@ -2277,7 +2290,7 @@ xfs_change_file_space(
        bf->l_whence = 0;
 
        startoffset = bf->l_start;
-       fsize = ip->i_size;
+       fsize = XFS_ISIZE(ip);
 
        /*
         * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve
index fc1575fd4596e484c0fc44c7614e6decb5e8c6b6..5b5af0d30a9738a7cb938a04b839c3d6a5f5727e 100644 (file)
@@ -58,6 +58,7 @@
 #define METHOD_NAME__PRT        "_PRT"
 #define METHOD_NAME__CRS        "_CRS"
 #define METHOD_NAME__PRS        "_PRS"
+#define METHOD_NAME__AEI        "_AEI"
 #define METHOD_NAME__PRW        "_PRW"
 #define METHOD_NAME__SRS        "_SRS"
 
index 173972672175588c181718aef6cf7f1537c37758..451823cb88372b2130793abbbb4e17869af34faf 100644 (file)
@@ -15,6 +15,7 @@ extern int pxm_to_node(int);
 extern int node_to_pxm(int);
 extern void __acpi_map_pxm_to_node(int, int);
 extern int acpi_map_pxm_to_node(int);
+extern unsigned char acpi_srat_revision;
 
 #endif                         /* CONFIG_ACPI_NUMA */
 #endif                         /* __ACP_NUMA_H */
index 83062ed0ef2f7177285e6688a07e81db8c1a90e4..7c9aebe8a7aa27ebf091c1a0ec2470e1e23d7f0a 100644 (file)
@@ -218,9 +218,13 @@ acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width);
  */
 acpi_status
 acpi_os_read_memory(acpi_physical_address address, u32 * value, u32 width);
+acpi_status
+acpi_os_read_memory64(acpi_physical_address address, u64 *value, u32 width);
 
 acpi_status
 acpi_os_write_memory(acpi_physical_address address, u32 value, u32 width);
+acpi_status
+acpi_os_write_memory64(acpi_physical_address address, u64 value, u32 width);
 
 /*
  * Platform and hardware-independent PCI configuration space access
@@ -238,13 +242,6 @@ acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
 /*
  * Miscellaneous
  */
-acpi_status
-acpi_os_validate_address(u8 space_id, acpi_physical_address address,
-                        acpi_size length, char *name);
-acpi_status
-acpi_os_invalidate_address(u8 space_id, acpi_physical_address address,
-                        acpi_size length);
-
 u64 acpi_os_get_timer(void);
 
 acpi_status acpi_os_signal(u32 function, void *info);
index 7762bc2d8404370d27be30e362b031e4da26af4c..a28da35ba45ee3f1fd3bcdf2b8a7f64bbe5d2391 100644 (file)
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20110623
+#define ACPI_CA_VERSION                 0x20120111
 
 #include "actypes.h"
 #include "actbl.h"
@@ -74,6 +74,7 @@ extern u8 acpi_gbl_disable_auto_repair;
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;
 extern u8 acpi_gbl_system_awake_and_running;
+extern u8 acpi_gbl_reduced_hardware;   /* ACPI 5.0 */
 
 extern u32 acpi_rsdt_forced;
 /*
@@ -111,6 +112,11 @@ acpi_status acpi_install_interface(acpi_string interface_name);
 
 acpi_status acpi_remove_interface(acpi_string interface_name);
 
+u32
+acpi_check_address_range(acpi_adr_space_type space_id,
+                        acpi_physical_address address,
+                        acpi_size length, u8 warn);
+
 /*
  * ACPI Memory management
  */
@@ -276,12 +282,23 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler);
 acpi_status acpi_install_interface_handler(acpi_interface_handler handler);
 
 /*
- * Event interfaces
+ * Global Lock interfaces
  */
 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle);
 
 acpi_status acpi_release_global_lock(u32 handle);
 
+/*
+ * Interfaces to AML mutex objects
+ */
+acpi_status
+acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout);
+
+acpi_status acpi_release_mutex(acpi_handle handle, acpi_string pathname);
+
+/*
+ * Fixed Event interfaces
+ */
 acpi_status acpi_enable_event(u32 event, u32 flags);
 
 acpi_status acpi_disable_event(u32 event, u32 flags);
@@ -291,7 +308,7 @@ acpi_status acpi_clear_event(u32 event);
 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
 
 /*
- * GPE Interfaces
+ * General Purpose Event (GPE) Interfaces
  */
 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number);
 
@@ -345,6 +362,10 @@ acpi_status
 acpi_get_possible_resources(acpi_handle device, struct acpi_buffer *ret_buffer);
 #endif
 
+acpi_status
+acpi_get_event_resources(acpi_handle device_handle,
+                        struct acpi_buffer *ret_buffer);
+
 acpi_status
 acpi_walk_resources(acpi_handle device,
                    char *name,
@@ -360,6 +381,11 @@ acpi_status
 acpi_resource_to_address64(struct acpi_resource *resource,
                           struct acpi_resource_address64 *out);
 
+acpi_status
+acpi_buffer_to_resource(u8 *aml_buffer,
+                       u16 aml_buffer_length,
+                       struct acpi_resource **resource_ptr);
+
 /*
  * Hardware (ACPI device) interfaces
  */
index 0a66cc45dd6b79a0fdb17be3368b87cdd1c646f5..3506e39a66b15962a5d6de4ab54a8117ff0267bb 100644 (file)
@@ -61,11 +61,14 @@ typedef u32 acpi_rsdesc_size;       /* Max Resource Descriptor size is (Length+3) = (6
 #define ACPI_WRITE_COMBINING_MEMORY     (u8) 0x02
 #define ACPI_PREFETCHABLE_MEMORY        (u8) 0x03
 
+/*! [Begin] no source code translation */
 /*
  * IO Attributes
- * The ISA IO ranges are:     n000-n0_fFh, n400-n4_fFh, n800-n8_fFh, n_c00-n_cFFh.
- * The non-ISA IO ranges are: n100-n3_fFh, n500-n7_fFh, n900-n_bFFh, n_cd0-n_fFFh.
+ * The ISA IO ranges are:     n000-n0FFh,  n400-n4FFh, n800-n8FFh, nC00-nCFFh.
+ * The non-ISA IO ranges are: n100-n3FFh,  n500-n7FFh, n900-nBFFh, nCD0-nFFFh.
  */
+/*! [End] no source code translation !*/
+
 #define ACPI_NON_ISA_ONLY_RANGES        (u8) 0x01
 #define ACPI_ISA_ONLY_RANGES            (u8) 0x02
 #define ACPI_ENTIRE_RANGE               (ACPI_NON_ISA_ONLY_RANGES | ACPI_ISA_ONLY_RANGES)
@@ -81,16 +84,26 @@ typedef u32 acpi_rsdesc_size;       /* Max Resource Descriptor size is (Length+3) = (6
 #define ACPI_DECODE_16                  (u8) 0x01      /* 16-bit IO address decode */
 
 /*
- * IRQ Attributes
+ * Interrupt attributes - used in multiple descriptors
  */
+
+/* Triggering */
+
 #define ACPI_LEVEL_SENSITIVE            (u8) 0x00
 #define ACPI_EDGE_SENSITIVE             (u8) 0x01
 
+/* Polarity */
+
 #define ACPI_ACTIVE_HIGH                (u8) 0x00
 #define ACPI_ACTIVE_LOW                 (u8) 0x01
+#define ACPI_ACTIVE_BOTH                (u8) 0x02
+
+/* Sharing */
 
 #define ACPI_EXCLUSIVE                  (u8) 0x00
 #define ACPI_SHARED                     (u8) 0x01
+#define ACPI_EXCLUSIVE_AND_WAKE         (u8) 0x02
+#define ACPI_SHARED_AND_WAKE            (u8) 0x03
 
 /*
  * DMA Attributes
@@ -127,6 +140,8 @@ typedef u32 acpi_rsdesc_size;       /* Max Resource Descriptor size is (Length+3) = (6
 #define ACPI_POS_DECODE                 (u8) 0x00
 #define ACPI_SUB_DECODE                 (u8) 0x01
 
+/* Producer/Consumer */
+
 #define ACPI_PRODUCER                   (u8) 0x00
 #define ACPI_CONSUMER                   (u8) 0x01
 
@@ -192,6 +207,21 @@ struct acpi_resource_fixed_io {
        u8 address_length;
 };
 
+struct acpi_resource_fixed_dma {
+       u16 request_lines;
+       u16 channels;
+       u8 width;
+};
+
+/* Values for Width field above */
+
+#define ACPI_DMA_WIDTH8                         0
+#define ACPI_DMA_WIDTH16                        1
+#define ACPI_DMA_WIDTH32                        2
+#define ACPI_DMA_WIDTH64                        3
+#define ACPI_DMA_WIDTH128                       4
+#define ACPI_DMA_WIDTH256                       5
+
 struct acpi_resource_vendor {
        u16 byte_length;
        u8 byte_data[1];
@@ -329,6 +359,166 @@ struct acpi_resource_generic_register {
        u64 address;
 };
 
+struct acpi_resource_gpio {
+       u8 revision_id;
+       u8 connection_type;
+       u8 producer_consumer;   /* For values, see Producer/Consumer above */
+       u8 pin_config;
+       u8 sharable;            /* For values, see Interrupt Attributes above */
+       u8 io_restriction;
+       u8 triggering;          /* For values, see Interrupt Attributes above */
+       u8 polarity;            /* For values, see Interrupt Attributes above */
+       u16 drive_strength;
+       u16 debounce_timeout;
+       u16 pin_table_length;
+       u16 vendor_length;
+       struct acpi_resource_source resource_source;
+       u16 *pin_table;
+       u8 *vendor_data;
+};
+
+/* Values for GPIO connection_type field above */
+
+#define ACPI_RESOURCE_GPIO_TYPE_INT             0
+#define ACPI_RESOURCE_GPIO_TYPE_IO              1
+
+/* Values for pin_config field above */
+
+#define ACPI_PIN_CONFIG_DEFAULT                 0
+#define ACPI_PIN_CONFIG_PULLUP                  1
+#define ACPI_PIN_CONFIG_PULLDOWN                2
+#define ACPI_PIN_CONFIG_NOPULL                  3
+
+/* Values for io_restriction field above */
+
+#define ACPI_IO_RESTRICT_NONE                   0
+#define ACPI_IO_RESTRICT_INPUT                  1
+#define ACPI_IO_RESTRICT_OUTPUT                 2
+#define ACPI_IO_RESTRICT_NONE_PRESERVE          3
+
+/* Common structure for I2C, SPI, and UART serial descriptors */
+
+#define ACPI_RESOURCE_SERIAL_COMMON \
+       u8                                      revision_id; \
+       u8                                      type; \
+       u8                                      producer_consumer;   /* For values, see Producer/Consumer above */\
+       u8                                      slave_mode; \
+       u8                                      type_revision_id; \
+       u16                                     type_data_length; \
+       u16                                     vendor_length; \
+       struct acpi_resource_source             resource_source; \
+       u8                                      *vendor_data;
+
+struct acpi_resource_common_serialbus {
+ACPI_RESOURCE_SERIAL_COMMON};
+
+/* Values for the Type field above */
+
+#define ACPI_RESOURCE_SERIAL_TYPE_I2C           1
+#define ACPI_RESOURCE_SERIAL_TYPE_SPI           2
+#define ACPI_RESOURCE_SERIAL_TYPE_UART          3
+
+/* Values for slave_mode field above */
+
+#define ACPI_CONTROLLER_INITIATED               0
+#define ACPI_DEVICE_INITIATED                   1
+
+struct acpi_resource_i2c_serialbus {
+       ACPI_RESOURCE_SERIAL_COMMON u8 access_mode;
+       u16 slave_address;
+       u32 connection_speed;
+};
+
+/* Values for access_mode field above */
+
+#define ACPI_I2C_7BIT_MODE                      0
+#define ACPI_I2C_10BIT_MODE                     1
+
+struct acpi_resource_spi_serialbus {
+       ACPI_RESOURCE_SERIAL_COMMON u8 wire_mode;
+       u8 device_polarity;
+       u8 data_bit_length;
+       u8 clock_phase;
+       u8 clock_polarity;
+       u16 device_selection;
+       u32 connection_speed;
+};
+
+/* Values for wire_mode field above */
+
+#define ACPI_SPI_4WIRE_MODE                     0
+#define ACPI_SPI_3WIRE_MODE                     1
+
+/* Values for device_polarity field above */
+
+#define ACPI_SPI_ACTIVE_LOW                     0
+#define ACPI_SPI_ACTIVE_HIGH                    1
+
+/* Values for clock_phase field above */
+
+#define ACPI_SPI_FIRST_PHASE                    0
+#define ACPI_SPI_SECOND_PHASE                   1
+
+/* Values for clock_polarity field above */
+
+#define ACPI_SPI_START_LOW                      0
+#define ACPI_SPI_START_HIGH                     1
+
+struct acpi_resource_uart_serialbus {
+       ACPI_RESOURCE_SERIAL_COMMON u8 endian;
+       u8 data_bits;
+       u8 stop_bits;
+       u8 flow_control;
+       u8 parity;
+       u8 lines_enabled;
+       u16 rx_fifo_size;
+       u16 tx_fifo_size;
+       u32 default_baud_rate;
+};
+
+/* Values for Endian field above */
+
+#define ACPI_UART_LITTLE_ENDIAN                 0
+#define ACPI_UART_BIG_ENDIAN                    1
+
+/* Values for data_bits field above */
+
+#define ACPI_UART_5_DATA_BITS                   0
+#define ACPI_UART_6_DATA_BITS                   1
+#define ACPI_UART_7_DATA_BITS                   2
+#define ACPI_UART_8_DATA_BITS                   3
+#define ACPI_UART_9_DATA_BITS                   4
+
+/* Values for stop_bits field above */
+
+#define ACPI_UART_NO_STOP_BITS                  0
+#define ACPI_UART_1_STOP_BIT                    1
+#define ACPI_UART_1P5_STOP_BITS                 2
+#define ACPI_UART_2_STOP_BITS                   3
+
+/* Values for flow_control field above */
+
+#define ACPI_UART_FLOW_CONTROL_NONE             0
+#define ACPI_UART_FLOW_CONTROL_HW               1
+#define ACPI_UART_FLOW_CONTROL_XON_XOFF         2
+
+/* Values for Parity field above */
+
+#define ACPI_UART_PARITY_NONE                   0
+#define ACPI_UART_PARITY_EVEN                   1
+#define ACPI_UART_PARITY_ODD                    2
+#define ACPI_UART_PARITY_MARK                   3
+#define ACPI_UART_PARITY_SPACE                  4
+
+/* Values for lines_enabled bitfield above */
+
+#define ACPI_UART_CARRIER_DETECT                (1<<2)
+#define ACPI_UART_RING_INDICATOR                (1<<3)
+#define ACPI_UART_DATA_SET_READY                (1<<4)
+#define ACPI_UART_DATA_TERMINAL_READY           (1<<5)
+#define ACPI_UART_CLEAR_TO_SEND                 (1<<6)
+#define ACPI_UART_REQUEST_TO_SEND               (1<<7)
+
 /* ACPI_RESOURCE_TYPEs */
 
 #define ACPI_RESOURCE_TYPE_IRQ                  0
@@ -348,7 +538,10 @@ struct acpi_resource_generic_register {
 #define ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64   14     /* ACPI 3.0 */
 #define ACPI_RESOURCE_TYPE_EXTENDED_IRQ         15
 #define ACPI_RESOURCE_TYPE_GENERIC_REGISTER     16
-#define ACPI_RESOURCE_TYPE_MAX                  16
+#define ACPI_RESOURCE_TYPE_GPIO                 17     /* ACPI 5.0 */
+#define ACPI_RESOURCE_TYPE_FIXED_DMA            18     /* ACPI 5.0 */
+#define ACPI_RESOURCE_TYPE_SERIAL_BUS           19     /* ACPI 5.0 */
+#define ACPI_RESOURCE_TYPE_MAX                  19
 
 /* Master union for resource descriptors */
 
@@ -358,6 +551,7 @@ union acpi_resource_data {
        struct acpi_resource_start_dependent start_dpf;
        struct acpi_resource_io io;
        struct acpi_resource_fixed_io fixed_io;
+       struct acpi_resource_fixed_dma fixed_dma;
        struct acpi_resource_vendor vendor;
        struct acpi_resource_vendor_typed vendor_typed;
        struct acpi_resource_end_tag end_tag;
@@ -370,6 +564,11 @@ union acpi_resource_data {
        struct acpi_resource_extended_address64 ext_address64;
        struct acpi_resource_extended_irq extended_irq;
        struct acpi_resource_generic_register generic_reg;
+       struct acpi_resource_gpio gpio;
+       struct acpi_resource_i2c_serialbus i2c_serial_bus;
+       struct acpi_resource_spi_serialbus spi_serial_bus;
+       struct acpi_resource_uart_serialbus uart_serial_bus;
+       struct acpi_resource_common_serialbus common_serial_bus;
 
        /* Common fields */
 
index f1380287ed4d821474f58a39c372fca6cb5909a1..8e1b92f6f650332e6130486d6b7e7a5bd3f1b3f8 100644 (file)
@@ -255,6 +255,8 @@ struct acpi_table_fadt {
        struct acpi_generic_address xpm_timer_block;    /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */
        struct acpi_generic_address xgpe0_block;        /* 64-bit Extended General Purpose Event 0 Reg Blk address */
        struct acpi_generic_address xgpe1_block;        /* 64-bit Extended General Purpose Event 1 Reg Blk address */
+       struct acpi_generic_address sleep_control;      /* 64-bit Sleep Control register */
+       struct acpi_generic_address sleep_status;       /* 64-bit Sleep Status register */
 };
 
 /* Masks for FADT Boot Architecture Flags (boot_flags) */
@@ -264,6 +266,7 @@ struct acpi_table_fadt {
 #define ACPI_FADT_NO_VGA            (1<<2)     /* 02: [V4] It is not safe to probe for VGA hardware */
 #define ACPI_FADT_NO_MSI            (1<<3)     /* 03: [V4] Message Signaled Interrupts (MSI) must not be enabled */
 #define ACPI_FADT_NO_ASPM           (1<<4)     /* 04: [V4] PCIe ASPM control must not be enabled */
+#define ACPI_FADT_NO_CMOS_RTC       (1<<5)     /* 05: [V5] No CMOS real-time clock present */
 
 #define FADT2_REVISION_ID               3
 
@@ -289,6 +292,8 @@ struct acpi_table_fadt {
 #define ACPI_FADT_REMOTE_POWER_ON   (1<<17)    /* 17: [V4] System is compatible with remote power on (ACPI 3.0) */
 #define ACPI_FADT_APIC_CLUSTER      (1<<18)    /* 18: [V4] All local APICs must use cluster model (ACPI 3.0) */
 #define ACPI_FADT_APIC_PHYSICAL     (1<<19)    /* 19: [V4] All local x_aPICs must use physical dest mode (ACPI 3.0) */
+#define ACPI_FADT_HW_REDUCED        (1<<20)    /* 20: [V5] ACPI hardware is not implemented (ACPI 5.0) */
+#define ACPI_FADT_LOW_POWER_S0      (1<<21)    /* 21: [V5] S0 power savings are equal or better than S3 (ACPI 5.0) */
 
 /* Values for preferred_profile (Preferred Power Management Profiles) */
 
@@ -299,14 +304,16 @@ enum acpi_prefered_pm_profiles {
        PM_WORKSTATION = 3,
        PM_ENTERPRISE_SERVER = 4,
        PM_SOHO_SERVER = 5,
-       PM_APPLIANCE_PC = 6
+       PM_APPLIANCE_PC = 6,
+       PM_PERFORMANCE_SERVER = 7,
+       PM_TABLET = 8
 };
 
 /* Reset to default packing */
 
 #pragma pack()
 
-#define ACPI_FADT_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_fadt, f)
+#define ACPI_FADT_OFFSET(f)             (u16) ACPI_OFFSET (struct acpi_table_fadt, f)
 
 /*
  * Internal table-related structures
@@ -342,6 +349,7 @@ struct acpi_table_desc {
 
 #include <acpi/actbl1.h>
 #include <acpi/actbl2.h>
+#include <acpi/actbl3.h>
 
 /*
  * Sizes of the various flavors of FADT. We need to look closely
@@ -351,12 +359,15 @@ struct acpi_table_desc {
  * FADT is the bottom line as to what the version really is.
  *
  * For reference, the values below are as follows:
- *     FADT V1  size: 0x74
- *     FADT V2  size: 0x84
- *     FADT V3+ size: 0xF4
+ *     FADT V1  size: 0x074
+ *     FADT V2  size: 0x084
+ *     FADT V3  size: 0x0F4
+ *     FADT V4  size: 0x0F4
+ *     FADT V5  size: 0x10C
  */
 #define ACPI_FADT_V1_SIZE       (u32) (ACPI_FADT_OFFSET (flags) + 4)
 #define ACPI_FADT_V2_SIZE       (u32) (ACPI_FADT_OFFSET (reserved4[0]) + 3)
-#define ACPI_FADT_V3_SIZE       (u32) (sizeof (struct acpi_table_fadt))
+#define ACPI_FADT_V3_SIZE       (u32) (ACPI_FADT_OFFSET (sleep_control))
+#define ACPI_FADT_V5_SIZE       (u32) (sizeof (struct acpi_table_fadt))
 
 #endif                         /* __ACTBL_H__ */
index 7504bc99b29b7359f9ec503a6c0def183c98c2c9..71e747beac8f3e016fa3719f4b75e7706a3b64fb 100644 (file)
@@ -228,7 +228,8 @@ enum acpi_einj_actions {
        ACPI_EINJ_EXECUTE_OPERATION = 5,
        ACPI_EINJ_CHECK_BUSY_STATUS = 6,
        ACPI_EINJ_GET_COMMAND_STATUS = 7,
-       ACPI_EINJ_ACTION_RESERVED = 8,  /* 8 and greater are reserved */
+       ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS = 8,
+       ACPI_EINJ_ACTION_RESERVED = 9,  /* 9 and greater are reserved */
        ACPI_EINJ_TRIGGER_ERROR = 0xFF  /* Except for this value */
 };
 
@@ -240,7 +241,27 @@ enum acpi_einj_instructions {
        ACPI_EINJ_WRITE_REGISTER = 2,
        ACPI_EINJ_WRITE_REGISTER_VALUE = 3,
        ACPI_EINJ_NOOP = 4,
-       ACPI_EINJ_INSTRUCTION_RESERVED = 5      /* 5 and greater are reserved */
+       ACPI_EINJ_FLUSH_CACHELINE = 5,
+       ACPI_EINJ_INSTRUCTION_RESERVED = 6      /* 6 and greater are reserved */
+};
+
+struct acpi_einj_error_type_with_addr {
+       u32 error_type;
+       u32 vendor_struct_offset;
+       u32 flags;
+       u32 apic_id;
+       u64 address;
+       u64 range;
+       u32 pcie_id;
+};
+
+struct acpi_einj_vendor {
+       u32 length;
+       u32 pcie_id;
+       u16 vendor_id;
+       u16 device_id;
+       u8 revision_id;
+       u8 reserved[3];
 };
 
 /* EINJ Trigger Error Action Table */
@@ -275,6 +296,7 @@ enum acpi_einj_command_status {
 #define ACPI_EINJ_PLATFORM_CORRECTABLE      (1<<9)
 #define ACPI_EINJ_PLATFORM_UNCORRECTABLE    (1<<10)
 #define ACPI_EINJ_PLATFORM_FATAL            (1<<11)
+#define ACPI_EINJ_VENDOR_DEFINED            (1<<31)
 
 /*******************************************************************************
  *
@@ -631,7 +653,9 @@ enum acpi_madt_type {
        ACPI_MADT_TYPE_INTERRUPT_SOURCE = 8,
        ACPI_MADT_TYPE_LOCAL_X2APIC = 9,
        ACPI_MADT_TYPE_LOCAL_X2APIC_NMI = 10,
-       ACPI_MADT_TYPE_RESERVED = 11    /* 11 and greater are reserved */
+       ACPI_MADT_TYPE_GENERIC_INTERRUPT = 11,
+       ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR = 12,
+       ACPI_MADT_TYPE_RESERVED = 13    /* 13 and greater are reserved */
 };
 
 /*
@@ -752,11 +776,36 @@ struct acpi_madt_local_x2apic_nmi {
        u8 reserved[3];
 };
 
+/* 11: Generic Interrupt (ACPI 5.0) */
+
+struct acpi_madt_generic_interrupt {
+       struct acpi_subtable_header header;
+       u16 reserved;           /* Reserved - must be zero */
+       u32 gic_id;
+       u32 uid;
+       u32 flags;
+       u32 parking_version;
+       u32 performance_interrupt;
+       u64 parked_address;
+       u64 base_address;
+};
+
+/* 12: Generic Distributor (ACPI 5.0) */
+
+struct acpi_madt_generic_distributor {
+       struct acpi_subtable_header header;
+       u16 reserved;           /* Reserved - must be zero */
+       u32 gic_id;
+       u64 base_address;
+       u32 global_irq_base;
+       u32 reserved2;          /* Reserved - must be zero */
+};
+
 /*
  * Common flags fields for MADT subtables
  */
 
-/* MADT Local APIC flags (lapic_flags) */
+/* MADT Local APIC flags (lapic_flags) and GIC flags */
 
 #define ACPI_MADT_ENABLED           (1)        /* 00: Processor is usable if set */
 
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
new file mode 100644 (file)
index 0000000..c22ce80
--- /dev/null
@@ -0,0 +1,552 @@
+/******************************************************************************
+ *
+ * Name: actbl3.h - ACPI Table Definitions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#ifndef __ACTBL3_H__
+#define __ACTBL3_H__
+
+/*******************************************************************************
+ *
+ * Additional ACPI Tables (3)
+ *
+ * These tables are not consumed directly by the ACPICA subsystem, but are
+ * included here to support device drivers and the AML disassembler.
+ *
+ * The tables in this file are fully defined within the ACPI specification.
+ *
+ ******************************************************************************/
+
+/*
+ * Values for description table header signatures for tables defined in this
+ * file. Useful because they make it more difficult to inadvertently type in
+ * the wrong signature.
+ */
+#define ACPI_SIG_BGRT           "BGRT" /* Boot Graphics Resource Table */
+#define ACPI_SIG_DRTM           "DRTM" /* Dynamic Root of Trust for Measurement table */
+#define ACPI_SIG_FPDT           "FPDT" /* Firmware Performance Data Table */
+#define ACPI_SIG_GTDT           "GTDT" /* Generic Timer Description Table */
+#define ACPI_SIG_MPST           "MPST" /* Memory Power State Table */
+#define ACPI_SIG_PCCT           "PCCT" /* Platform Communications Channel Table */
+#define ACPI_SIG_PMTT           "PMTT" /* Platform Memory Topology Table */
+#define ACPI_SIG_RASF           "RASF" /* RAS Feature table */
+
+#define ACPI_SIG_S3PT           "S3PT" /* S3 Performance (sub)Table */
+#define ACPI_SIG_PCCS           "PCC"  /* PCC Shared Memory Region */
+
+/* Reserved table signatures */
+
+#define ACPI_SIG_CSRT           "CSRT" /* Core System Resources Table */
+#define ACPI_SIG_DBG2           "DBG2" /* Debug Port table 2 */
+#define ACPI_SIG_MATR           "MATR" /* Memory Address Translation Table */
+#define ACPI_SIG_MSDM           "MSDM" /* Microsoft Data Management Table */
+#define ACPI_SIG_WPBT           "WPBT" /* Windows Platform Binary Table */
+
+/*
+ * All tables must be byte-packed to match the ACPI specification, since
+ * the tables are provided by the system BIOS.
+ */
+#pragma pack(1)
+
+/*
+ * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
+ * This is the only type that is even remotely portable. Anything else is not
+ * portable, so do not use any other bitfield types.
+ */
+
+/*******************************************************************************
+ *
+ * BGRT - Boot Graphics Resource Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_bgrt {
+       struct acpi_table_header header;        /* Common ACPI table header */
+       u16 version;
+       u8 status;
+       u8 image_type;
+       u64 image_address;
+       u32 image_offset_x;
+       u32 image_offset_y;
+};
+
+/*******************************************************************************
+ *
+ * DRTM - Dynamic Root of Trust for Measurement table
+ *
+ ******************************************************************************/
+
+struct acpi_table_drtm {
+       struct acpi_table_header header;        /* Common ACPI table header */
+       u64 entry_base_address;
+       u64 entry_length;
+       u32 entry_address32;
+       u64 entry_address64;
+       u64 exit_address;
+       u64 log_area_address;
+       u32 log_area_length;
+       u64 arch_dependent_address;
+       u32 flags;
+};
+
+/* 1) Validated Tables List */
+
+struct acpi_drtm_vtl_list {
+       u32 validated_table_list_count;
+};
+
+/* 2) Resources List */
+
+struct acpi_drtm_resource_list {
+       u32 resource_list_count;
+};
+
+/* 3) Platform-specific Identifiers List */
+
+struct acpi_drtm_id_list {
+       u32 id_list_count;
+};
+
+/*******************************************************************************
+ *
+ * FPDT - Firmware Performance Data Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_fpdt {
+       struct acpi_table_header header;        /* Common ACPI table header */
+};
+
+/* FPDT subtable header */
+
+struct acpi_fpdt_header {
+       u16 type;
+       u8 length;
+       u8 revision;
+};
+
+/* Values for Type field above */
+
+enum acpi_fpdt_type {
+       ACPI_FPDT_TYPE_BOOT = 0,
+       ACPI_FPDT_TYPE_S3PERF = 1,
+};
+
+/*
+ * FPDT subtables
+ */
+
+/* 0: Firmware Basic Boot Performance Record */
+
+struct acpi_fpdt_boot {
+       struct acpi_fpdt_header header;
+       u8 reserved[4];
+       u64 reset_end;
+       u64 load_start;
+       u64 startup_start;
+       u64 exit_services_entry;
+       u64 exit_services_exit;
+};
+
+/* 1: S3 Performance Table Pointer Record */
+
+struct acpi_fpdt_s3pt_ptr {
+       struct acpi_fpdt_header header;
+       u8 reserved[4];
+       u64 address;
+};
+
+/*
+ * S3PT - S3 Performance Table. This table is pointed to by the
+ * FPDT S3 Pointer Record above.
+ */
+struct acpi_table_s3pt {
+       u8 signature[4];        /* "S3PT" */
+       u32 length;
+};
+
+/*
+ * S3PT Subtables
+ */
+struct acpi_s3pt_header {
+       u16 type;
+       u8 length;
+       u8 revision;
+};
+
+/* Values for Type field above */
+
+enum acpi_s3pt_type {
+       ACPI_S3PT_TYPE_RESUME = 0,
+       ACPI_S3PT_TYPE_SUSPEND = 1,
+};
+
+struct acpi_s3pt_resume {
+       struct acpi_s3pt_header header;
+       u32 resume_count;
+       u64 full_resume;
+       u64 average_resume;
+};
+
+struct acpi_s3pt_suspend {
+       struct acpi_s3pt_header header;
+       u64 suspend_start;
+       u64 suspend_end;
+};
+
+/*******************************************************************************
+ *
+ * GTDT - Generic Timer Description Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_gtdt {
+       struct acpi_table_header header;        /* Common ACPI table header */
+       u64 address;
+       u32 flags;
+       u32 secure_pl1_interrupt;
+       u32 secure_pl1_flags;
+       u32 non_secure_pl1_interrupt;
+       u32 non_secure_pl1_flags;
+       u32 virtual_timer_interrupt;
+       u32 virtual_timer_flags;
+       u32 non_secure_pl2_interrupt;
+       u32 non_secure_pl2_flags;
+};
+
+/* Values for Flags field above */
+
+#define ACPI_GTDT_MAPPED_BLOCK_PRESENT      1
+
+/* Values for all "TimerFlags" fields above */
+
+#define ACPI_GTDT_INTERRUPT_MODE            1
+#define ACPI_GTDT_INTERRUPT_POLARITY        2
+
+/*******************************************************************************
+ *
+ * MPST - Memory Power State Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+#define ACPI_MPST_CHANNEL_INFO \
+       u16                             reserved1; \
+       u8                              channel_id; \
+       u8                              reserved2; \
+       u16                             power_node_count;
+
+/* Main table */
+
+struct acpi_table_mpst {
+       struct acpi_table_header header;        /* Common ACPI table header */
+        ACPI_MPST_CHANNEL_INFO /* Platform Communication Channel */
+};
+
+/* Memory Platform Communication Channel Info */
+
+struct acpi_mpst_channel {
+       ACPI_MPST_CHANNEL_INFO  /* Platform Communication Channel */
+};
+
+/* Memory Power Node Structure */
+
+struct acpi_mpst_power_node {
+       u8 flags;
+       u8 reserved1;
+       u16 node_id;
+       u32 length;
+       u64 range_address;
+       u64 range_length;
+       u8 num_power_states;
+       u8 num_physical_components;
+       u16 reserved2;
+};
+
+/* Values for Flags field above */
+
+#define ACPI_MPST_ENABLED               1
+#define ACPI_MPST_POWER_MANAGED         2
+#define ACPI_MPST_HOT_PLUG_CAPABLE      4
+
+/* Memory Power State Structure (follows POWER_NODE above) */
+
+struct acpi_mpst_power_state {
+       u8 power_state;
+       u8 info_index;
+};
+
+/* Physical Component ID Structure (follows POWER_STATE above) */
+
+struct acpi_mpst_component {
+       u16 component_id;
+};
+
+/* Memory Power State Characteristics Structure (follows all POWER_NODEs) */
+
+struct acpi_mpst_data_hdr {
+       u16 characteristics_count;
+};
+
+struct acpi_mpst_power_data {
+       u8 revision;
+       u8 flags;
+       u16 reserved1;
+       u32 average_power;
+       u32 power_saving;
+       u64 exit_latency;
+       u64 reserved2;
+};
+
+/* Values for Flags field above */
+
+#define ACPI_MPST_PRESERVE              1
+#define ACPI_MPST_AUTOENTRY             2
+#define ACPI_MPST_AUTOEXIT              4
+
+/* Shared Memory Region (not part of an ACPI table) */
+
+struct acpi_mpst_shared {
+       u32 signature;
+       u16 pcc_command;
+       u16 pcc_status;
+       u16 command_register;
+       u16 status_register;
+       u16 power_state_id;
+       u16 power_node_id;
+       u64 energy_consumed;
+       u64 average_power;
+};
+
+/*******************************************************************************
+ *
+ * PCCT - Platform Communications Channel Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_pcct {
+       struct acpi_table_header header;        /* Common ACPI table header */
+       u32 flags;
+       u32 latency;
+       u32 reserved;
+};
+
+/* Values for Flags field above */
+
+#define ACPI_PCCT_DOORBELL              1
+
+/*
+ * PCCT subtables
+ */
+
+/* 0: Generic Communications Subspace */
+
+struct acpi_pcct_subspace {
+       struct acpi_subtable_header header;
+       u8 reserved[6];
+       u64 base_address;
+       u64 length;
+       struct acpi_generic_address doorbell_register;
+       u64 preserve_mask;
+       u64 write_mask;
+};
+
+/*
+ * PCC memory structures (not part of the ACPI table)
+ */
+
+/* Shared Memory Region */
+
+struct acpi_pcct_shared_memory {
+       u32 signature;
+       u16 command;
+       u16 status;
+};
+
+/*******************************************************************************
+ *
+ * PMTT - Platform Memory Topology Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_pmtt {
+       struct acpi_table_header header;        /* Common ACPI table header */
+       u32 reserved;
+};
+
+/* Common header for PMTT subtables that follow main table */
+
+struct acpi_pmtt_header {
+       u8 type;
+       u8 reserved1;
+       u16 length;
+       u16 flags;
+       u16 reserved2;
+};
+
+/* Values for Type field above */
+
+#define ACPI_PMTT_TYPE_SOCKET           0
+#define ACPI_PMTT_TYPE_CONTROLLER       1
+#define ACPI_PMTT_TYPE_DIMM             2
+#define ACPI_PMTT_TYPE_RESERVED         3      /* 0x03-0xFF are reserved */
+
+/* Values for Flags field above */
+
+#define ACPI_PMTT_TOP_LEVEL             0x0001
+#define ACPI_PMTT_PHYSICAL              0x0002
+#define ACPI_PMTT_MEMORY_TYPE           0x000C
+
+/*
+ * PMTT subtables, correspond to Type in struct acpi_pmtt_header
+ */
+
+/* 0: Socket Structure */
+
+struct acpi_pmtt_socket {
+       struct acpi_pmtt_header header;
+       u16 socket_id;
+       u16 reserved;
+};
+
+/* 1: Memory Controller subtable */
+
+struct acpi_pmtt_controller {
+       struct acpi_pmtt_header header;
+       u32 read_latency;
+       u32 write_latency;
+       u32 read_bandwidth;
+       u32 write_bandwidth;
+       u16 access_width;
+       u16 alignment;
+       u16 reserved;
+       u16 domain_count;
+};
+
+/* 1a: Proximity Domain substructure */
+
+struct acpi_pmtt_domain {
+       u32 proximity_domain;
+};
+
+/* 2: Physical Component Identifier (DIMM) */
+
+struct acpi_pmtt_physical_component {
+       struct acpi_pmtt_header header;
+       u16 component_id;
+       u16 reserved;
+       u32 memory_size;
+       u32 bios_handle;
+};
+
+/*******************************************************************************
+ *
+ * RASF - RAS Feature Table (ACPI 5.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_rasf {
+       struct acpi_table_header header;        /* Common ACPI table header */
+       u8 channel_id[12];
+};
+
+/* RASF Platform Communication Channel Shared Memory Region */
+
+struct acpi_rasf_shared_memory {
+       u32 signature;
+       u16 command;
+       u16 status;
+       u64 requested_address;
+       u64 requested_length;
+       u64 actual_address;
+       u64 actual_length;
+       u16 flags;
+       u8 speed;
+};
+
+/* Masks for Flags and Speed fields above */
+
+#define ACPI_RASF_SCRUBBER_RUNNING      1
+#define ACPI_RASF_SPEED                 (7<<1)
+
+/* Channel Commands */
+
+enum acpi_rasf_commands {
+       ACPI_RASF_GET_RAS_CAPABILITIES = 1,
+       ACPI_RASF_GET_PATROL_PARAMETERS = 2,
+       ACPI_RASF_START_PATROL_SCRUBBER = 3,
+       ACPI_RASF_STOP_PATROL_SCRUBBER = 4
+};
+
+/* Channel Command flags */
+
+#define ACPI_RASF_GENERATE_SCI          (1<<15)
+
+/* Status values */
+
+enum acpi_rasf_status {
+       ACPI_RASF_SUCCESS = 0,
+       ACPI_RASF_NOT_VALID = 1,
+       ACPI_RASF_NOT_SUPPORTED = 2,
+       ACPI_RASF_BUSY = 3,
+       ACPI_RASF_FAILED = 4,
+       ACPI_RASF_ABORTED = 5,
+       ACPI_RASF_INVALID_DATA = 6
+};
+
+/* Status flags */
+
+#define ACPI_RASF_COMMAND_COMPLETE      (1)
+#define ACPI_RASF_SCI_DOORBELL          (1<<1)
+#define ACPI_RASF_ERROR                 (1<<2)
+#define ACPI_RASF_STATUS                (0x1F<<3)
+
+/* Reset to default packing */
+
+#pragma pack()
+
+#endif                         /* __ACTBL3_H__ */
index ed73f6705c860d2bc8c28db91b7191c13c144b31..d5dee7ce9474ee88c4bf3cda01339e74067311ad 100644 (file)
@@ -712,8 +712,10 @@ typedef u8 acpi_adr_space_type;
 #define ACPI_ADR_SPACE_CMOS             (acpi_adr_space_type) 5
 #define ACPI_ADR_SPACE_PCI_BAR_TARGET   (acpi_adr_space_type) 6
 #define ACPI_ADR_SPACE_IPMI             (acpi_adr_space_type) 7
+#define ACPI_ADR_SPACE_GPIO             (acpi_adr_space_type) 8
+#define ACPI_ADR_SPACE_GSBUS            (acpi_adr_space_type) 9
 
-#define ACPI_NUM_PREDEFINED_REGIONS     8
+#define ACPI_NUM_PREDEFINED_REGIONS     10
 
 /*
  * Special Address Spaces
@@ -957,6 +959,14 @@ acpi_status(*acpi_adr_space_handler) (u32 function,
 
 #define ACPI_DEFAULT_HANDLER            NULL
 
+/* Special Context data for generic_serial_bus/general_purpose_io (ACPI 5.0) */
+
+struct acpi_connection_info {
+       u8 *connection;
+       u16 length;
+       u8 access_length;
+};
+
 typedef
 acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle,
                                    u32 function,
diff --git a/include/acpi/atomicio.h b/include/acpi/atomicio.h
deleted file mode 100644 (file)
index 8b9fb4b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef ACPI_ATOMIC_IO_H
-#define ACPI_ATOMIC_IO_H
-
-int acpi_pre_map_gar(struct acpi_generic_address *reg);
-int acpi_post_unmap_gar(struct acpi_generic_address *reg);
-
-int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg);
-int acpi_atomic_write(u64 val, struct acpi_generic_address *reg);
-
-#endif
index 610f6fb1bbc2ed71109c3ad4e290d51febbb4376..8cf7e98a2c7bc21dc050b85dc778fa6329c4d076 100644 (file)
@@ -195,6 +195,7 @@ struct acpi_processor_flags {
        u8 has_cst:1;
        u8 power_setup_done:1;
        u8 bm_rld_set:1;
+       u8 need_hotplug_init:1;
 };
 
 struct acpi_processor {
diff --git a/include/asm-generic/io-64-nonatomic-hi-lo.h b/include/asm-generic/io-64-nonatomic-hi-lo.h
new file mode 100644 (file)
index 0000000..a6806a9
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _ASM_IO_64_NONATOMIC_HI_LO_H_
+#define _ASM_IO_64_NONATOMIC_HI_LO_H_
+
+#include <linux/io.h>
+#include <asm-generic/int-ll64.h>
+
+#ifndef readq
+static inline __u64 readq(const volatile void __iomem *addr)
+{
+       const volatile u32 __iomem *p = addr;
+       u32 low, high;
+
+       high = readl(p + 1);
+       low = readl(p);
+
+       return low + ((u64)high << 32);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(__u64 val, volatile void __iomem *addr)
+{
+       writel(val >> 32, addr + 4);
+       writel(val, addr);
+}
+#endif
+
+#endif /* _ASM_IO_64_NONATOMIC_HI_LO_H_ */
diff --git a/include/asm-generic/io-64-nonatomic-lo-hi.h b/include/asm-generic/io-64-nonatomic-lo-hi.h
new file mode 100644 (file)
index 0000000..ca546b1
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _ASM_IO_64_NONATOMIC_LO_HI_H_
+#define _ASM_IO_64_NONATOMIC_LO_HI_H_
+
+#include <linux/io.h>
+#include <asm-generic/int-ll64.h>
+
+#ifndef readq
+static inline __u64 readq(const volatile void __iomem *addr)
+{
+       const volatile u32 __iomem *p = addr;
+       u32 low, high;
+
+       low = readl(p);
+       high = readl(p + 1);
+
+       return low + ((u64)high << 32);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(__u64 val, volatile void __iomem *addr)
+{
+       writel(val, addr);
+       writel(val >> 32, addr + 4);
+}
+#endif
+
+#endif /* _ASM_IO_64_NONATOMIC_LO_HI_H_ */
index 8de4b73e19e25b8c72099bfdd90f55e5821a2e61..e58fcf891370e73996a7fe09b510a7b61d7a9fb8 100644 (file)
@@ -15,6 +15,16 @@ struct pci_dev;
 #ifdef CONFIG_PCI
 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+/* Create a virtual mapping cookie for a port on a given PCI device.
+ * Do not call this directly, it exists to make it easier for architectures
+ * to override */
+#ifdef CONFIG_NO_GENERIC_PCI_IOPORT_MAP
+extern void __iomem *__pci_ioport_map(struct pci_dev *dev, unsigned long port,
+                                     unsigned int nr);
+#else
+#define __pci_ioport_map(dev, port, nr) ioport_map((port), (nr))
+#endif
+
 #else
 static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
 {
index 76caa67c22e2629391a4124396723a94a5736e56..92f0981b5fb862e214ecf8b5c906ad98ef065a92 100644 (file)
@@ -1328,6 +1328,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 extern int drm_authmagic(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
 
 /* Cache management (drm_cache.c) */
 void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
index c37c34275a449626b31bd02731fa3fa649bfef70..bc9ec1d7698cd730df2ef58c4a3ee58f1c067568 100644 (file)
@@ -17,7 +17,7 @@
 
 /*****************************************************************************/
 /*
- * the payload for a key of type "user"
+ * the payload for a key of type "user" or "logon"
  * - once filled in and attached to a key:
  *   - the payload struct is invariant may not be changed, only replaced
  *   - the payload must be read with RCU procedures or with the key semaphore
@@ -33,6 +33,7 @@ struct user_key_payload {
 };
 
 extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
 
 extern int user_instantiate(struct key *key, const void *data, size_t datalen);
 extern int user_update(struct key *key, const void *data, size_t datalen);
index 627a3a42e4d8e3ba015ad32a6bf01f779c356943..3f968665899b9cadeef825dab03666d04eac3c64 100644 (file)
@@ -310,6 +310,11 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
                                             u32 *mask, u32 req);
 extern void acpi_early_init(void);
 
+extern int acpi_nvs_register(__u64 start, __u64 size);
+
+extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
+                                   void *data);
+
 #else  /* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -352,15 +357,18 @@ static inline int acpi_table_parse(char *id,
 {
        return -1;
 }
-#endif /* !CONFIG_ACPI */
 
-#ifdef CONFIG_ACPI_SLEEP
-int suspend_nvs_register(unsigned long start, unsigned long size);
-#else
-static inline int suspend_nvs_register(unsigned long a, unsigned long b)
+static inline int acpi_nvs_register(__u64 start, __u64 size)
 {
        return 0;
 }
-#endif
+
+static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
+                                          void *data)
+{
+       return 0;
+}
+
+#endif /* !CONFIG_ACPI */
 
 #endif /*_LINUX_ACPI_H*/
index 4afd7102459d7fbdef49be451141e16b0591f5e7..b0ffa219993ec2be82a01854718d5e1269ef05bb 100644 (file)
@@ -12,4 +12,7 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
 
 void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size);
 
+int acpi_os_map_generic_address(struct acpi_generic_address *addr);
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
+
 #endif
index 9eabffbc4e50c4b2ae7a1049970d7f7bc39f12ed..033f6aa670de5086ba64dcde7ee6ab7c80e269a7 100644 (file)
@@ -134,7 +134,7 @@ struct pl08x_txd {
        struct dma_async_tx_descriptor tx;
        struct list_head node;
        struct list_head dsg_list;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        dma_addr_t llis_bus;
        struct pl08x_lli *llis_va;
        /* Default cctl value for LLIs */
@@ -197,7 +197,7 @@ struct pl08x_dma_chan {
        dma_addr_t dst_addr;
        u32 src_cctl;
        u32 dst_cctl;
-       enum dma_data_direction runtime_direction;
+       enum dma_transfer_direction runtime_direction;
        dma_cookie_t lc;
        struct list_head pend_list;
        struct pl08x_txd *at;
index 426ab9f4dd853b18d3e8df1b6a3fd2831fec0a57..9ff7a2c48b508103576d175d88fed1c5b3593592 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/types.h>
 #include <linux/elf-em.h>
+#include <linux/ptrace.h>
 
 /* The netlink messages for the audit system is divided into blocks:
  * 1000 - 1099 are for commanding the audit system
  * AUDIT_UNUSED_BITS is updated if need be. */
 #define AUDIT_UNUSED_BITS      0x07FFFC00
 
+/* AUDIT_FIELD_COMPARE rule list */
+#define AUDIT_COMPARE_UID_TO_OBJ_UID   1
+#define AUDIT_COMPARE_GID_TO_OBJ_GID   2
+#define AUDIT_COMPARE_EUID_TO_OBJ_UID  3
+#define AUDIT_COMPARE_EGID_TO_OBJ_GID  4
+#define AUDIT_COMPARE_AUID_TO_OBJ_UID  5
+#define AUDIT_COMPARE_SUID_TO_OBJ_UID  6
+#define AUDIT_COMPARE_SGID_TO_OBJ_GID  7
+#define AUDIT_COMPARE_FSUID_TO_OBJ_UID 8
+#define AUDIT_COMPARE_FSGID_TO_OBJ_GID 9
+
+#define AUDIT_COMPARE_UID_TO_AUID      10
+#define AUDIT_COMPARE_UID_TO_EUID      11
+#define AUDIT_COMPARE_UID_TO_FSUID     12
+#define AUDIT_COMPARE_UID_TO_SUID      13
+
+#define AUDIT_COMPARE_AUID_TO_FSUID    14
+#define AUDIT_COMPARE_AUID_TO_SUID     15
+#define AUDIT_COMPARE_AUID_TO_EUID     16
+
+#define AUDIT_COMPARE_EUID_TO_SUID     17
+#define AUDIT_COMPARE_EUID_TO_FSUID    18
+
+#define AUDIT_COMPARE_SUID_TO_FSUID    19
+
+#define AUDIT_COMPARE_GID_TO_EGID      20
+#define AUDIT_COMPARE_GID_TO_FSGID     21
+#define AUDIT_COMPARE_GID_TO_SGID      22
+
+#define AUDIT_COMPARE_EGID_TO_FSGID    23
+#define AUDIT_COMPARE_EGID_TO_SGID     24
+#define AUDIT_COMPARE_SGID_TO_FSGID    25
+
+#define AUDIT_MAX_FIELD_COMPARE                AUDIT_COMPARE_SGID_TO_FSGID
 
 /* Rule fields */
                                /* These are useful when checking the
 #define AUDIT_PERM     106
 #define AUDIT_DIR      107
 #define AUDIT_FILETYPE 108
+#define AUDIT_OBJ_UID  109
+#define AUDIT_OBJ_GID  110
+#define AUDIT_FIELD_COMPARE    111
 
 #define AUDIT_ARG0      200
 #define AUDIT_ARG1      (AUDIT_ARG0+1)
@@ -408,28 +446,24 @@ struct audit_field {
        void                            *lsm_rule;
 };
 
-#define AUDITSC_INVALID 0
-#define AUDITSC_SUCCESS 1
-#define AUDITSC_FAILURE 2
-#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
 extern int __init audit_register_class(int class, unsigned *list);
 extern int audit_classify_syscall(int abi, unsigned syscall);
 extern int audit_classify_arch(int arch);
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
                                /* Public API */
-extern void audit_finish_fork(struct task_struct *child);
 extern int  audit_alloc(struct task_struct *task);
-extern void audit_free(struct task_struct *task);
-extern void audit_syscall_entry(int arch,
-                               int major, unsigned long a0, unsigned long a1,
-                               unsigned long a2, unsigned long a3);
-extern void audit_syscall_exit(int failed, long return_code);
+extern void __audit_free(struct task_struct *task);
+extern void __audit_syscall_entry(int arch,
+                                 int major, unsigned long a0, unsigned long a1,
+                                 unsigned long a2, unsigned long a3);
+extern void __audit_syscall_exit(int ret_success, long ret_value);
 extern void __audit_getname(const char *name);
 extern void audit_putname(const char *name);
 extern void __audit_inode(const char *name, const struct dentry *dentry);
 extern void __audit_inode_child(const struct dentry *dentry,
                                const struct inode *parent);
+extern void __audit_seccomp(unsigned long syscall);
 extern void __audit_ptrace(struct task_struct *t);
 
 static inline int audit_dummy_context(void)
@@ -437,6 +471,27 @@ static inline int audit_dummy_context(void)
        void *p = current->audit_context;
        return !p || *(int *)p;
 }
+static inline void audit_free(struct task_struct *task)
+{
+       if (unlikely(task->audit_context))
+               __audit_free(task);
+}
+static inline void audit_syscall_entry(int arch, int major, unsigned long a0,
+                                      unsigned long a1, unsigned long a2,
+                                      unsigned long a3)
+{
+       if (unlikely(!audit_dummy_context()))
+               __audit_syscall_entry(arch, major, a0, a1, a2, a3);
+}
+static inline void audit_syscall_exit(void *pt_regs)
+{
+       if (unlikely(current->audit_context)) {
+               int success = is_syscall_success(pt_regs);
+               int return_code = regs_return_value(pt_regs);
+
+               __audit_syscall_exit(success, return_code);
+       }
+}
 static inline void audit_getname(const char *name)
 {
        if (unlikely(!audit_dummy_context()))
@@ -453,6 +508,12 @@ static inline void audit_inode_child(const struct dentry *dentry,
 }
 void audit_core_dumps(long signr);
 
+static inline void audit_seccomp(unsigned long syscall)
+{
+       if (unlikely(!audit_dummy_context()))
+               __audit_seccomp(syscall);
+}
+
 static inline void audit_ptrace(struct task_struct *t)
 {
        if (unlikely(!audit_dummy_context()))
@@ -463,17 +524,16 @@ static inline void audit_ptrace(struct task_struct *t)
 extern unsigned int audit_serial(void);
 extern int auditsc_get_stamp(struct audit_context *ctx,
                              struct timespec *t, unsigned int *serial);
-extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
+extern int  audit_set_loginuid(uid_t loginuid);
 #define audit_get_loginuid(t) ((t)->loginuid)
 #define audit_get_sessionid(t) ((t)->sessionid)
 extern void audit_log_task_context(struct audit_buffer *ab);
 extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
-extern int audit_bprm(struct linux_binprm *bprm);
-extern void audit_socketcall(int nargs, unsigned long *args);
-extern int audit_sockaddr(int len, void *addr);
+extern int __audit_bprm(struct linux_binprm *bprm);
+extern void __audit_socketcall(int nargs, unsigned long *args);
+extern int __audit_sockaddr(int len, void *addr);
 extern void __audit_fd_pair(int fd1, int fd2);
-extern int audit_set_macxattr(const char *name);
 extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr);
 extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
 extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
@@ -499,6 +559,23 @@ static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid
        if (unlikely(!audit_dummy_context()))
                __audit_ipc_set_perm(qbytes, uid, gid, mode);
 }
+static inline int audit_bprm(struct linux_binprm *bprm)
+{
+       if (unlikely(!audit_dummy_context()))
+               return __audit_bprm(bprm);
+       return 0;
+}
+static inline void audit_socketcall(int nargs, unsigned long *args)
+{
+       if (unlikely(!audit_dummy_context()))
+               __audit_socketcall(nargs, args);
+}
+static inline int audit_sockaddr(int len, void *addr)
+{
+       if (unlikely(!audit_dummy_context()))
+               return __audit_sockaddr(len, addr);
+       return 0;
+}
 static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
 {
        if (unlikely(!audit_dummy_context()))
@@ -544,12 +621,11 @@ static inline void audit_mmap_fd(int fd, int flags)
 
 extern int audit_n_rules;
 extern int audit_signals;
-#else
-#define audit_finish_fork(t)
+#else /* CONFIG_AUDITSYSCALL */
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
 #define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
-#define audit_syscall_exit(f,r) do { ; } while (0)
+#define audit_syscall_exit(r) do { ; } while (0)
 #define audit_dummy_context() 1
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
@@ -558,6 +634,7 @@ extern int audit_signals;
 #define audit_inode(n,d) do { (void)(d); } while (0)
 #define audit_inode_child(i,p) do { ; } while (0)
 #define audit_core_dumps(i) do { ; } while (0)
+#define audit_seccomp(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) (0)
 #define audit_get_loginuid(t) (-1)
 #define audit_get_sessionid(t) (-1)
@@ -568,7 +645,6 @@ extern int audit_signals;
 #define audit_socketcall(n,a) ((void)0)
 #define audit_fd_pair(n,a) ((void)0)
 #define audit_sockaddr(len, addr) ({ 0; })
-#define audit_set_macxattr(n) do { ; } while (0)
 #define audit_mq_open(o,m,a) ((void)0)
 #define audit_mq_sendrecv(d,l,p,t) ((void)0)
 #define audit_mq_notify(d,n) ((void)0)
@@ -579,7 +655,7 @@ extern int audit_signals;
 #define audit_ptrace(t) ((void)0)
 #define audit_n_rules 0
 #define audit_signals 0
-#endif
+#endif /* CONFIG_AUDITSYSCALL */
 
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
index f4b8346b1a331f90fc9f29431b84b9176e4e6acb..83c209f39493adf3ef4ae659c2cc46b3770c2948 100644 (file)
@@ -162,7 +162,7 @@ struct bcma_driver {
 
        int (*probe)(struct bcma_device *dev);
        void (*remove)(struct bcma_device *dev);
-       int (*suspend)(struct bcma_device *dev, pm_message_t state);
+       int (*suspend)(struct bcma_device *dev);
        int (*resume)(struct bcma_device *dev);
        void (*shutdown)(struct bcma_device *dev);
 
index fd88a3945aa149af16b2671d656fede2e46fafe2..0092102db2de7be71f648d0e1c761530cb8f2b14 100644 (file)
@@ -18,7 +18,7 @@ struct pt_regs;
 #define BINPRM_BUF_SIZE 128
 
 #ifdef __KERNEL__
-#include <linux/list.h>
+#include <linux/sched.h>
 
 #define CORENAME_MAX_SIZE 128
 
@@ -58,6 +58,7 @@ struct linux_binprm {
        unsigned interp_flags;
        unsigned interp_data;
        unsigned long loader, exec;
+       char tcomm[TASK_COMM_LEN];
 };
 
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
index 3c1063acb2abd6e7db59b0f7de4a756630f7e375..94300fe46ccedd4ca5333fad2b0bac4a74b704b0 100644 (file)
@@ -55,6 +55,26 @@ static inline unsigned long hweight_long(unsigned long w)
        return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
 }
 
+/**
+ * rol64 - rotate a 64-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 rol64(__u64 word, unsigned int shift)
+{
+       return (word << shift) | (word >> (64 - shift));
+}
+
+/**
+ * ror64 - rotate a 64-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 ror64(__u64 word, unsigned int shift)
+{
+       return (word >> shift) | (word << (64 - shift));
+}
+
 /**
  * rol32 - rotate a 32-bit value left
  * @word: value to rotate
index 6c6a1f008065984821435a50f12fd4c08d17fe42..606cf339bb561f6b526c2a58ddcf1378c8376bf1 100644 (file)
@@ -399,9 +399,6 @@ struct request_queue {
        /* Throttle data */
        struct throtl_data *td;
 #endif
-#ifdef CONFIG_LOCKDEP
-       int                     ioc_release_depth;
-#endif
 };
 
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
index 35eae4b675038a6f13ae0b0cfe33fc28d656049e..7c48029dffe6fa93b349e8a1aa8c5775694aa6fa 100644 (file)
@@ -952,7 +952,8 @@ struct cdrom_device_info {
        char name[20];                  /* name of the device type */
 /* per-device flags */
         __u8 sanyo_slot                : 2;    /* Sanyo 3 CD changer support */
-        __u8 reserved          : 6;    /* not used yet */
+        __u8 keeplocked                : 1;    /* CDROM_LOCKDOOR status */
+        __u8 reserved          : 5;    /* not used yet */
        int cdda_method;                /* see flags */
        __u8 last_sense;
        __u8 media_written;             /* dirty flag, DVD+RW bookkeeping */
index 23f81de518298dda6349ee3f44d425045cf9f62b..712abcc205ae0f4a68bda6c4da51e22a7b4000d3 100644 (file)
@@ -186,7 +186,14 @@ struct cpuidle_governor {
 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
 extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
 
+#ifdef CONFIG_INTEL_IDLE
+extern int intel_idle_cpu_init(int cpu);
 #else
+static inline int intel_idle_cpu_init(int cpu) { return -1; }
+#endif
+
+#else
+static inline int intel_idle_cpu_init(int cpu) { return -1; }
 
 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
 {return 0;}
index 5b3adb8f9588226657fedf612948e59952e09aea..b63fb393aa58a2c6ab73bab121960be022269d65 100644 (file)
@@ -279,11 +279,11 @@ struct device *driver_find_device(struct device_driver *drv,
 
 /**
  * struct subsys_interface - interfaces to device functions
- * @name        name of the device function
- * @subsystem   subsytem of the devices to attach to
- * @node        the list of functions registered at the subsystem
- * @add         device hookup to device function handler
- * @remove      device hookup to device function handler
+ * @name:       name of the device function
+ * @subsys:     subsytem of the devices to attach to
+ * @node:       the list of functions registered at the subsystem
+ * @add_dev:    device hookup to device function handler
+ * @remove_dev: device hookup to device function handler
  *
  * Simple interfaces attached to a subsystem. Multiple interfaces can
  * attach to a subsystem and its devices. Unlike drivers, they do not
@@ -612,6 +612,7 @@ struct device_dma_parameters {
  * @archdata:  For arch-specific additions.
  * @of_node:   Associated device tree node.
  * @devt:      For creating the sysfs "dev".
+ * @id:                device instance
  * @devres_lock: Spinlock to protect the resource of the device.
  * @devres_head: The resources list of the device.
  * @knode_class: The node used to add the device to the class list.
@@ -1003,6 +1004,10 @@ extern long sysfs_deprecated;
  * Each module may only use this macro once, and calling it replaces
  * module_init() and module_exit().
  *
+ * @__driver: driver name
+ * @__register: register function for this driver type
+ * @__unregister: unregister function for this driver type
+ *
  * Use this macro to construct bus specific macros for registering
  * drivers, and do not use it on its own.
  */
index efae755017d7de93d4bc40b28c29488aa959bf46..6f85a070bb45a052334387b9574264656df108cd 100644 (file)
@@ -30,7 +30,7 @@ enum digest_algo {
 
 struct pubkey_hdr {
        uint8_t         version;        /* key format version */
-       time_t          timestamp;      /* key made, always 0 for now */
+       uint32_t        timestamp;      /* key made, always 0 for now */
        uint8_t         algo;
        uint8_t         nmpi;
        char            mpi[0];
@@ -38,7 +38,7 @@ struct pubkey_hdr {
 
 struct signature_hdr {
        uint8_t         version;        /* signature format version */
-       time_t          timestamp;      /* signature made */
+       uint32_t        timestamp;      /* signature made */
        uint8_t         algo;
        uint8_t         hash;
        uint8_t         keyid[8];
@@ -46,7 +46,7 @@ struct signature_hdr {
        char            mpi[0];
 } __packed;
 
-#if defined(CONFIG_DIGSIG) || defined(CONFIG_DIGSIG_MODULE)
+#if defined(CONFIG_SIGNATURE) || defined(CONFIG_SIGNATURE_MODULE)
 
 int digsig_verify(struct key *keyring, const char *sig, int siglen,
                                        const char *digest, int digestlen);
@@ -59,6 +59,6 @@ static inline int digsig_verify(struct key *keyring, const char *sig,
        return -EOPNOTSUPP;
 }
 
-#endif /* CONFIG_DIGSIG */
+#endif /* CONFIG_SIGNATURE */
 
 #endif /* _DIGSIG_H */
index 75f53f874b24a0c0abb790f501f2f60ace48e17e..679b349d9b66695f65bb3597b2a530e3e9709600 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/device.h>
 #include <linux/uio.h>
-#include <linux/dma-direction.h>
 #include <linux/scatterlist.h>
 #include <linux/bitmap.h>
 #include <asm/page.h>
@@ -72,11 +71,93 @@ enum dma_transaction_type {
        DMA_ASYNC_TX,
        DMA_SLAVE,
        DMA_CYCLIC,
+       DMA_INTERLEAVE,
+/* last transaction type for creation of the capabilities mask */
+       DMA_TX_TYPE_END,
 };
 
-/* last transaction type for creation of the capabilities mask */
-#define DMA_TX_TYPE_END (DMA_CYCLIC + 1)
+/**
+ * enum dma_transfer_direction - dma transfer mode and direction indicator
+ * @DMA_MEM_TO_MEM: Async/Memcpy mode
+ * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device
+ * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory
+ * @DMA_DEV_TO_DEV: Slave mode & From Device to Device
+ */
+enum dma_transfer_direction {
+       DMA_MEM_TO_MEM,
+       DMA_MEM_TO_DEV,
+       DMA_DEV_TO_MEM,
+       DMA_DEV_TO_DEV,
+       DMA_TRANS_NONE,
+};
+
+/**
+ * Interleaved Transfer Request
+ * ----------------------------
+ * A chunk is collection of contiguous bytes to be transfered.
+ * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG).
+ * ICGs may or maynot change between chunks.
+ * A FRAME is the smallest series of contiguous {chunk,icg} pairs,
+ *  that when repeated an integral number of times, specifies the transfer.
+ * A transfer template is specification of a Frame, the number of times
+ *  it is to be repeated and other per-transfer attributes.
+ *
+ * Practically, a client driver would have ready a template for each
+ *  type of transfer it is going to need during its lifetime and
+ *  set only 'src_start' and 'dst_start' before submitting the requests.
+ *
+ *
+ *  |      Frame-1        |       Frame-2       | ~ |       Frame-'numf'  |
+ *  |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...|
+ *
+ *    ==  Chunk size
+ *    ... ICG
+ */
+
+/**
+ * struct data_chunk - Element of scatter-gather list that makes a frame.
+ * @size: Number of bytes to read from source.
+ *       size_dst := fn(op, size_src), so doesn't mean much for destination.
+ * @icg: Number of bytes to jump after last src/dst address of this
+ *      chunk and before first src/dst address for next chunk.
+ *      Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false.
+ *      Ignored for src(assumed 0), if src_inc is true and src_sgl is false.
+ */
+struct data_chunk {
+       size_t size;
+       size_t icg;
+};
 
+/**
+ * struct dma_interleaved_template - Template to convey DMAC the transfer pattern
+ *      and attributes.
+ * @src_start: Bus address of source for the first chunk.
+ * @dst_start: Bus address of destination for the first chunk.
+ * @dir: Specifies the type of Source and Destination.
+ * @src_inc: If the source address increments after reading from it.
+ * @dst_inc: If the destination address increments after writing to it.
+ * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read).
+ *             Otherwise, source is read contiguously (icg ignored).
+ *             Ignored if src_inc is false.
+ * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write).
+ *             Otherwise, destination is filled contiguously (icg ignored).
+ *             Ignored if dst_inc is false.
+ * @numf: Number of frames in this template.
+ * @frame_size: Number of chunks in a frame i.e, size of sgl[].
+ * @sgl: Array of {chunk,icg} pairs that make up a frame.
+ */
+struct dma_interleaved_template {
+       dma_addr_t src_start;
+       dma_addr_t dst_start;
+       enum dma_transfer_direction dir;
+       bool src_inc;
+       bool dst_inc;
+       bool src_sgl;
+       bool dst_sgl;
+       size_t numf;
+       size_t frame_size;
+       struct data_chunk sgl[0];
+};
 
 /**
  * enum dma_ctrl_flags - DMA flags to augment operation preparation,
@@ -269,7 +350,7 @@ enum dma_slave_buswidth {
  * struct, if applicable.
  */
 struct dma_slave_config {
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        dma_addr_t src_addr;
        dma_addr_t dst_addr;
        enum dma_slave_buswidth src_addr_width;
@@ -433,6 +514,7 @@ struct dma_tx_state {
  * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio.
  *     The function takes a buffer of size buf_len. The callback function will
  *     be called after period_len bytes have been transferred.
+ * @device_prep_interleaved_dma: Transfer expression in a generic way.
  * @device_control: manipulate all pending operations on a channel, returns
  *     zero or error code
  * @device_tx_status: poll for transaction completion, the optional
@@ -492,11 +574,14 @@ struct dma_device {
 
        struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
                struct dma_chan *chan, struct scatterlist *sgl,
-               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags);
        struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
                struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-               size_t period_len, enum dma_data_direction direction);
+               size_t period_len, enum dma_transfer_direction direction);
+       struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
+               struct dma_chan *chan, struct dma_interleaved_template *xt,
+               unsigned long flags);
        int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                unsigned long arg);
 
@@ -522,7 +607,7 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
 
 static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
        struct dma_chan *chan, void *buf, size_t len,
-       enum dma_data_direction dir, unsigned long flags)
+       enum dma_transfer_direction dir, unsigned long flags)
 {
        struct scatterlist sg;
        sg_init_one(&sg, buf, len);
index 4bfe0a2f7d50cc218bce24040154286a582aaf94..f2c64f92c4a006394e21e022bcf6b5c03590c930 100644 (file)
@@ -127,7 +127,7 @@ struct dw_cyclic_desc {
 
 struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                dma_addr_t buf_addr, size_t buf_len, size_t period_len,
-               enum dma_data_direction direction);
+               enum dma_transfer_direction direction);
 void dw_dma_cyclic_free(struct dma_chan *chan);
 int dw_dma_cyclic_start(struct dma_chan *chan);
 void dw_dma_cyclic_stop(struct dma_chan *chan);
index c24f3d7fbf1e4543f3159155618cab9186e600d9..7d4e0356f329253f8932e712693544d31e01cacd 100644 (file)
@@ -42,12 +42,6 @@ struct elevator_ops
        elevator_merged_fn *elevator_merged_fn;
        elevator_merge_req_fn *elevator_merge_req_fn;
        elevator_allow_merge_fn *elevator_allow_merge_fn;
-
-       /*
-        * Used for both plugged list and elevator merging and in the
-        * former case called without queue_lock.  Read comment on top of
-        * attempt_plug_merge() for details.
-        */
        elevator_bio_merged_fn *elevator_bio_merged_fn;
 
        elevator_dispatch_fn *elevator_dispatch_fn;
@@ -122,7 +116,6 @@ extern void elv_dispatch_add_tail(struct request_queue *, struct request *);
 extern void elv_add_request(struct request_queue *, struct request *, int);
 extern void __elv_add_request(struct request_queue *, struct request *, int);
 extern int elv_merge(struct request_queue *, struct request **, struct bio *);
-extern int elv_try_merge(struct request *, struct bio *);
 extern void elv_merge_requests(struct request_queue *, struct request *,
                               struct request *);
 extern void elv_merged_request(struct request_queue *, struct request *, int);
@@ -155,7 +148,7 @@ extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);
 extern int elevator_init(struct request_queue *, char *);
 extern void elevator_exit(struct elevator_queue *);
 extern int elevator_change(struct request_queue *, const char *);
-extern int elv_rq_merge_ok(struct request *, struct bio *);
+extern bool elv_rq_merge_ok(struct request *, struct bio *);
 
 /*
  * Helper functions.
index 0ab54e16a91f499b37db61fcd2be564232144a4a..d09af4b67cf121ad91fd4ca02bec01560b6110fd 100644 (file)
@@ -39,6 +39,7 @@ extern bool __refrigerator(bool check_kthr_stop);
 extern int freeze_processes(void);
 extern int freeze_kernel_threads(void);
 extern void thaw_processes(void);
+extern void thaw_kernel_threads(void);
 
 static inline bool try_to_freeze(void)
 {
@@ -174,6 +175,7 @@ static inline bool __refrigerator(bool check_kthr_stop) { return false; }
 static inline int freeze_processes(void) { return -ENOSYS; }
 static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
+static inline void thaw_kernel_threads(void) {}
 
 static inline bool try_to_freeze(void) { return false; }
 
index 0244082d42c5794ba7c2b7b5a3d6a0181f73c6b9..69cd5bb640f5f6f0e4dd13431c34c6f8c760f42b 100644 (file)
@@ -396,6 +396,7 @@ struct inodes_stat_t {
 #include <linux/rculist_bl.h>
 #include <linux/atomic.h>
 #include <linux/shrinker.h>
+#include <linux/migrate_mode.h>
 
 #include <asm/byteorder.h>
 
@@ -526,7 +527,6 @@ enum positive_aop_returns {
 struct page;
 struct address_space;
 struct writeback_control;
-enum migrate_mode;
 
 struct iov_iter {
        const struct iovec *iov;
@@ -2496,6 +2496,7 @@ extern void get_filesystem(struct file_system_type *fs);
 extern void put_filesystem(struct file_system_type *fs);
 extern struct file_system_type *get_fs_type(const char *name);
 extern struct super_block *get_super(struct block_device *);
+extern struct super_block *get_super_thawed(struct block_device *);
 extern struct super_block *get_active_super(struct block_device *bdev);
 extern void drop_super(struct super_block *sb);
 extern void iterate_supers(void (*)(struct super_block *, void *), void *);
index b5ca4b2c08ecad2fad00c33d48b62466737966b0..004ff33ab38e4dc3e2135f01ebe6b0d84fbb1529 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _GPIO_KEYS_H
 #define _GPIO_KEYS_H
 
+struct device;
+
 struct gpio_keys_button {
        /* Configuration parameters */
        unsigned int code;      /* input event code (KEY_*, SW_*) */
index 62b908e0e5910a2863a0f623f3dede3a3b0bebb1..0ae065a5fcb2775540a012e7710e25b84fef81ff 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/mod_devicetable.h>
 
 
-#define MAX_PAGE_BUFFER_COUNT                          18
+#define MAX_PAGE_BUFFER_COUNT                          19
 #define MAX_MULTIPAGE_BUFFER_COUNT                     32 /* 128K */
 
 #pragma pack(push, 1)
index 828181fbad5d709db91797e359b617efdd606a40..58404b0c50101e93b2978d6d0807447f08e4a049 100644 (file)
@@ -46,6 +46,10 @@ struct team_port {
        u32 speed;
        u8 duplex;
 
+       /* Custom gennetlink interface related flags */
+       bool changed;
+       bool removed;
+
        struct rcu_head rcu;
 };
 
@@ -72,6 +76,10 @@ struct team_option {
        enum team_option_type type;
        int (*getter)(struct team *team, void *arg);
        int (*setter)(struct team *team, void *arg);
+
+       /* Custom gennetlink interface related flags */
+       bool changed;
+       bool removed;
 };
 
 struct team_mode {
@@ -207,6 +215,7 @@ enum {
        TEAM_ATTR_OPTION_CHANGED,       /* flag */
        TEAM_ATTR_OPTION_TYPE,          /* u8 */
        TEAM_ATTR_OPTION_DATA,          /* dynamic */
+       TEAM_ATTR_OPTION_REMOVED,       /* flag */
 
        __TEAM_ATTR_OPTION_MAX,
        TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1,
@@ -227,6 +236,7 @@ enum {
        TEAM_ATTR_PORT_LINKUP,          /* flag */
        TEAM_ATTR_PORT_SPEED,           /* u32 */
        TEAM_ATTR_PORT_DUPLEX,          /* u8 */
+       TEAM_ATTR_PORT_REMOVED,         /* flag */
 
        __TEAM_ATTR_PORT_MAX,
        TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1,
index 7e1371c4bccf93143e6234e15b11924b4375274f..119773eebe3144a46925c8f616a70049b745d8f9 100644 (file)
@@ -133,7 +133,7 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc)
 
 struct task_struct;
 #ifdef CONFIG_BLOCK
-void put_io_context(struct io_context *ioc, struct request_queue *locked_q);
+void put_io_context(struct io_context *ioc);
 void exit_io_context(struct task_struct *task);
 struct io_context *get_task_io_context(struct task_struct *task,
                                       gfp_t gfp_flags, int node);
@@ -141,8 +141,7 @@ void ioc_ioprio_changed(struct io_context *ioc, int ioprio);
 void ioc_cgroup_changed(struct io_context *ioc);
 #else
 struct io_context;
-static inline void put_io_context(struct io_context *ioc,
-                                 struct request_queue *locked_q) { }
+static inline void put_io_context(struct io_context *ioc) { }
 static inline void exit_io_context(struct task_struct *task) { }
 #endif
 
index 2fa0901219d4b7fe69158689e08b33db5ac69db1..0d7d6a1b172f29fde03d030168b253197b84f479 100644 (file)
  * note header.  For kdump, the code in vmcore.c runs in the context
  * of the second kernel to combine them into one note.
  */
+#ifndef KEXEC_NOTE_BYTES
 #define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) +               \
                            KEXEC_CORE_NOTE_NAME_BYTES +                \
                            KEXEC_CORE_NOTE_DESC_BYTES )
+#endif
 
 /*
  * This structure is used to hold the arguments that are used when loading
index 183a6af7715d341bb5ffa9c8ebb3428d44f93cc8..5253471cd2ea32ec8459ef5023432b745b395771 100644 (file)
@@ -271,7 +271,7 @@ extern int keyring_add_key(struct key *keyring,
 
 extern struct key *key_lookup(key_serial_t id);
 
-static inline key_serial_t key_serial(struct key *key)
+static inline key_serial_t key_serial(const struct key *key)
 {
        return key ? key->serial : 0;
 }
@@ -293,6 +293,9 @@ static inline bool key_is_instantiated(const struct key *key)
        (rcu_dereference_protected((KEY)->payload.rcudata,              \
                                   rwsem_is_locked(&((struct key *)(KEY))->sem)))
 
+#define rcu_assign_keypointer(KEY, PAYLOAD)                            \
+       (rcu_assign_pointer((KEY)->payload.rcudata, PAYLOAD))
+
 #ifdef CONFIG_SYSCTL
 extern ctl_table key_sysctls[];
 #endif
index abc0120b09b772ff90fe539016295a00dfb08107..9c07dcebded747493041c8e6a5c18d68bc43fabf 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/bug.h>
 #include <linux/atomic.h>
+#include <linux/kernel.h>
 
 struct kref {
        atomic_t refcount;
old mode 100755 (executable)
new mode 100644 (file)
index 1515e64e3663abd1a557e339c0eb57d6f13d8117..f88c1cc0cb0f24bfda24e69f63cb728a923d5d45 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef MCP_H
 #define MCP_H
 
-#include <linux/mod_devicetable.h>
 #include <mach/dma.h>
 
 struct mcp_ops;
@@ -27,7 +26,7 @@ struct mcp {
        dma_device_t    dma_telco_rd;
        dma_device_t    dma_telco_wr;
        struct device   attached_device;
-       const char      *codec;
+       int             gpio_base;
 };
 
 struct mcp_ops {
@@ -45,11 +44,10 @@ void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
 unsigned int mcp_reg_read(struct mcp *, unsigned int);
 void mcp_enable(struct mcp *);
 void mcp_disable(struct mcp *);
-const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp);
 #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
 
 struct mcp *mcp_host_alloc(struct device *, size_t);
-int mcp_host_register(struct mcp *, void *);
+int mcp_host_register(struct mcp *);
 void mcp_host_unregister(struct mcp *);
 
 struct mcp_driver {
@@ -58,7 +56,6 @@ struct mcp_driver {
        void (*remove)(struct mcp *);
        int (*suspend)(struct mcp *, pm_message_t);
        int (*resume)(struct mcp *);
-       const struct mcp_device_id *id_table;
 };
 
 int mcp_driver_register(struct mcp_driver *);
@@ -67,6 +64,9 @@ void mcp_driver_unregister(struct mcp_driver *);
 #define mcp_get_drvdata(mcp)   dev_get_drvdata(&(mcp)->attached_device)
 #define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d)
 
-#define mcp_priv(mcp)          ((void *)((mcp)+1))
+static inline void *mcp_priv(struct mcp *mcp)
+{
+       return mcp + 1;
+}
 
 #endif
index 2463c2619596fab1667b1ca1c5365c5963bf29ea..9bc9ac651dad9bf2be544961c18e06fd1bfbd119 100644 (file)
@@ -187,8 +187,10 @@ struct twl6040 {
        int rev;
        u8 vibra_ctrl_cache[2];
 
+       /* PLL configuration */
        int pll;
        unsigned int sysclk;
+       unsigned int mclk;
 
        unsigned int irq;
        unsigned int irq_base;
index bc19e5fb7ea8f1791960e961e7a9dab803f15a54..4321f044d1e45e1ad5cdaf20eba1440427b1fb5e 100644 (file)
 #define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
 #define UCB_MODE_AUD_OFF_CAN   (1 << 13)
 
-struct ucb1x00_plat_data {
-       int             gpio_base;
-};
 
 struct ucb1x00_irq {
        void *devid;
@@ -119,7 +116,7 @@ struct ucb1x00 {
        unsigned int            irq;
        struct semaphore        adc_sem;
        spinlock_t              io_lock;
-       const struct mcp_device_id *id;
+       u16                     id;
        u16                     io_dir;
        u16                     io_out;
        u16                     adc_cr;
index eaf867412f7adf26e96a3ad4eb3f002a418434e4..05ed2828a5535bfe151c17ab2b5a656a5209ef4c 100644 (file)
@@ -3,22 +3,10 @@
 
 #include <linux/mm.h>
 #include <linux/mempolicy.h>
+#include <linux/migrate_mode.h>
 
 typedef struct page *new_page_t(struct page *, unsigned long private, int **);
 
-/*
- * MIGRATE_ASYNC means never block
- * MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
- *     on most operations but not ->writepage as the potential stall time
- *     is too significant
- * MIGRATE_SYNC will block when migrating pages
- */
-enum migrate_mode {
-       MIGRATE_ASYNC,
-       MIGRATE_SYNC_LIGHT,
-       MIGRATE_SYNC,
-};
-
 #ifdef CONFIG_MIGRATION
 #define PAGE_MIGRATION 1
 
diff --git a/include/linux/migrate_mode.h b/include/linux/migrate_mode.h
new file mode 100644 (file)
index 0000000..ebf3d89
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef MIGRATE_MODE_H_INCLUDED
+#define MIGRATE_MODE_H_INCLUDED
+/*
+ * MIGRATE_ASYNC means never block
+ * MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
+ *     on most operations but not ->writepage as the potential stall time
+ *     is too significant
+ * MIGRATE_SYNC will block when migrating pages
+ */
+enum migrate_mode {
+       MIGRATE_ASYNC,
+       MIGRATE_SYNC_LIGHT,
+       MIGRATE_SYNC,
+};
+
+#endif         /* MIGRATE_MODE_H_INCLUDED */
index 32085249e9cbf54d0d65ebc63e0e08cb8b6a132f..0549d2115507124405b06f5ea96f072880a3e475 100644 (file)
@@ -42,6 +42,7 @@
 #define AUTOFS_MINOR           235
 #define MAPPER_CTRL_MINOR      236
 #define LOOP_CTRL_MINOR                237
+#define VHOST_NET_MINOR                238
 #define MISC_DYNAMIC_MINOR     255
 
 struct device;
index 5c4fe8e5bfe563669d9f2ef3b23eaa9ad14b1b7c..aea61905499b0e20598969cb02e63f32a3010d2d 100644 (file)
@@ -621,6 +621,7 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
 int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
 int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn);
 void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn);
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap);
 
 int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
index 9f22ba572de0a9a332ec4c2156560b0eac8726cc..19a41d1737afd25cb4462870ae75eea0802a4664 100644 (file)
@@ -217,6 +217,7 @@ struct mmc_card {
 #define MMC_CARD_SDXC          (1<<6)          /* card is SDXC */
 #define MMC_CARD_REMOVED       (1<<7)          /* card has been removed */
 #define MMC_STATE_HIGHSPEED_200        (1<<8)          /* card is in HS200 mode */
+#define MMC_STATE_SLEEP                (1<<9)          /* card is in sleep state */
        unsigned int            quirks;         /* card quirks */
 #define MMC_QUIRK_LENIENT_FN0  (1<<0)          /* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)   /* use func->cur_blksize */
@@ -382,6 +383,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_sd_card_uhs(c)     ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)    ((c) && ((c)->state & MMC_CARD_REMOVED))
+#define mmc_card_is_sleep(c)   ((c)->state & MMC_STATE_SLEEP)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -393,7 +395,9 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
+#define mmc_card_set_sleep(c)  ((c)->state |= MMC_STATE_SLEEP)
 
+#define mmc_card_clr_sleep(c)  ((c)->state &= ~MMC_STATE_SLEEP)
 /*
  * Quirk add/remove for MMC products.
  */
index e8779c6d175923172a9f2d00e7213b9305fd1e4b..aae5d1f1bb394af5a3d7bd1156bc11b67e556882 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef LINUX_MMC_DW_MMC_H
 #define LINUX_MMC_DW_MMC_H
 
+#include <linux/scatterlist.h>
+
 #define MAX_MCI_SLOTS  2
 
 enum dw_mci_state {
@@ -40,7 +42,7 @@ struct mmc_data;
  * @lock: Spinlock protecting the queue and associated data.
  * @regs: Pointer to MMIO registers.
  * @sg: Scatterlist entry currently being processed by PIO code, if any.
- * @pio_offset: Offset into the current scatterlist entry.
+ * @sg_miter: PIO mapping scatterlist iterator.
  * @cur_slot: The slot which is currently using the controller.
  * @mrq: The request currently being processed on @cur_slot,
  *     or NULL if the controller is idle.
@@ -115,7 +117,7 @@ struct dw_mci {
        void __iomem            *regs;
 
        struct scatterlist      *sg;
-       unsigned int            pio_offset;
+       struct sg_mapping_iter  sg_miter;
 
        struct dw_mci_slot      *cur_slot;
        struct mmc_request      *mrq;
index 0beba1e5e1ed4675ebbe35b42091394845be459e..ee2b0363c0406565d2d7c5d6996a500e72a921d5 100644 (file)
@@ -257,6 +257,7 @@ struct mmc_host {
 #define MMC_CAP2_HS200_1_2V_SDR        (1 << 6)        /* can support */
 #define MMC_CAP2_HS200         (MMC_CAP2_HS200_1_8V_SDR | \
                                 MMC_CAP2_HS200_1_2V_SDR)
+#define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
        unsigned int        power_notify_type;
@@ -444,4 +445,23 @@ static inline int mmc_boot_partition_access(struct mmc_host *host)
        return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC);
 }
 
+#ifdef CONFIG_MMC_CLKGATE
+void mmc_host_clk_hold(struct mmc_host *host);
+void mmc_host_clk_release(struct mmc_host *host);
+unsigned int mmc_host_clk_rate(struct mmc_host *host);
+
+#else
+static inline void mmc_host_clk_hold(struct mmc_host *host)
+{
+}
+
+static inline void mmc_host_clk_release(struct mmc_host *host)
+{
+}
+
+static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
+{
+       return host->ios.clock;
+}
+#endif
 #endif /* LINUX_MMC_HOST_H */
index b29e7f6f8fa580d9c4c39b4fca596a98e249b2d4..83ac0713ed0aa9a2a0c79b95013c5bfd42137d9c 100644 (file)
@@ -436,17 +436,6 @@ struct spi_device_id {
                        __attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
-/* mcp */
-
-#define MCP_NAME_SIZE  20
-#define MCP_MODULE_PREFIX "mcp:"
-
-struct mcp_device_id {
-       char name[MCP_NAME_SIZE];
-       kernel_ulong_t driver_data      /* Data private to the driver */
-                       __attribute__((aligned(sizeof(kernel_ulong_t))));
-};
-
 /* dmi */
 enum dmi_field {
        DMI_NONE,
index 06f88994ccaafa36f7c679b5364942a0ffba9cf8..d02cca6cc8ce0552bcf652a29b5562979f72f056 100644 (file)
@@ -57,8 +57,6 @@ struct gcry_mpi {
 
 typedef struct gcry_mpi *MPI;
 
-#define MPI_NULL NULL
-
 #define mpi_get_nlimbs(a)     ((a)->nlimbs)
 #define mpi_is_neg(a)        ((a)->sign)
 
diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h
new file mode 100644 (file)
index 0000000..69b6dbf
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 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 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 __MACH_MXS_GPMI_NAND_H__
+#define __MACH_MXS_GPMI_NAND_H__
+
+/* The size of the resources is fixed. */
+#define GPMI_NAND_RES_SIZE     6
+
+/* Resource names for the GPMI NAND driver. */
+#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "GPMI NAND GPMI Registers"
+#define GPMI_NAND_GPMI_INTERRUPT_RES_NAME  "GPMI NAND GPMI Interrupt"
+#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "GPMI NAND BCH Registers"
+#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "GPMI NAND BCH Interrupt"
+#define GPMI_NAND_DMA_CHANNELS_RES_NAME    "GPMI NAND DMA Channels"
+#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "GPMI NAND DMA Interrupt"
+
+/**
+ * struct gpmi_nand_platform_data - GPMI NAND driver platform data.
+ *
+ * This structure communicates platform-specific information to the GPMI NAND
+ * driver that can't be expressed as resources.
+ *
+ * @platform_init:           A pointer to a function the driver will call to
+ *                           initialize the platform (e.g., set up the pin mux).
+ * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
+ *                           from the NAND Flash device, in nanoseconds.
+ * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
+ *                           from the NAND Flash device, in nanoseconds.
+ * @max_chip_count:          The maximum number of chips for which the driver
+ *                           should configure the hardware. This value most
+ *                           likely reflects the number of pins that are
+ *                           connected to a NAND Flash device. If this is
+ *                           greater than the SoC hardware can support, the
+ *                           driver will print a message and fail to initialize.
+ * @partitions:              An optional pointer to an array of partition
+ *                           descriptions.
+ * @partition_count:         The number of elements in the partitions array.
+ */
+struct gpmi_nand_platform_data {
+       /* SoC hardware information. */
+       int             (*platform_init)(void);
+
+       /* NAND Flash information. */
+       unsigned int    min_prop_delay_in_ns;
+       unsigned int    max_prop_delay_in_ns;
+       unsigned int    max_chip_count;
+
+       /* Medium information. */
+       struct          mtd_partition *partitions;
+       unsigned        partition_count;
+};
+#endif
index 1a81fde8f3331d9652054325aa36809cb40b45f1..d43dc25af82e23a8c6b18f5f3785b8ad4383c8c7 100644 (file)
@@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
-       if (!mtd->suspend)
-               return -EOPNOTSUPP;
-       return mtd->suspend(mtd);
+       return mtd->suspend ? mtd->suspend(mtd) : 0;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
@@ -441,7 +439,7 @@ static inline void mtd_resume(struct mtd_info *mtd)
 static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
        if (!mtd->block_isbad)
-               return -EOPNOTSUPP;
+               return 0;
        return mtd->block_isbad(mtd, ofs);
 }
 
index 9e3a2838291bfe6aee8f6b3e0d88b43ace455abf..0d3dd66322ecbb24529303f6634f36e5ce6f390d 100644 (file)
@@ -83,10 +83,6 @@ enum ip_conntrack_status {
        /* Conntrack is a fake untracked entry */
        IPS_UNTRACKED_BIT = 12,
        IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
-
-       /* Conntrack has a userspace helper. */
-       IPS_USERSPACE_HELPER_BIT = 13,
-       IPS_USERSPACE_HELPER = (1 << IPS_USERSPACE_HELPER_BIT),
 };
 
 /* Connection tracking event types */
index 6390f0992f36f0723393d282c6d39d3f68abb12e..b56e76811c04380e9779dbe82c2cfa4a5b0c6abd 100644 (file)
@@ -3,8 +3,7 @@
 
 #include <linux/types.h>
 
-#define XT_CT_NOTRACK          0x1
-#define XT_CT_USERSPACE_HELPER 0x2
+#define XT_CT_NOTRACK  0x1
 
 struct xt_ct_target_info {
        __u16 flags;
index a764cef06b733f34f89ed4a618bfb41e33428258..d6ba9a12591ea464991b1d36157918ee5fc1eebe 100644 (file)
@@ -614,7 +614,6 @@ struct nfs_getaclargs {
        size_t                          acl_len;
        unsigned int                    acl_pgbase;
        struct page **                  acl_pages;
-       struct page *                   acl_scratch;
        struct nfs4_sequence_args       seq_args;
 };
 
@@ -624,6 +623,7 @@ struct nfs_getaclres {
        size_t                          acl_len;
        size_t                          acl_data_offset;
        int                             acl_flags;
+       struct page *                   acl_scratch;
        struct nfs4_sequence_res        seq_res;
 };
 
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
new file mode 100644 (file)
index 0000000..9490a00
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * Definitions for the NVM Express interface
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LINUX_NVME_H
+#define _LINUX_NVME_H
+
+#include <linux/types.h>
+
+struct nvme_bar {
+       __u64                   cap;    /* Controller Capabilities */
+       __u32                   vs;     /* Version */
+       __u32                   intms;  /* Interrupt Mask Set */
+       __u32                   intmc;  /* Interrupt Mask Clear */
+       __u32                   cc;     /* Controller Configuration */
+       __u32                   rsvd1;  /* Reserved */
+       __u32                   csts;   /* Controller Status */
+       __u32                   rsvd2;  /* Reserved */
+       __u32                   aqa;    /* Admin Queue Attributes */
+       __u64                   asq;    /* Admin SQ Base Address */
+       __u64                   acq;    /* Admin CQ Base Address */
+};
+
+#define NVME_CAP_TIMEOUT(cap)  (((cap) >> 24) & 0xff)
+#define NVME_CAP_STRIDE(cap)   (((cap) >> 32) & 0xf)
+
+enum {
+       NVME_CC_ENABLE          = 1 << 0,
+       NVME_CC_CSS_NVM         = 0 << 4,
+       NVME_CC_MPS_SHIFT       = 7,
+       NVME_CC_ARB_RR          = 0 << 11,
+       NVME_CC_ARB_WRRU        = 1 << 11,
+       NVME_CC_ARB_VS          = 7 << 11,
+       NVME_CC_SHN_NONE        = 0 << 14,
+       NVME_CC_SHN_NORMAL      = 1 << 14,
+       NVME_CC_SHN_ABRUPT      = 2 << 14,
+       NVME_CC_IOSQES          = 6 << 16,
+       NVME_CC_IOCQES          = 4 << 20,
+       NVME_CSTS_RDY           = 1 << 0,
+       NVME_CSTS_CFS           = 1 << 1,
+       NVME_CSTS_SHST_NORMAL   = 0 << 2,
+       NVME_CSTS_SHST_OCCUR    = 1 << 2,
+       NVME_CSTS_SHST_CMPLT    = 2 << 2,
+};
+
+struct nvme_id_power_state {
+       __le16                  max_power;      /* centiwatts */
+       __u16                   rsvd2;
+       __le32                  entry_lat;      /* microseconds */
+       __le32                  exit_lat;       /* microseconds */
+       __u8                    read_tput;
+       __u8                    read_lat;
+       __u8                    write_tput;
+       __u8                    write_lat;
+       __u8                    rsvd16[16];
+};
+
+#define NVME_VS(major, minor)  (major << 16 | minor)
+
+struct nvme_id_ctrl {
+       __le16                  vid;
+       __le16                  ssvid;
+       char                    sn[20];
+       char                    mn[40];
+       char                    fr[8];
+       __u8                    rab;
+       __u8                    ieee[3];
+       __u8                    mic;
+       __u8                    mdts;
+       __u8                    rsvd78[178];
+       __le16                  oacs;
+       __u8                    acl;
+       __u8                    aerl;
+       __u8                    frmw;
+       __u8                    lpa;
+       __u8                    elpe;
+       __u8                    npss;
+       __u8                    rsvd264[248];
+       __u8                    sqes;
+       __u8                    cqes;
+       __u8                    rsvd514[2];
+       __le32                  nn;
+       __le16                  oncs;
+       __le16                  fuses;
+       __u8                    fna;
+       __u8                    vwc;
+       __le16                  awun;
+       __le16                  awupf;
+       __u8                    rsvd530[1518];
+       struct nvme_id_power_state      psd[32];
+       __u8                    vs[1024];
+};
+
+struct nvme_lbaf {
+       __le16                  ms;
+       __u8                    ds;
+       __u8                    rp;
+};
+
+struct nvme_id_ns {
+       __le64                  nsze;
+       __le64                  ncap;
+       __le64                  nuse;
+       __u8                    nsfeat;
+       __u8                    nlbaf;
+       __u8                    flbas;
+       __u8                    mc;
+       __u8                    dpc;
+       __u8                    dps;
+       __u8                    rsvd30[98];
+       struct nvme_lbaf        lbaf[16];
+       __u8                    rsvd192[192];
+       __u8                    vs[3712];
+};
+
+enum {
+       NVME_NS_FEAT_THIN       = 1 << 0,
+       NVME_LBAF_RP_BEST       = 0,
+       NVME_LBAF_RP_BETTER     = 1,
+       NVME_LBAF_RP_GOOD       = 2,
+       NVME_LBAF_RP_DEGRADED   = 3,
+};
+
+struct nvme_lba_range_type {
+       __u8                    type;
+       __u8                    attributes;
+       __u8                    rsvd2[14];
+       __u64                   slba;
+       __u64                   nlb;
+       __u8                    guid[16];
+       __u8                    rsvd48[16];
+};
+
+enum {
+       NVME_LBART_TYPE_FS      = 0x01,
+       NVME_LBART_TYPE_RAID    = 0x02,
+       NVME_LBART_TYPE_CACHE   = 0x03,
+       NVME_LBART_TYPE_SWAP    = 0x04,
+
+       NVME_LBART_ATTRIB_TEMP  = 1 << 0,
+       NVME_LBART_ATTRIB_HIDE  = 1 << 1,
+};
+
+/* I/O commands */
+
+enum nvme_opcode {
+       nvme_cmd_flush          = 0x00,
+       nvme_cmd_write          = 0x01,
+       nvme_cmd_read           = 0x02,
+       nvme_cmd_write_uncor    = 0x04,
+       nvme_cmd_compare        = 0x05,
+       nvme_cmd_dsm            = 0x09,
+};
+
+struct nvme_common_command {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u32                   cdw2[2];
+       __le64                  metadata;
+       __le64                  prp1;
+       __le64                  prp2;
+       __u32                   cdw10[6];
+};
+
+struct nvme_rw_command {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2;
+       __le64                  metadata;
+       __le64                  prp1;
+       __le64                  prp2;
+       __le64                  slba;
+       __le16                  length;
+       __le16                  control;
+       __le32                  dsmgmt;
+       __le32                  reftag;
+       __le16                  apptag;
+       __le16                  appmask;
+};
+
+enum {
+       NVME_RW_LR                      = 1 << 15,
+       NVME_RW_FUA                     = 1 << 14,
+       NVME_RW_DSM_FREQ_UNSPEC         = 0,
+       NVME_RW_DSM_FREQ_TYPICAL        = 1,
+       NVME_RW_DSM_FREQ_RARE           = 2,
+       NVME_RW_DSM_FREQ_READS          = 3,
+       NVME_RW_DSM_FREQ_WRITES         = 4,
+       NVME_RW_DSM_FREQ_RW             = 5,
+       NVME_RW_DSM_FREQ_ONCE           = 6,
+       NVME_RW_DSM_FREQ_PREFETCH       = 7,
+       NVME_RW_DSM_FREQ_TEMP           = 8,
+       NVME_RW_DSM_LATENCY_NONE        = 0 << 4,
+       NVME_RW_DSM_LATENCY_IDLE        = 1 << 4,
+       NVME_RW_DSM_LATENCY_NORM        = 2 << 4,
+       NVME_RW_DSM_LATENCY_LOW         = 3 << 4,
+       NVME_RW_DSM_SEQ_REQ             = 1 << 6,
+       NVME_RW_DSM_COMPRESSED          = 1 << 7,
+};
+
+/* Admin commands */
+
+enum nvme_admin_opcode {
+       nvme_admin_delete_sq            = 0x00,
+       nvme_admin_create_sq            = 0x01,
+       nvme_admin_get_log_page         = 0x02,
+       nvme_admin_delete_cq            = 0x04,
+       nvme_admin_create_cq            = 0x05,
+       nvme_admin_identify             = 0x06,
+       nvme_admin_abort_cmd            = 0x08,
+       nvme_admin_set_features         = 0x09,
+       nvme_admin_get_features         = 0x0a,
+       nvme_admin_async_event          = 0x0c,
+       nvme_admin_activate_fw          = 0x10,
+       nvme_admin_download_fw          = 0x11,
+       nvme_admin_format_nvm           = 0x80,
+       nvme_admin_security_send        = 0x81,
+       nvme_admin_security_recv        = 0x82,
+};
+
+enum {
+       NVME_QUEUE_PHYS_CONTIG  = (1 << 0),
+       NVME_CQ_IRQ_ENABLED     = (1 << 1),
+       NVME_SQ_PRIO_URGENT     = (0 << 1),
+       NVME_SQ_PRIO_HIGH       = (1 << 1),
+       NVME_SQ_PRIO_MEDIUM     = (2 << 1),
+       NVME_SQ_PRIO_LOW        = (3 << 1),
+       NVME_FEAT_ARBITRATION   = 0x01,
+       NVME_FEAT_POWER_MGMT    = 0x02,
+       NVME_FEAT_LBA_RANGE     = 0x03,
+       NVME_FEAT_TEMP_THRESH   = 0x04,
+       NVME_FEAT_ERR_RECOVERY  = 0x05,
+       NVME_FEAT_VOLATILE_WC   = 0x06,
+       NVME_FEAT_NUM_QUEUES    = 0x07,
+       NVME_FEAT_IRQ_COALESCE  = 0x08,
+       NVME_FEAT_IRQ_CONFIG    = 0x09,
+       NVME_FEAT_WRITE_ATOMIC  = 0x0a,
+       NVME_FEAT_ASYNC_EVENT   = 0x0b,
+       NVME_FEAT_SW_PROGRESS   = 0x0c,
+};
+
+struct nvme_identify {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2[2];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  cns;
+       __u32                   rsvd11[5];
+};
+
+struct nvme_features {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2[2];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  fid;
+       __le32                  dword11;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_create_cq {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[5];
+       __le64                  prp1;
+       __u64                   rsvd8;
+       __le16                  cqid;
+       __le16                  qsize;
+       __le16                  cq_flags;
+       __le16                  irq_vector;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_create_sq {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[5];
+       __le64                  prp1;
+       __u64                   rsvd8;
+       __le16                  sqid;
+       __le16                  qsize;
+       __le16                  sq_flags;
+       __le16                  cqid;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_delete_queue {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[9];
+       __le16                  qid;
+       __u16                   rsvd10;
+       __u32                   rsvd11[5];
+};
+
+struct nvme_download_firmware {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[5];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  numd;
+       __le32                  offset;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_command {
+       union {
+               struct nvme_common_command common;
+               struct nvme_rw_command rw;
+               struct nvme_identify identify;
+               struct nvme_features features;
+               struct nvme_create_cq create_cq;
+               struct nvme_create_sq create_sq;
+               struct nvme_delete_queue delete_queue;
+               struct nvme_download_firmware dlfw;
+       };
+};
+
+enum {
+       NVME_SC_SUCCESS                 = 0x0,
+       NVME_SC_INVALID_OPCODE          = 0x1,
+       NVME_SC_INVALID_FIELD           = 0x2,
+       NVME_SC_CMDID_CONFLICT          = 0x3,
+       NVME_SC_DATA_XFER_ERROR         = 0x4,
+       NVME_SC_POWER_LOSS              = 0x5,
+       NVME_SC_INTERNAL                = 0x6,
+       NVME_SC_ABORT_REQ               = 0x7,
+       NVME_SC_ABORT_QUEUE             = 0x8,
+       NVME_SC_FUSED_FAIL              = 0x9,
+       NVME_SC_FUSED_MISSING           = 0xa,
+       NVME_SC_INVALID_NS              = 0xb,
+       NVME_SC_LBA_RANGE               = 0x80,
+       NVME_SC_CAP_EXCEEDED            = 0x81,
+       NVME_SC_NS_NOT_READY            = 0x82,
+       NVME_SC_CQ_INVALID              = 0x100,
+       NVME_SC_QID_INVALID             = 0x101,
+       NVME_SC_QUEUE_SIZE              = 0x102,
+       NVME_SC_ABORT_LIMIT             = 0x103,
+       NVME_SC_ABORT_MISSING           = 0x104,
+       NVME_SC_ASYNC_LIMIT             = 0x105,
+       NVME_SC_FIRMWARE_SLOT           = 0x106,
+       NVME_SC_FIRMWARE_IMAGE          = 0x107,
+       NVME_SC_INVALID_VECTOR          = 0x108,
+       NVME_SC_INVALID_LOG_PAGE        = 0x109,
+       NVME_SC_INVALID_FORMAT          = 0x10a,
+       NVME_SC_BAD_ATTRIBUTES          = 0x180,
+       NVME_SC_WRITE_FAULT             = 0x280,
+       NVME_SC_READ_ERROR              = 0x281,
+       NVME_SC_GUARD_CHECK             = 0x282,
+       NVME_SC_APPTAG_CHECK            = 0x283,
+       NVME_SC_REFTAG_CHECK            = 0x284,
+       NVME_SC_COMPARE_FAILED          = 0x285,
+       NVME_SC_ACCESS_DENIED           = 0x286,
+};
+
+struct nvme_completion {
+       __le32  result;         /* Used by admin commands to return data */
+       __u32   rsvd;
+       __le16  sq_head;        /* how much of this queue may be reclaimed */
+       __le16  sq_id;          /* submission queue that generated this entry */
+       __u16   command_id;     /* of the command which completed */
+       __le16  status;         /* did the command fail, and if so, why? */
+};
+
+struct nvme_user_io {
+       __u8    opcode;
+       __u8    flags;
+       __u16   control;
+       __u16   nblocks;
+       __u16   rsvd;
+       __u64   metadata;
+       __u64   addr;
+       __u64   slba;
+       __u32   dsmgmt;
+       __u32   reftag;
+       __u16   apptag;
+       __u16   appmask;
+};
+
+struct nvme_admin_cmd {
+       __u8    opcode;
+       __u8    flags;
+       __u16   rsvd1;
+       __u32   nsid;
+       __u32   cdw2;
+       __u32   cdw3;
+       __u64   metadata;
+       __u64   addr;
+       __u32   metadata_len;
+       __u32   data_len;
+       __u32   cdw10;
+       __u32   cdw11;
+       __u32   cdw12;
+       __u32   cdw13;
+       __u32   cdw14;
+       __u32   cdw15;
+       __u32   timeout_ms;
+       __u32   result;
+};
+
+#define NVME_IOCTL_ID          _IO('N', 0x40)
+#define NVME_IOCTL_ADMIN_CMD   _IOWR('N', 0x41, struct nvme_admin_cmd)
+#define NVME_IOCTL_SUBMIT_IO   _IOW('N', 0x42, struct nvme_user_io)
+
+#endif /* _LINUX_NVME_H */
index 08855613ceb32ed66e425eb41f69206d6feb61da..abb2776be1ba1bdce8f04788f0b66af967d08050 100644 (file)
@@ -587,6 +587,7 @@ struct hw_perf_event {
        u64                             sample_period;
        u64                             last_period;
        local64_t                       period_left;
+       u64                             interrupts_seq;
        u64                             interrupts;
 
        u64                             freq_time_stamp;
index e5bbcbaa6f5700f3bfcb9d14550cce632fcbd53d..4d99e4e6ef83fa4910e22959bc9326117ce1288e 100644 (file)
@@ -110,7 +110,19 @@ static inline void pm_qos_remove_request(struct pm_qos_request *req)
                        { return; }
 
 static inline int pm_qos_request(int pm_qos_class)
-                       { return 0; }
+{
+       switch (pm_qos_class) {
+       case PM_QOS_CPU_DMA_LATENCY:
+               return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+       case PM_QOS_NETWORK_LATENCY:
+               return PM_QOS_NETWORK_LAT_DEFAULT_VALUE;
+       case PM_QOS_NETWORK_THROUGHPUT:
+               return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE;
+       default:
+               return PM_QOS_DEFAULT_VALUE;
+       }
+}
+
 static inline int pm_qos_add_notifier(int pm_qos_class,
                                      struct notifier_block *notifier)
                        { return 0; }
index ef35bb73f69b63716a2c0cc12e65f1a64221c86e..26a8a4ed9b07bbf6c779545d547f3aab3f5103d4 100644 (file)
@@ -81,7 +81,11 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
  * Limit the time part in order to ensure there are some bits left for the
  * cycle counter and fraction multiply.
  */
+#if BITS_PER_LONG == 32
 #define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
+#else
+#define PROP_MAX_SHIFT (BITS_PER_LONG/2)
+#endif
 
 #define PROP_FRAC_SHIFT                (BITS_PER_LONG - PROP_MAX_SHIFT - 1)
 #define PROP_FRAC_BASE         (1UL << PROP_FRAC_SHIFT)
index a27e56ca41a4cf2ae505e08710c88f745f476510..c2f1f6a5fcb8a67f52c90c8397c7384534d3010a 100644 (file)
 
 #include <linux/compiler.h>            /* For unlikely.  */
 #include <linux/sched.h>               /* For struct task_struct.  */
+#include <linux/err.h>                 /* for IS_ERR_VALUE */
 
 
 extern long arch_ptrace(struct task_struct *child, long request,
@@ -266,6 +267,15 @@ static inline void ptrace_release_task(struct task_struct *task)
 #define force_successful_syscall_return() do { } while (0)
 #endif
 
+#ifndef is_syscall_success
+/*
+ * On most systems we can tell if a syscall is a success based on if the retval
+ * is an error value.  On some systems like ia64 and powerpc they have different
+ * indicators of success/failure and must define their own.
+ */
+#define is_syscall_success(regs) (!IS_ERR_VALUE((unsigned long)(regs_return_value(regs))))
+#endif
+
 /*
  * <asm/ptrace.h> should define the following things inside #ifdef __KERNEL__.
  *
index cb785569903759e054141b09e62e4a2c0442425f..c09fa042b5ea077bb748507fd41e464891bbb7b3 100644 (file)
@@ -230,7 +230,11 @@ struct mem_dqinfo {
 struct super_block;
 
 #define DQF_MASK 0xffff                /* Mask for format specific flags */
-#define DQF_INFO_DIRTY_B 16
+#define DQF_GETINFO_MASK 0x1ffff       /* Mask for flags passed to userspace */
+#define DQF_SETINFO_MASK 0xffff                /* Mask for flags modifiable from userspace */
+#define DQF_SYS_FILE_B         16
+#define DQF_SYS_FILE (1 << DQF_SYS_FILE_B)     /* Quota file stored as system file */
+#define DQF_INFO_DIRTY_B       31
 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
 
 extern void mark_info_dirty(struct super_block *sb, int type);
index c9d625ca659ec387c6b9456c4d03d0bb4af80fb9..da81af086eaf765ea701247cd332944ba7b3c570 100644 (file)
@@ -109,12 +109,18 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent);
  *
  * returns 0 on success and <0 if the counter->usage will exceed the
  * counter->limit _locked call expects the counter->lock to be taken
+ *
+ * charge_nofail works the same, except that it charges the resource
+ * counter unconditionally, and returns < 0 if the after the current
+ * charge we are over limit.
  */
 
 int __must_check res_counter_charge_locked(struct res_counter *counter,
                unsigned long val);
 int __must_check res_counter_charge(struct res_counter *counter,
                unsigned long val, struct res_counter **limit_fail_at);
+int __must_check res_counter_charge_nofail(struct res_counter *counter,
+               unsigned long val, struct res_counter **limit_fail_at);
 
 /*
  * uncharge - tell that some portion of the resource is released
@@ -142,7 +148,10 @@ static inline unsigned long long res_counter_margin(struct res_counter *cnt)
        unsigned long flags;
 
        spin_lock_irqsave(&cnt->lock, flags);
-       margin = cnt->limit - cnt->usage;
+       if (cnt->limit > cnt->usage)
+               margin = cnt->limit - cnt->usage;
+       else
+               margin = 0;
        spin_unlock_irqrestore(&cnt->lock, flags);
        return margin;
 }
index 4032ec1cf836fe2055a422c8d2356a4ea620117a..7d379a6bfd886679fcfefee2ed90fb636d6cd028 100644 (file)
@@ -2088,9 +2088,9 @@ extern int sched_setscheduler_nocheck(struct task_struct *, int,
 extern struct task_struct *idle_task(int cpu);
 /**
  * is_idle_task - is the specified task an idle task?
- * @tsk: the task in question.
+ * @p: the task in question.
  */
-static inline bool is_idle_task(struct task_struct *p)
+static inline bool is_idle_task(const struct task_struct *p)
 {
        return p->pid == 0;
 }
@@ -2259,6 +2259,12 @@ static inline void mmdrop(struct mm_struct * mm)
 extern void mmput(struct mm_struct *);
 /* Grab a reference to a task's mm, if it is not already going away */
 extern struct mm_struct *get_task_mm(struct task_struct *task);
+/*
+ * Grab a reference to a task's mm, if it is not already going away
+ * and ptrace_may_access with the mode parameter passed to it
+ * succeeds.
+ */
+extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode);
 /* Remove the current tasks stale references to the old mm_struct */
 extern void mm_release(struct task_struct *, struct mm_struct *);
 /* Allocate a new mm structure and copy contents from tsk->mm */
index cb2dd118cc0ffb91e62ad7746d230b0376f442dd..425450b980b8a8e60ea532b76702d552c3da6857 100644 (file)
@@ -30,7 +30,7 @@ struct sh_desc {
        struct sh_dmae_regs hw;
        struct list_head node;
        struct dma_async_tx_descriptor async_tx;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        dma_cookie_t cookie;
        size_t partial;
        int chunks;
@@ -48,6 +48,7 @@ struct sh_dmae_channel {
        unsigned int    offset;
        unsigned int    dmars;
        unsigned int    dmars_bit;
+       unsigned int    chclr_offset;
 };
 
 struct sh_dmae_pdata {
@@ -68,6 +69,8 @@ struct sh_dmae_pdata {
        unsigned int dmaor_is_32bit:1;
        unsigned int needs_tend_set:1;
        unsigned int no_dmars:1;
+       unsigned int chclr_present:1;
+       unsigned int slave_only:1;
 };
 
 /* DMA register */
index e4c711c6f3213c962e90cb25d528cd40861dbf4e..79ab2555b3b014ce75c780c7f149af2c5ead53fa 100644 (file)
@@ -48,6 +48,7 @@ extern struct file *shmem_file_setup(const char *name,
                                        loff_t size, unsigned long flags);
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
+extern void shmem_unlock_mapping(struct address_space *mapping);
 extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
                                        pgoff_t index, gfp_t gfp_mask);
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
diff --git a/include/linux/sirfsoc_dma.h b/include/linux/sirfsoc_dma.h
new file mode 100644 (file)
index 0000000..29d9593
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _SIRFSOC_DMA_H_
+#define _SIRFSOC_DMA_H_
+
+bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id);
+
+#endif
index e16557a357e5dc919036dbb0a4ac1473c153e9b4..c1241c428179c78bce7c8a774cbaeea9b38da35a 100644 (file)
@@ -192,7 +192,6 @@ enum
        LINUX_MIB_TCPPARTIALUNDO,               /* TCPPartialUndo */
        LINUX_MIB_TCPDSACKUNDO,                 /* TCPDSACKUndo */
        LINUX_MIB_TCPLOSSUNDO,                  /* TCPLossUndo */
-       LINUX_MIB_TCPLOSS,                      /* TCPLoss */
        LINUX_MIB_TCPLOSTRETRANSMIT,            /* TCPLostRetransmit */
        LINUX_MIB_TCPRENOFAILURES,              /* TCPRenoFailures */
        LINUX_MIB_TCPSACKFAILURES,              /* TCPSackFailures */
index 95040cc33107e1b59e8b1d7966d349aaaa845c68..91784a4f860852d01f958ecce70439e381dcaabf 100644 (file)
@@ -357,14 +357,29 @@ extern bool pm_save_wakeup_count(unsigned int count);
 
 static inline void lock_system_sleep(void)
 {
-       freezer_do_not_count();
+       current->flags |= PF_FREEZER_SKIP;
        mutex_lock(&pm_mutex);
 }
 
 static inline void unlock_system_sleep(void)
 {
+       /*
+        * Don't use freezer_count() because we don't want the call to
+        * try_to_freeze() here.
+        *
+        * Reason:
+        * Fundamentally, we just don't need it, because freezing condition
+        * doesn't come into effect until we release the pm_mutex lock,
+        * since the freezer always works with pm_mutex held.
+        *
+        * More importantly, in the case of hibernation,
+        * unlock_system_sleep() gets called in snapshot_read() and
+        * snapshot_write() when the freezing condition is still in effect.
+        * Which means, if we use try_to_freeze() here, it would make them
+        * enter the refrigerator, thus causing hibernation to lockup.
+        */
+       current->flags &= ~PF_FREEZER_SKIP;
        mutex_unlock(&pm_mutex);
-       freezer_count();
 }
 
 #else /* !CONFIG_PM_SLEEP */
index 06061a7f8e69131e2401985e243298cbf9795a50..3e60228e7299bade2a864f21c9d4addc6c304cf7 100644 (file)
@@ -273,7 +273,7 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)
 #endif
 
 extern int page_evictable(struct page *page, struct vm_area_struct *vma);
-extern void scan_mapping_unevictable_pages(struct address_space *);
+extern void check_move_unevictable_pages(struct page **, int nr_pages);
 
 extern unsigned long scan_unevictable_pages;
 extern int scan_unevictable_handler(struct ctl_table *, int,
index 515669fa3c1d97e0067c6ef404c5263458251810..8ec1153ff57b9c3c4d4b6c7360fd01bbdaebbc2c 100644 (file)
@@ -624,7 +624,7 @@ asmlinkage long sys_socketpair(int, int, int, int __user *);
 asmlinkage long sys_socketcall(int call, unsigned long __user *args);
 asmlinkage long sys_listen(int, int);
 asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
-                               long timeout);
+                               int timeout);
 asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                        fd_set __user *exp, struct timeval __user *tvp);
 asmlinkage long sys_old_select(struct sel_arg_struct __user *arg);
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
deleted file mode 100644 (file)
index 20f63d3..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * System devices follow a slightly different driver model. 
- * They don't need to do dynammic driver binding, can't be probed, 
- * and don't reside on any type of peripheral bus. 
- * So, we represent and treat them a little differently.
- * 
- * We still have a notion of a driver for a system device, because we still
- * want to perform basic operations on these devices. 
- *
- * We also support auxiliary drivers binding to devices of a certain class.
- * 
- * This allows configurable drivers to register themselves for devices of
- * a certain type. And, it allows class definitions to reside in generic
- * code while arch-specific code can register specific drivers.
- *
- * Auxiliary drivers registered with a NULL cls are registered as drivers
- * for all system devices, and get notification calls for each device. 
- */
-
-
-#ifndef _SYSDEV_H_
-#define _SYSDEV_H_
-
-#include <linux/kobject.h>
-#include <linux/pm.h>
-
-
-struct sys_device;
-struct sysdev_class_attribute;
-
-struct sysdev_class {
-       const char *name;
-       struct list_head        drivers;
-       struct sysdev_class_attribute **attrs;
-       struct kset             kset;
-};
-
-struct sysdev_class_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *,
-                       char *);
-       ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *,
-                        const char *, size_t);
-};
-
-#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)           \
-{                                                              \
-       .attr = {.name = __stringify(_name), .mode = _mode },   \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
-}
-
-#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)            \
-       struct sysdev_class_attribute attr_##_name =            \
-               _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
-
-
-extern int sysdev_class_register(struct sysdev_class *);
-extern void sysdev_class_unregister(struct sysdev_class *);
-
-extern int sysdev_class_create_file(struct sysdev_class *,
-       struct sysdev_class_attribute *);
-extern void sysdev_class_remove_file(struct sysdev_class *,
-       struct sysdev_class_attribute *);
-/**
- * Auxiliary system device drivers.
- */
-
-struct sysdev_driver {
-       struct list_head        entry;
-       int     (*add)(struct sys_device *);
-       int     (*remove)(struct sys_device *);
-};
-
-
-extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *);
-extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *);
-
-
-/**
- * sys_devices can be simplified a lot from regular devices, because they're
- * simply not as versatile. 
- */
-
-struct sys_device {
-       u32             id;
-       struct sysdev_class     * cls;
-       struct kobject          kobj;
-};
-
-extern int sysdev_register(struct sys_device *);
-extern void sysdev_unregister(struct sys_device *);
-
-
-struct sysdev_attribute { 
-       struct attribute        attr;
-       ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
-       ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
-                        const char *, size_t);
-};
-
-
-#define _SYSDEV_ATTR(_name, _mode, _show, _store)              \
-{                                                              \
-       .attr = { .name = __stringify(_name), .mode = _mode },  \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
-}
-
-#define SYSDEV_ATTR(_name, _mode, _show, _store)               \
-       struct sysdev_attribute attr_##_name =                  \
-               _SYSDEV_ATTR(_name, _mode, _show, _store);
-
-extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
-extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
-
-/* Create/remove NULL terminated attribute list */
-static inline int
-sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a)
-{
-       return sysfs_create_files(&d->kobj, (const struct attribute **)a);
-}
-
-static inline void
-sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a)
-{
-       return sysfs_remove_files(&d->kobj, (const struct attribute **)a);
-}
-
-struct sysdev_ext_attribute {
-       struct sysdev_attribute attr;
-       void *var;
-};
-
-/*
- * Support for simple variable sysdev attributes.
- * The pointer to the variable is stored in a sysdev_ext_attribute
- */
-
-/* Add more types as needed */
-
-extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
-                               char *);
-extern ssize_t sysdev_store_ulong(struct sys_device *,
-                       struct sysdev_attribute *, const char *, size_t);
-extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
-                               char *);
-extern ssize_t sysdev_store_int(struct sys_device *,
-                       struct sysdev_attribute *, const char *, size_t);
-
-#define _SYSDEV_ULONG_ATTR(_name, _mode, _var)                         \
-       { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
-         &(_var) }
-#define SYSDEV_ULONG_ATTR(_name, _mode, _var)                  \
-       struct sysdev_ext_attribute attr_##_name =              \
-               _SYSDEV_ULONG_ATTR(_name, _mode, _var);
-#define _SYSDEV_INT_ATTR(_name, _mode, _var)                           \
-       { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
-         &(_var) }
-#define SYSDEV_INT_ATTR(_name, _mode, _var)                    \
-       struct sysdev_ext_attribute attr_##_name =              \
-               _SYSDEV_INT_ATTR(_name, _mode, _var);
-
-#endif /* _SYSDEV_H_ */
index 47b4a27e6e97c27f1d2bd6cfab895f4e36adb37c..796f1ff0388c979138b81b7094bb6feda5bfd212 100644 (file)
@@ -152,9 +152,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 
 #ifdef CONFIG_NET
-extern int generate_netlink_event(u32 orig, enum events event);
+extern int thermal_generate_netlink_event(u32 orig, enum events event);
 #else
-static inline int generate_netlink_event(u32 orig, enum events event)
+static inline int thermal_generate_netlink_event(u32 orig, enum events event)
 {
        return 0;
 }
index ecdaeb98b293727274b6511ee7ef523c00324564..5cf685086dd3f6d728b6a0374f096a080b1bfc1d 100644 (file)
@@ -312,7 +312,6 @@ struct tty_driver {
         */
        struct tty_struct **ttys;
        struct ktermios **termios;
-       struct ktermios **termios_locked;
        void *driver_state;
 
        /*
index 27a4e16d2bf1c668ab08d721fa93981bd3ab7f9c..69d845739bc2304ff52bfac2f9e18f87b1002d8e 100644 (file)
@@ -1073,6 +1073,7 @@ typedef void (*usb_complete_t)(struct urb *);
  *     which the host controller driver should use in preference to the
  *     transfer_buffer.
  * @sg: scatter gather buffer list
+ * @num_mapped_sgs: (internal) number of mapped sg entries
  * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
  *     be broken up into chunks according to the current maximum packet
index 31fdb4c6ee3dd3d8200596017da81652f3385e41..0b83acd3360a1e52042850fff29ca0b4d1827c5f 100644 (file)
 #define USB_PORT_FEAT_TEST              21
 #define USB_PORT_FEAT_INDICATOR         22
 #define USB_PORT_FEAT_C_PORT_L1         23
-#define USB_PORT_FEAT_C_PORT_LINK_STATE        25
-#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26
-#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27
-#define USB_PORT_FEAT_BH_PORT_RESET     28
-#define USB_PORT_FEAT_C_BH_PORT_RESET   29
-#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30
 
 /*
  * Port feature selectors added by USB 3.0 spec.
@@ -75,8 +69,8 @@
 #define USB_PORT_FEAT_LINK_STATE               5
 #define USB_PORT_FEAT_U1_TIMEOUT               23
 #define USB_PORT_FEAT_U2_TIMEOUT               24
-#define USB_PORT_FEAT_C_LINK_STATE             25
-#define USB_PORT_FEAT_C_CONFIG_ERR             26
+#define USB_PORT_FEAT_C_PORT_LINK_STATE                25
+#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR      26
 #define USB_PORT_FEAT_REMOTE_WAKE_MASK         27
 #define USB_PORT_FEAT_BH_PORT_RESET            28
 #define USB_PORT_FEAT_C_BH_PORT_RESET          29
index 61b29057b0547cbe42e050d1debab583d8fd38e1..3b6f628880f83b0f05b3c3363a7202665a5ce9ca 100644 (file)
@@ -589,7 +589,7 @@ static inline int usb_endpoint_is_isoc_out(
  */
 static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
 {
-       return le16_to_cpu(epd->wMaxPacketSize);
+       return __le16_to_cpu(epd->wMaxPacketSize);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h
deleted file mode 100644 (file)
index 51f17b1..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __LANGWELL_OTG_H
-#define __LANGWELL_OTG_H
-
-#include <linux/usb/intel_mid_otg.h>
-
-#define CI_USBCMD              0x30
-#      define USBCMD_RST               BIT(1)
-#      define USBCMD_RS                BIT(0)
-#define CI_USBSTS              0x34
-#      define USBSTS_SLI               BIT(8)
-#      define USBSTS_URI               BIT(6)
-#      define USBSTS_PCI               BIT(2)
-#define CI_PORTSC1             0x74
-#      define PORTSC_PP                BIT(12)
-#      define PORTSC_LS                (BIT(11) | BIT(10))
-#      define PORTSC_SUSP              BIT(7)
-#      define PORTSC_CCS               BIT(0)
-#define CI_HOSTPC1             0xb4
-#      define HOSTPC1_PHCD             BIT(22)
-#define CI_OTGSC               0xf4
-#      define OTGSC_DPIE               BIT(30)
-#      define OTGSC_1MSE               BIT(29)
-#      define OTGSC_BSEIE              BIT(28)
-#      define OTGSC_BSVIE              BIT(27)
-#      define OTGSC_ASVIE              BIT(26)
-#      define OTGSC_AVVIE              BIT(25)
-#      define OTGSC_IDIE               BIT(24)
-#      define OTGSC_DPIS               BIT(22)
-#      define OTGSC_1MSS               BIT(21)
-#      define OTGSC_BSEIS              BIT(20)
-#      define OTGSC_BSVIS              BIT(19)
-#      define OTGSC_ASVIS              BIT(18)
-#      define OTGSC_AVVIS              BIT(17)
-#      define OTGSC_IDIS               BIT(16)
-#      define OTGSC_DPS                BIT(14)
-#      define OTGSC_1MST               BIT(13)
-#      define OTGSC_BSE                BIT(12)
-#      define OTGSC_BSV                BIT(11)
-#      define OTGSC_ASV                BIT(10)
-#      define OTGSC_AVV                BIT(9)
-#      define OTGSC_ID                 BIT(8)
-#      define OTGSC_HABA               BIT(7)
-#      define OTGSC_HADP               BIT(6)
-#      define OTGSC_IDPU               BIT(5)
-#      define OTGSC_DP                 BIT(4)
-#      define OTGSC_OT                 BIT(3)
-#      define OTGSC_HAAR               BIT(2)
-#      define OTGSC_VC                 BIT(1)
-#      define OTGSC_VD                 BIT(0)
-#      define OTGSC_INTEN_MASK         (0x7f << 24)
-#      define OTGSC_INT_MASK           (0x5f << 24)
-#      define OTGSC_INTSTS_MASK        (0x7f << 16)
-#define CI_USBMODE             0xf8
-#      define USBMODE_CM               (BIT(1) | BIT(0))
-#      define USBMODE_IDLE             0
-#      define USBMODE_DEVICE           0x2
-#      define USBMODE_HOST             0x3
-#define USBCFG_ADDR                    0xff10801c
-#define USBCFG_LEN                     4
-#      define USBCFG_VBUSVAL           BIT(14)
-#      define USBCFG_AVALID            BIT(13)
-#      define USBCFG_BVALID            BIT(12)
-#      define USBCFG_SESEND            BIT(11)
-
-#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
-
-enum langwell_otg_timer_type {
-       TA_WAIT_VRISE_TMR,
-       TA_WAIT_BCON_TMR,
-       TA_AIDL_BDIS_TMR,
-       TB_ASE0_BRST_TMR,
-       TB_SE0_SRP_TMR,
-       TB_SRP_INIT_TMR,
-       TB_SRP_FAIL_TMR,
-       TB_BUS_SUSPEND_TMR
-};
-
-#define TA_WAIT_VRISE  100
-#define TA_WAIT_BCON   30000
-#define TA_AIDL_BDIS   15000
-#define TB_ASE0_BRST   5000
-#define TB_SE0_SRP     2
-#define TB_SRP_INIT    100
-#define TB_SRP_FAIL    5500
-#define TB_BUS_SUSPEND 500
-
-struct langwell_otg_timer {
-       unsigned long expires;  /* Number of count increase to timeout */
-       unsigned long count;    /* Tick counter */
-       void (*function)(unsigned long);        /* Timeout function */
-       unsigned long data;     /* Data passed to function */
-       struct list_head list;
-};
-
-struct langwell_otg {
-       struct intel_mid_otg_xceiv      iotg;
-       struct device                   *dev;
-
-       void __iomem                    *usbcfg;        /* SCCBUSB config Reg */
-
-       unsigned                        region;
-       unsigned                        cfg_region;
-
-       struct work_struct              work;
-       struct workqueue_struct         *qwork;
-       struct timer_list               hsm_timer;
-
-       spinlock_t                      lock;
-       spinlock_t                      wq_lock;
-
-       struct notifier_block           iotg_notifier;
-};
-
-static inline
-struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg)
-{
-       return container_of(iotg, struct langwell_otg, iotg);
-}
-
-#endif /* __LANGWELL_OTG_H__ */
index 89c290b69a5c6bf345f7d6e27d3b1921301b87fc..29e1920e7339867124e3605e1afd1a2777d66e8a 100644 (file)
 #define TUNER_PHILIPS_FMD1216MEX_MK3   78
 #define TUNER_PHILIPS_FM1216MK5                79
 #define TUNER_PHILIPS_FQ1216LME_MK3    80      /* Active loopthrough, no FM */
-#define TUNER_XC4000                   81      /* Xceive Silicon Tuner */
 
 #define TUNER_PARTSNIC_PTI_5NF05       81
 #define TUNER_PHILIPS_CU1216L           82
 #define TUNER_PHILIPS_FQ1236_MK5       85      /* NTSC, TDA9885, no FM radio */
 #define TUNER_TENA_TNF_5337            86
 
+#define TUNER_XC4000                   87      /* Xceive Silicon Tuner */
+
 /* tv card specific */
 #define TDA9887_PRESENT                (1<<0)
 #define TDA9887_PORT1_INACTIVE                 (1<<1)
index 5b2fed5eebf2e32063d59be921b2a830b9eaa8ea..00596e816b4d6d8dd79f6272d0e293f163d277d0 100644 (file)
@@ -1388,6 +1388,6 @@ struct hci_inquiry_req {
 };
 #define IREQ_CACHE_FLUSH 0x0001
 
-extern int enable_hs;
+extern bool enable_hs;
 
 #endif /* __HCI_H */
index 15f4be7d768e48e740b5b58f39ba76813e79e2f6..a067d30ce73e88fa86dce220e3f2002cac5be878 100644 (file)
@@ -1140,6 +1140,7 @@ struct cfg80211_disassoc_request {
  * @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
  *     search for IBSSs with a different BSSID.
  * @channel: The channel to use if no IBSS can be found to join.
+ * @channel_type: channel type (HT mode)
  * @channel_fixed: The channel should be fixed -- do not search for
  *     IBSSs to join on other channels.
  * @ie: information element(s) to include in the beacon
@@ -1978,6 +1979,11 @@ struct wiphy_wowlan_support {
  *     configured as RX antennas. Antenna configuration commands will be
  *     rejected unless this or @available_antennas_tx is set.
  *
+ * @probe_resp_offload:
+ *      Bitmap of supported protocols for probe response offloading.
+ *      See &enum nl80211_probe_resp_offload_support_attr. Only valid
+ *      when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+ *
  * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation
  *     may request, if implemented.
  *
index da1f064a81b3744688545acef85fcaf507fe6c82..6c469dbdb9176d278a7815ad0aaf82acdfbc78e5 100644 (file)
@@ -78,7 +78,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
                                      __u32 mark, __u8 tos, __u8 scope,
                                      __u8 proto, __u8 flags,
                                      __be32 daddr, __be32 saddr,
-                                     __be16 dport, __be32 sport)
+                                     __be16 dport, __be16 sport)
 {
        fl4->flowi4_oif = oif;
        fl4->flowi4_iif = 0;
@@ -93,6 +93,16 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
        fl4->fl4_dport = dport;
        fl4->fl4_sport = sport;
 }
+
+/* Reset some input parameters after previous lookup */
+static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos,
+                                       __be32 daddr, __be32 saddr)
+{
+       fl4->flowi4_oif = oif;
+       fl4->flowi4_tos = tos;
+       fl4->daddr = daddr;
+       fl4->saddr = saddr;
+}
                                      
 
 struct flowi6 {
index 3419bf5cd15401d611373f961edb7dcb344315d1..d55f4344333514f43f26d4da76d53574b6a9bd48 100644 (file)
@@ -41,6 +41,7 @@ static inline void *net_generic(const struct net *net, int id)
        ptr = ng->ptr[id - 1];
        rcu_read_unlock();
 
+       BUG_ON(!ptr);
        return ptr;
 }
 #endif
index e503b87c4c1b4d3310be150b07e4a94a36508133..d58fdec47597bccc095a9da28066bd6b67acfc2f 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifndef _NETPRIO_CGROUP_H
 #define _NETPRIO_CGROUP_H
-#include <linux/module.h>
 #include <linux/cgroup.h>
 #include <linux/hardirq.h>
 #include <linux/rcupdate.h>
@@ -38,19 +37,51 @@ extern int net_prio_subsys_id;
 
 extern void sock_update_netprioidx(struct sock *sk);
 
-static inline struct cgroup_netprio_state
-               *task_netprio_state(struct task_struct *p)
+#if IS_BUILTIN(CONFIG_NETPRIO_CGROUP)
+
+static inline u32 task_netprioidx(struct task_struct *p)
 {
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
-       return container_of(task_subsys_state(p, net_prio_subsys_id),
-                           struct cgroup_netprio_state, css);
-#else
-       return NULL;
-#endif
+       struct cgroup_netprio_state *state;
+       u32 idx;
+
+       rcu_read_lock();
+       state = container_of(task_subsys_state(p, net_prio_subsys_id),
+                            struct cgroup_netprio_state, css);
+       idx = state->prioidx;
+       rcu_read_unlock();
+       return idx;
+}
+
+#elif IS_MODULE(CONFIG_NETPRIO_CGROUP)
+
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+       struct cgroup_netprio_state *state;
+       int subsys_id;
+       u32 idx = 0;
+
+       rcu_read_lock();
+       subsys_id = rcu_dereference_index_check(net_prio_subsys_id,
+                                               rcu_read_lock_held());
+       if (subsys_id >= 0) {
+               state = container_of(task_subsys_state(p, subsys_id),
+                                    struct cgroup_netprio_state, css);
+               idx = state->prioidx;
+       }
+       rcu_read_unlock();
+       return idx;
 }
 
 #else
 
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+       return 0;
+}
+
+#endif /* CONFIG_NETPRIO_CGROUP */
+
+#else
 #define sock_update_netprioidx(sk)
 #endif
 
index 91855d185b537f96fc0ea09134c96a93b63aa3d3..b1c0d5b564c2c1936455086cbf37dbbc761de0dd 100644 (file)
@@ -270,6 +270,7 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
                if (IS_ERR(rt))
                        return rt;
                ip_rt_put(rt);
+               flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
        }
        security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
        return ip_route_output_flow(net, fl4, sk);
@@ -284,6 +285,9 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable
                fl4->fl4_dport = dport;
                fl4->fl4_sport = sport;
                ip_rt_put(rt);
+               flowi4_update_output(fl4, sk->sk_bound_dev_if,
+                                    RT_CONN_FLAGS(sk), fl4->daddr,
+                                    fl4->saddr);
                security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
                return ip_route_output_flow(sock_net(sk), fl4, sk);
        }
index f6bb08b73ca4c81a923a2d575801c5a38940efa4..55ce96b53b092e3ca04db6eaa7d6888fb9f478bc 100644 (file)
@@ -220,9 +220,16 @@ struct tcf_proto {
 
 struct qdisc_skb_cb {
        unsigned int            pkt_len;
-       long                    data[];
+       unsigned char           data[24];
 };
 
+static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
+{
+       struct qdisc_skb_cb *qcb;
+       BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz);
+       BUILD_BUG_ON(sizeof(qcb->data) < sz);
+}
+
 static inline int qdisc_qlen(const struct Qdisc *q)
 {
        return q->q.qlen;
index bb972d254dff4550301b189bb487e554da02ae58..91c1c8baf020d3c5e80df8c3f7eb88323003408f 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/uaccess.h>
 #include <linux/memcontrol.h>
 #include <linux/res_counter.h>
+#include <linux/jump_label.h>
 
 #include <linux/filter.h>
 #include <linux/rculist_nulls.h>
@@ -226,6 +227,7 @@ struct cg_proto;
   *    @sk_ack_backlog: current listen backlog
   *    @sk_max_ack_backlog: listen backlog set in listen()
   *    @sk_priority: %SO_PRIORITY setting
+  *    @sk_cgrp_prioidx: socket group's priority map index
   *    @sk_type: socket type (%SOCK_STREAM, etc)
   *    @sk_protocol: which protocol this socket belongs in this network family
   *    @sk_peer_pid: &struct pid for this socket's peer
@@ -921,7 +923,7 @@ inline void sk_refcnt_debug_release(const struct sock *sk)
 #define sk_refcnt_debug_release(sk) do { } while (0)
 #endif /* SOCK_REFCNT_DEBUG */
 
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_NET)
 extern struct jump_label_key memcg_socket_limit_enabled;
 static inline struct cg_proto *parent_cg_proto(struct proto *proto,
                                               struct cg_proto *cg_proto)
@@ -1007,9 +1009,8 @@ static inline void memcg_memory_allocated_add(struct cg_proto *prot,
        struct res_counter *fail;
        int ret;
 
-       ret = res_counter_charge(prot->memory_allocated,
-                                amt << PAGE_SHIFT, &fail);
-
+       ret = res_counter_charge_nofail(prot->memory_allocated,
+                                       amt << PAGE_SHIFT, &fail);
        if (ret < 0)
                *parent_status = OVER_LIMIT;
 }
@@ -1053,12 +1054,11 @@ sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status)
 }
 
 static inline void
-sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status)
+sk_memory_allocated_sub(struct sock *sk, int amt)
 {
        struct proto *prot = sk->sk_prot;
 
-       if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
-           parent_status != OVER_LIMIT) /* Otherwise was uncharged already */
+       if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
                memcg_memory_allocated_sub(sk->sk_cgrp, amt);
 
        atomic_long_sub(amt, prot->memory_allocated);
index 0118ea999f67a882f6e4e389aa9f2b685e571955..42c29bfbcee34d8d6ada5d18533850d82973f352 100644 (file)
@@ -273,6 +273,14 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
        return seq3 - seq2 >= seq1 - seq2;
 }
 
+static inline bool tcp_out_of_memory(struct sock *sk)
+{
+       if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+           sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2))
+               return true;
+       return false;
+}
+
 static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
 {
        struct percpu_counter *ocp = sk->sk_prot->orphan_count;
@@ -283,13 +291,11 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
                if (orphans << shift > sysctl_tcp_max_orphans)
                        return true;
        }
-
-       if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-           sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2))
-               return true;
        return false;
 }
 
+extern bool tcp_check_oom(struct sock *sk, int shift);
+
 /* syncookies: remember time of last synqueue overflow */
 static inline void tcp_synq_overflow(struct sock *sk)
 {
@@ -311,6 +317,8 @@ extern struct proto tcp_prot;
 #define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
 #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
 
+extern void tcp_init_mem(struct net *net);
+
 extern void tcp_v4_err(struct sk_buff *skb, u32);
 
 extern void tcp_shutdown (struct sock *sk, int how);
index 5d1a758e05950a7669157914a15b6025da11a7cc..6a3922fe0be0b840c3d8a416cb6919aa28f78b7a 100644 (file)
@@ -857,7 +857,7 @@ struct fc_lport {
        enum fc_lport_state            state;
        unsigned long                  boot_time;
        struct fc_host_statistics      host_stats;
-       struct fcoe_dev_stats          *dev_stats;
+       struct fcoe_dev_stats __percpu *dev_stats;
        u8                             retry_count;
 
        /* Fabric information */
index 5ab255f196cc85c6b894adc2182f1271562a301e..cea1b5426dfa2f1c42c71f4450224722d1c2daf2 100644 (file)
@@ -417,6 +417,7 @@ static inline int __snd_bug_on(int cond)
 #define gameport_get_port_data(gp) (gp)->port_data
 #endif
 
+#ifdef CONFIG_PCI
 /* PCI quirk list helper */
 struct snd_pci_quirk {
        unsigned short subvendor;       /* PCI subvendor ID */
@@ -456,5 +457,6 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
 const struct snd_pci_quirk *
 snd_pci_quirk_lookup_id(u16 vendor, u16 device,
                        const struct snd_pci_quirk *list);
+#endif
 
 #endif /* __SOUND_CORE_H */
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
new file mode 100644 (file)
index 0000000..e5e6ff9
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef TARGET_CORE_BACKEND_H
+#define TARGET_CORE_BACKEND_H
+
+#define TRANSPORT_PLUGIN_PHBA_PDEV             1
+#define TRANSPORT_PLUGIN_VHBA_PDEV             2
+#define TRANSPORT_PLUGIN_VHBA_VDEV             3
+
+struct se_subsystem_api {
+       struct list_head sub_api_list;
+
+       char name[16];
+       struct module *owner;
+
+       u8 transport_type;
+
+       unsigned int fua_write_emulated : 1;
+       unsigned int write_cache_emulated : 1;
+
+       int (*attach_hba)(struct se_hba *, u32);
+       void (*detach_hba)(struct se_hba *);
+       int (*pmode_enable_hba)(struct se_hba *, unsigned long);
+       void *(*allocate_virtdevice)(struct se_hba *, const char *);
+       struct se_device *(*create_virtdevice)(struct se_hba *,
+                               struct se_subsystem_dev *, void *);
+       void (*free_device)(void *);
+       int (*transport_complete)(struct se_task *task);
+       struct se_task *(*alloc_task)(unsigned char *cdb);
+       int (*do_task)(struct se_task *);
+       int (*do_discard)(struct se_device *, sector_t, u32);
+       void (*do_sync_cache)(struct se_task *);
+       void (*free_task)(struct se_task *);
+       ssize_t (*check_configfs_dev_params)(struct se_hba *,
+                       struct se_subsystem_dev *);
+       ssize_t (*set_configfs_dev_params)(struct se_hba *,
+                       struct se_subsystem_dev *, const char *, ssize_t);
+       ssize_t (*show_configfs_dev_params)(struct se_hba *,
+                       struct se_subsystem_dev *, char *);
+       u32 (*get_device_rev)(struct se_device *);
+       u32 (*get_device_type)(struct se_device *);
+       sector_t (*get_blocks)(struct se_device *);
+       unsigned char *(*get_sense_buffer)(struct se_task *);
+};
+
+int    transport_subsystem_register(struct se_subsystem_api *);
+void   transport_subsystem_release(struct se_subsystem_api *);
+
+struct se_device *transport_add_device_to_core_hba(struct se_hba *,
+               struct se_subsystem_api *, struct se_subsystem_dev *, u32,
+               void *, struct se_dev_limits *, const char *, const char *);
+
+void   transport_complete_sync_cache(struct se_cmd *, int);
+void   transport_complete_task(struct se_task *, int);
+
+void   target_get_task_cdb(struct se_task *, unsigned char *);
+
+void   transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
+int    transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
+int    transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
+int    transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
+
+/* core helpers also used by command snooping in pscsi */
+void   *transport_kmap_data_sg(struct se_cmd *);
+void   transport_kunmap_data_sg(struct se_cmd *);
+
+#endif /* TARGET_CORE_BACKEND_H */
index 6873c7dd9145d2a23f682d9e8d2c695a7571d656..dc4e345a01637078d62b8a0075323b9b24ef6887 100644 (file)
@@ -10,6 +10,7 @@
 #include <net/tcp.h>
 
 #define TARGET_CORE_MOD_VERSION                "v4.1.0-rc1-ml"
+#define TARGET_CORE_VERSION            TARGET_CORE_MOD_VERSION
 
 /* Maximum Number of LUNs per Target Portal Group */
 /* Don't raise above 511 or REPORT_LUNS needs to handle >1 page */
@@ -34,6 +35,7 @@
 #define TRANSPORT_SENSE_BUFFER                 SCSI_SENSE_BUFFERSIZE
 /* Used by transport_send_check_condition_and_sense() */
 #define SPC_SENSE_KEY_OFFSET                   2
+#define SPC_ADD_SENSE_LEN_OFFSET               7
 #define SPC_ASC_KEY_OFFSET                     12
 #define SPC_ASCQ_KEY_OFFSET                    13
 #define TRANSPORT_IQN_LEN                      224
 /* Used by transport_get_inquiry_vpd_device_ident() */
 #define INQUIRY_VPD_DEVICE_IDENTIFIER_LEN      254
 
+/* Attempts before moving from SHORT to LONG */
+#define PYX_TRANSPORT_WINDOW_CLOSED_THRESHOLD  3
+#define PYX_TRANSPORT_WINDOW_CLOSED_WAIT_SHORT 3  /* In milliseconds */
+#define PYX_TRANSPORT_WINDOW_CLOSED_WAIT_LONG  10 /* In milliseconds */
+
+#define PYX_TRANSPORT_STATUS_INTERVAL          5 /* In seconds */
+
+/*
+ * struct se_subsystem_dev->su_dev_flags
+*/
+#define SDF_FIRMWARE_VPD_UNIT_SERIAL           0x00000001
+#define SDF_EMULATED_VPD_UNIT_SERIAL           0x00000002
+#define SDF_USING_UDEV_PATH                    0x00000004
+#define SDF_USING_ALIAS                                0x00000008
+
+/*
+ * struct se_device->dev_flags
+ */
+#define DF_READ_ONLY                           0x00000001
+#define DF_SPC2_RESERVATIONS                   0x00000002
+#define DF_SPC2_RESERVATIONS_WITH_ISID         0x00000004
+
+/* struct se_dev_attrib sanity values */
+/* Default max_unmap_lba_count */
+#define DA_MAX_UNMAP_LBA_COUNT                 0
+/* Default max_unmap_block_desc_count */
+#define DA_MAX_UNMAP_BLOCK_DESC_COUNT          0
+/* Default unmap_granularity */
+#define DA_UNMAP_GRANULARITY_DEFAULT           0
+/* Default unmap_granularity_alignment */
+#define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0
+/* Emulation for Direct Page Out */
+#define DA_EMULATE_DPO                         0
+/* Emulation for Forced Unit Access WRITEs */
+#define DA_EMULATE_FUA_WRITE                   1
+/* Emulation for Forced Unit Access READs */
+#define DA_EMULATE_FUA_READ                    0
+/* Emulation for WriteCache and SYNCHRONIZE_CACHE */
+#define DA_EMULATE_WRITE_CACHE                 0
+/* Emulation for UNIT ATTENTION Interlock Control */
+#define DA_EMULATE_UA_INTLLCK_CTRL             0
+/* Emulation for TASK_ABORTED status (TAS) by default */
+#define DA_EMULATE_TAS                         1
+/* Emulation for Thin Provisioning UNMAP using block/blk-lib.c:blkdev_issue_discard() */
+#define DA_EMULATE_TPU                         0
+/*
+ * Emulation for Thin Provisioning WRITE_SAME w/ UNMAP=1 bit using
+ * block/blk-lib.c:blkdev_issue_discard()
+ */
+#define DA_EMULATE_TPWS                                0
+/* No Emulation for PSCSI by default */
+#define DA_EMULATE_RESERVATIONS                        0
+/* No Emulation for PSCSI by default */
+#define DA_EMULATE_ALUA                                0
+/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
+#define DA_ENFORCE_PR_ISIDS                    1
+#define DA_STATUS_MAX_SECTORS_MIN              16
+#define DA_STATUS_MAX_SECTORS_MAX              8192
+/* By default don't report non-rotating (solid state) medium */
+#define DA_IS_NONROT                           0
+/* Queue Algorithm Modifier default for restricted reordering in control mode page */
+#define DA_EMULATE_REST_REORD                  0
+
+#define SE_MODE_PAGE_BUF                       512
+
+
 /* struct se_hba->hba_flags */
 enum hba_flags_table {
        HBA_FLAGS_INTERNAL_USE  = 0x01,
@@ -71,11 +139,12 @@ enum transport_tpg_type_table {
        TRANSPORT_TPG_TYPE_DISCOVERY = 1,
 };
 
-/* Used for generate timer flags */
+/* struct se_task->task_flags */
 enum se_task_flags {
        TF_ACTIVE               = (1 << 0),
        TF_SENT                 = (1 << 1),
        TF_REQUEST_STOP         = (1 << 2),
+       TF_HAS_SENSE            = (1 << 3),
 };
 
 /* Special transport agnostic struct se_cmd->t_states */
@@ -158,9 +227,38 @@ enum tcm_sense_reason_table {
        TCM_RESERVATION_CONFLICT                = 0x10,
 };
 
+enum target_sc_flags_table {
+       TARGET_SCF_BIDI_OP              = 0x01,
+       TARGET_SCF_ACK_KREF             = 0x02,
+};
+
+/* fabric independent task management function values */
+enum tcm_tmreq_table {
+       TMR_ABORT_TASK          = 1,
+       TMR_ABORT_TASK_SET      = 2,
+       TMR_CLEAR_ACA           = 3,
+       TMR_CLEAR_TASK_SET      = 4,
+       TMR_LUN_RESET           = 5,
+       TMR_TARGET_WARM_RESET   = 6,
+       TMR_TARGET_COLD_RESET   = 7,
+       TMR_FABRIC_TMR          = 255,
+};
+
+/* fabric independent task management response values */
+enum tcm_tmrsp_table {
+       TMR_FUNCTION_COMPLETE           = 0,
+       TMR_TASK_DOES_NOT_EXIST         = 1,
+       TMR_LUN_DOES_NOT_EXIST          = 2,
+       TMR_TASK_STILL_ALLEGIANT        = 3,
+       TMR_TASK_FAILOVER_NOT_SUPPORTED = 4,
+       TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED    = 5,
+       TMR_FUNCTION_AUTHORIZATION_FAILED = 6,
+       TMR_FUNCTION_REJECTED           = 255,
+};
+
 struct se_obj {
        atomic_t obj_access_count;
-} ____cacheline_aligned;
+};
 
 /*
  * Used by TCM Core internally to signal if ALUA emulation is enabled or
@@ -207,7 +305,7 @@ struct t10_alua {
        struct config_group alua_tg_pt_gps_group;
        int (*alua_state_check)(struct se_cmd *, unsigned char *, u8 *);
        struct list_head tg_pt_gps_list;
-} ____cacheline_aligned;
+};
 
 struct t10_alua_lu_gp {
        u16     lu_gp_id;
@@ -218,7 +316,7 @@ struct t10_alua_lu_gp {
        struct config_group lu_gp_group;
        struct list_head lu_gp_node;
        struct list_head lu_gp_mem_list;
-} ____cacheline_aligned;
+};
 
 struct t10_alua_lu_gp_member {
        bool lu_gp_assoc;
@@ -227,7 +325,7 @@ struct t10_alua_lu_gp_member {
        struct t10_alua_lu_gp *lu_gp;
        struct se_device *lu_gp_mem_dev;
        struct list_head lu_gp_mem_list;
-} ____cacheline_aligned;
+};
 
 struct t10_alua_tg_pt_gp {
        u16     tg_pt_gp_id;
@@ -250,7 +348,7 @@ struct t10_alua_tg_pt_gp {
        struct config_group tg_pt_gp_group;
        struct list_head tg_pt_gp_list;
        struct list_head tg_pt_gp_mem_list;
-} ____cacheline_aligned;
+};
 
 struct t10_alua_tg_pt_gp_member {
        bool tg_pt_gp_assoc;
@@ -259,7 +357,7 @@ struct t10_alua_tg_pt_gp_member {
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct se_port *tg_pt;
        struct list_head tg_pt_gp_mem_list;
-} ____cacheline_aligned;
+};
 
 struct t10_vpd {
        unsigned char device_identifier[INQUIRY_VPD_DEVICE_IDENTIFIER_LEN];
@@ -269,7 +367,7 @@ struct t10_vpd {
        u32 association;
        u32 device_identifier_type;
        struct list_head vpd_list;
-} ____cacheline_aligned;
+};
 
 struct t10_wwn {
        char vendor[8];
@@ -280,7 +378,7 @@ struct t10_wwn {
        struct se_subsystem_dev *t10_sub_dev;
        struct config_group t10_wwn_group;
        struct list_head t10_vpd_list;
-} ____cacheline_aligned;
+};
 
 
 /*
@@ -333,7 +431,7 @@ struct t10_pr_registration {
        struct list_head pr_reg_aptpl_list;
        struct list_head pr_reg_atp_list;
        struct list_head pr_reg_atp_mem_list;
-} ____cacheline_aligned;
+};
 
 /*
  * This set of function pointer ops is set based upon SPC3_PERSISTENT_RESERVATIONS,
@@ -374,20 +472,20 @@ struct t10_reservation {
        struct list_head registration_list;
        struct list_head aptpl_reg_list;
        struct t10_reservation_ops pr_ops;
-} ____cacheline_aligned;
+};
 
 struct se_queue_req {
        int                     state;
        struct se_cmd           *cmd;
        struct list_head        qr_list;
-} ____cacheline_aligned;
+};
 
 struct se_queue_obj {
        atomic_t                queue_cnt;
        spinlock_t              cmd_queue_lock;
        struct list_head        qobj_list;
        wait_queue_head_t       thread_wq;
-} ____cacheline_aligned;
+};
 
 struct se_task {
        unsigned long long      task_lba;
@@ -397,16 +495,14 @@ struct se_task {
        struct scatterlist      *task_sg;
        u32                     task_sg_nents;
        u16                     task_flags;
-       u8                      task_sense;
        u8                      task_scsi_status;
-       int                     task_error_status;
        enum dma_data_direction task_data_direction;
-       atomic_t                task_state_active;
        struct list_head        t_list;
        struct list_head        t_execute_list;
        struct list_head        t_state_list;
+       bool                    t_state_active;
        struct completion       task_stop_comp;
-} ____cacheline_aligned;
+};
 
 struct se_cmd {
        /* SAM response code being sent to initiator */
@@ -451,6 +547,7 @@ struct se_cmd {
        struct list_head        se_queue_node;
        struct list_head        se_cmd_list;
        struct completion       cmd_wait_comp;
+       struct kref             cmd_kref;
        struct target_core_fabric_ops *se_tfo;
        int (*execute_task)(struct se_task *);
        void (*transport_complete_callback)(struct se_cmd *);
@@ -485,6 +582,7 @@ struct se_cmd {
 
        struct scatterlist      *t_data_sg;
        unsigned int            t_data_nents;
+       void                    *t_data_vmap;
        struct scatterlist      *t_bidi_data_sg;
        unsigned int            t_bidi_data_nents;
 
@@ -492,7 +590,7 @@ struct se_cmd {
        struct list_head        t_task_list;
        u32                     t_task_list_num;
 
-} ____cacheline_aligned;
+};
 
 struct se_tmr_req {
        /* Task Management function to be preformed */
@@ -510,7 +608,7 @@ struct se_tmr_req {
        struct se_device        *tmr_dev;
        struct se_lun           *tmr_lun;
        struct list_head        tmr_list;
-} ____cacheline_aligned;
+};
 
 struct se_ua {
        u8                      ua_asc;
@@ -518,7 +616,7 @@ struct se_ua {
        struct se_node_acl      *ua_nacl;
        struct list_head        ua_dev_list;
        struct list_head        ua_nacl_list;
-} ____cacheline_aligned;
+};
 
 struct se_node_acl {
        char                    initiatorname[TRANSPORT_IQN_LEN];
@@ -545,7 +643,7 @@ struct se_node_acl {
        struct config_group     *acl_default_groups[5];
        struct list_head        acl_list;
        struct list_head        acl_sess_list;
-} ____cacheline_aligned;
+};
 
 struct se_session {
        unsigned                sess_tearing_down:1;
@@ -558,7 +656,7 @@ struct se_session {
        struct list_head        sess_cmd_list;
        struct list_head        sess_wait_list;
        spinlock_t              sess_cmd_lock;
-} ____cacheline_aligned;
+};
 
 struct se_device;
 struct se_transform_info;
@@ -578,7 +676,7 @@ struct se_lun_acl {
        struct list_head        lacl_list;
        struct config_group     se_lun_group;
        struct se_ml_stat_grps  ml_stat_grps;
-}  ____cacheline_aligned;
+};
 
 struct se_dev_entry {
        bool                    def_pr_registered;
@@ -603,7 +701,7 @@ struct se_dev_entry {
        struct se_lun           *se_lun;
        struct list_head        alua_port_list;
        struct list_head        ua_list;
-}  ____cacheline_aligned;
+};
 
 struct se_dev_limits {
        /* Max supported HW queue depth */
@@ -612,7 +710,7 @@ struct se_dev_limits {
        u32             queue_depth;
        /* From include/linux/blkdev.h for the other HW/SW limits. */
        struct queue_limits limits;
-} ____cacheline_aligned;
+};
 
 struct se_dev_attrib {
        int             emulate_dpo;
@@ -641,7 +739,7 @@ struct se_dev_attrib {
        u32             unmap_granularity_alignment;
        struct se_subsystem_dev *da_sub_dev;
        struct config_group da_group;
-} ____cacheline_aligned;
+};
 
 struct se_dev_stat_grps {
        struct config_group stat_group;
@@ -674,7 +772,7 @@ struct se_subsystem_dev {
        struct config_group se_dev_pr_group;
        /* For target_core_stat.c groups */
        struct se_dev_stat_grps dev_stat_grps;
-} ____cacheline_aligned;
+};
 
 struct se_device {
        /* RELATIVE TARGET PORT IDENTIFER Counter */
@@ -685,7 +783,6 @@ struct se_device {
        u32                     dev_port_count;
        /* See transport_device_status_table */
        u32                     dev_status;
-       u32                     dev_tcq_window_closed;
        /* Physical device queue depth */
        u32                     queue_depth;
        /* Used for SPC-2 reservations enforce of ISIDs */
@@ -702,7 +799,6 @@ struct se_device {
        spinlock_t              stats_lock;
        /* Active commands on this virtual SE device */
        atomic_t                simple_cmds;
-       atomic_t                depth_left;
        atomic_t                dev_ordered_id;
        atomic_t                execute_tasks;
        atomic_t                dev_ordered_sync;
@@ -740,7 +836,7 @@ struct se_device {
        struct se_subsystem_api *transport;
        /* Linked list for struct se_hba struct se_device list */
        struct list_head        dev_list;
-}  ____cacheline_aligned;
+};
 
 struct se_hba {
        u16                     hba_tpgt;
@@ -759,7 +855,7 @@ struct se_hba {
        struct config_group     hba_group;
        struct mutex            hba_access_mutex;
        struct se_subsystem_api *transport;
-}  ____cacheline_aligned;
+};
 
 struct se_port_stat_grps {
        struct config_group stat_group;
@@ -785,13 +881,13 @@ struct se_lun {
        struct se_port          *lun_sep;
        struct config_group     lun_group;
        struct se_port_stat_grps port_stat_grps;
-} ____cacheline_aligned;
+};
 
 struct scsi_port_stats {
        u64     cmd_pdus;
        u64     tx_data_octets;
        u64     rx_data_octets;
-} ____cacheline_aligned;
+};
 
 struct se_port {
        /* RELATIVE TARGET PORT IDENTIFER */
@@ -811,12 +907,12 @@ struct se_port {
        struct se_portal_group *sep_tpg;
        struct list_head sep_alua_list;
        struct list_head sep_list;
-} ____cacheline_aligned;
+};
 
 struct se_tpg_np {
        struct se_portal_group *tpg_np_parent;
        struct config_group     tpg_np_group;
-} ____cacheline_aligned;
+};
 
 struct se_portal_group {
        /* Type of target portal group, see transport_tpg_type_table */
@@ -849,13 +945,13 @@ struct se_portal_group {
        struct config_group     tpg_acl_group;
        struct config_group     tpg_attrib_group;
        struct config_group     tpg_param_group;
-} ____cacheline_aligned;
+};
 
 struct se_wwn {
        struct target_fabric_configfs *wwn_tf;
        struct config_group     wwn_group;
        struct config_group     *wwn_default_groups[2];
        struct config_group     fabric_stat_group;
-} ____cacheline_aligned;
+};
 
 #endif /* TARGET_CORE_BASE_H */
diff --git a/include/target/target_core_device.h b/include/target/target_core_device.h
deleted file mode 100644 (file)
index 2be31ff..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef TARGET_CORE_DEVICE_H
-#define TARGET_CORE_DEVICE_H
-
-extern int transport_lookup_cmd_lun(struct se_cmd *, u32);
-extern int transport_lookup_tmr_lun(struct se_cmd *, u32);
-extern struct se_dev_entry *core_get_se_deve_from_rtpi(
-                                       struct se_node_acl *, u16);
-extern int core_free_device_list_for_node(struct se_node_acl *,
-                                       struct se_portal_group *);
-extern void core_dec_lacl_count(struct se_node_acl *, struct se_cmd *);
-extern void core_update_device_list_access(u32, u32, struct se_node_acl *);
-extern int core_update_device_list_for_node(struct se_lun *, struct se_lun_acl *, u32,
-                                       u32, struct se_node_acl *,
-                                       struct se_portal_group *, int);
-extern void core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
-extern int core_dev_export(struct se_device *, struct se_portal_group *,
-                                       struct se_lun *);
-extern void core_dev_unexport(struct se_device *, struct se_portal_group *,
-                                       struct se_lun *);
-extern int target_report_luns(struct se_task *);
-extern void se_release_device_for_hba(struct se_device *);
-extern void se_release_vpd_for_dev(struct se_device *);
-extern void se_clear_dev_ports(struct se_device *);
-extern int se_free_virtual_device(struct se_device *, struct se_hba *);
-extern int se_dev_check_online(struct se_device *);
-extern int se_dev_check_shutdown(struct se_device *);
-extern void se_dev_set_default_attribs(struct se_device *, struct se_dev_limits *);
-extern int se_dev_set_task_timeout(struct se_device *, u32);
-extern int se_dev_set_max_unmap_lba_count(struct se_device *, u32);
-extern int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
-extern int se_dev_set_unmap_granularity(struct se_device *, u32);
-extern int se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
-extern int se_dev_set_emulate_dpo(struct se_device *, int);
-extern int se_dev_set_emulate_fua_write(struct se_device *, int);
-extern int se_dev_set_emulate_fua_read(struct se_device *, int);
-extern int se_dev_set_emulate_write_cache(struct se_device *, int);
-extern int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *, int);
-extern int se_dev_set_emulate_tas(struct se_device *, int);
-extern int se_dev_set_emulate_tpu(struct se_device *, int);
-extern int se_dev_set_emulate_tpws(struct se_device *, int);
-extern int se_dev_set_enforce_pr_isids(struct se_device *, int);
-extern int se_dev_set_is_nonrot(struct se_device *, int);
-extern int se_dev_set_emulate_rest_reord(struct se_device *dev, int);
-extern int se_dev_set_queue_depth(struct se_device *, u32);
-extern int se_dev_set_max_sectors(struct se_device *, u32);
-extern int se_dev_set_optimal_sectors(struct se_device *, u32);
-extern int se_dev_set_block_size(struct se_device *, u32);
-extern struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_hba *,
-                                       struct se_device *, u32);
-extern int core_dev_del_lun(struct se_portal_group *, u32);
-extern struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
-extern struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
-                                                       u32, char *, int *);
-extern int core_dev_add_initiator_node_lun_acl(struct se_portal_group *,
-                                               struct se_lun_acl *, u32, u32);
-extern int core_dev_del_initiator_node_lun_acl(struct se_portal_group *,
-                                               struct se_lun *, struct se_lun_acl *);
-extern void core_dev_free_initiator_node_lun_acl(struct se_portal_group *,
-                                               struct se_lun_acl *lacl);
-extern int core_dev_setup_virtual_lun0(void);
-extern void core_dev_release_virtual_lun0(void);
-
-#endif /* TARGET_CORE_DEVICE_H */
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
new file mode 100644 (file)
index 0000000..d36fad3
--- /dev/null
@@ -0,0 +1,187 @@
+#ifndef TARGET_CORE_FABRIC_H
+#define TARGET_CORE_FABRIC_H
+
+struct target_core_fabric_ops {
+       struct configfs_subsystem *tf_subsys;
+       /*
+        * Optional to signal struct se_task->task_sg[] padding entries
+        * for scatterlist chaining using transport_do_task_sg_link(),
+        * disabled by default
+        */
+       bool task_sg_chaining;
+       char *(*get_fabric_name)(void);
+       u8 (*get_fabric_proto_ident)(struct se_portal_group *);
+       char *(*tpg_get_wwn)(struct se_portal_group *);
+       u16 (*tpg_get_tag)(struct se_portal_group *);
+       u32 (*tpg_get_default_depth)(struct se_portal_group *);
+       u32 (*tpg_get_pr_transport_id)(struct se_portal_group *,
+                               struct se_node_acl *,
+                               struct t10_pr_registration *, int *,
+                               unsigned char *);
+       u32 (*tpg_get_pr_transport_id_len)(struct se_portal_group *,
+                               struct se_node_acl *,
+                               struct t10_pr_registration *, int *);
+       char *(*tpg_parse_pr_out_transport_id)(struct se_portal_group *,
+                               const char *, u32 *, char **);
+       int (*tpg_check_demo_mode)(struct se_portal_group *);
+       int (*tpg_check_demo_mode_cache)(struct se_portal_group *);
+       int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *);
+       int (*tpg_check_prod_mode_write_protect)(struct se_portal_group *);
+       /*
+        * Optionally used by fabrics to allow demo-mode login, but not
+        * expose any TPG LUNs, and return 'not connected' in standard
+        * inquiry response
+        */
+       int (*tpg_check_demo_mode_login_only)(struct se_portal_group *);
+       struct se_node_acl *(*tpg_alloc_fabric_acl)(
+                                       struct se_portal_group *);
+       void (*tpg_release_fabric_acl)(struct se_portal_group *,
+                                       struct se_node_acl *);
+       u32 (*tpg_get_inst_index)(struct se_portal_group *);
+       /*
+        * Optional function pointer for TCM to perform command map
+        * from TCM processing thread context, for those struct se_cmd
+        * initially allocated in interrupt context.
+        */
+       int (*new_cmd_map)(struct se_cmd *);
+       /*
+        * Optional to release struct se_cmd and fabric dependent allocated
+        * I/O descriptor in transport_cmd_check_stop().
+        *
+        * Returning 1 will signal a descriptor has been released.
+        * Returning 0 will signal a descriptor has not been released.
+        */
+       int (*check_stop_free)(struct se_cmd *);
+       void (*release_cmd)(struct se_cmd *);
+       /*
+        * Called with spin_lock_bh(struct se_portal_group->session_lock held.
+        */
+       int (*shutdown_session)(struct se_session *);
+       void (*close_session)(struct se_session *);
+       void (*stop_session)(struct se_session *, int, int);
+       void (*fall_back_to_erl0)(struct se_session *);
+       int (*sess_logged_in)(struct se_session *);
+       u32 (*sess_get_index)(struct se_session *);
+       /*
+        * Used only for SCSI fabrics that contain multi-value TransportIDs
+        * (like iSCSI).  All other SCSI fabrics should set this to NULL.
+        */
+       u32 (*sess_get_initiator_sid)(struct se_session *,
+                                     unsigned char *, u32);
+       int (*write_pending)(struct se_cmd *);
+       int (*write_pending_status)(struct se_cmd *);
+       void (*set_default_node_attributes)(struct se_node_acl *);
+       u32 (*get_task_tag)(struct se_cmd *);
+       int (*get_cmd_state)(struct se_cmd *);
+       int (*queue_data_in)(struct se_cmd *);
+       int (*queue_status)(struct se_cmd *);
+       int (*queue_tm_rsp)(struct se_cmd *);
+       u16 (*set_fabric_sense_len)(struct se_cmd *, u32);
+       u16 (*get_fabric_sense_len)(void);
+       int (*is_state_remove)(struct se_cmd *);
+       /*
+        * fabric module calls for target_core_fabric_configfs.c
+        */
+       struct se_wwn *(*fabric_make_wwn)(struct target_fabric_configfs *,
+                               struct config_group *, const char *);
+       void (*fabric_drop_wwn)(struct se_wwn *);
+       struct se_portal_group *(*fabric_make_tpg)(struct se_wwn *,
+                               struct config_group *, const char *);
+       void (*fabric_drop_tpg)(struct se_portal_group *);
+       int (*fabric_post_link)(struct se_portal_group *,
+                               struct se_lun *);
+       void (*fabric_pre_unlink)(struct se_portal_group *,
+                               struct se_lun *);
+       struct se_tpg_np *(*fabric_make_np)(struct se_portal_group *,
+                               struct config_group *, const char *);
+       void (*fabric_drop_np)(struct se_tpg_np *);
+       struct se_node_acl *(*fabric_make_nodeacl)(struct se_portal_group *,
+                               struct config_group *, const char *);
+       void (*fabric_drop_nodeacl)(struct se_node_acl *);
+};
+
+struct se_session *transport_init_session(void);
+void   __transport_register_session(struct se_portal_group *,
+               struct se_node_acl *, struct se_session *, void *);
+void   transport_register_session(struct se_portal_group *,
+               struct se_node_acl *, struct se_session *, void *);
+void   transport_free_session(struct se_session *);
+void   transport_deregister_session_configfs(struct se_session *);
+void   transport_deregister_session(struct se_session *);
+
+
+void   transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
+               struct se_session *, u32, int, int, unsigned char *);
+int    transport_lookup_cmd_lun(struct se_cmd *, u32);
+int    transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
+void   target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
+               unsigned char *, u32, u32, int, int, int);
+int    transport_handle_cdb_direct(struct se_cmd *);
+int    transport_generic_handle_cdb_map(struct se_cmd *);
+int    transport_generic_handle_data(struct se_cmd *);
+int    transport_generic_map_mem_to_cmd(struct se_cmd *cmd,
+               struct scatterlist *, u32, struct scatterlist *, u32);
+void   transport_do_task_sg_chain(struct se_cmd *);
+int    transport_generic_new_cmd(struct se_cmd *);
+
+void   transport_generic_process_write(struct se_cmd *);
+
+void   transport_generic_free_cmd(struct se_cmd *, int);
+
+bool   transport_wait_for_tasks(struct se_cmd *);
+int    transport_check_aborted_status(struct se_cmd *, int);
+int    transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
+
+void   target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
+int    target_put_sess_cmd(struct se_session *, struct se_cmd *);
+void   target_splice_sess_cmd_list(struct se_session *);
+void   target_wait_for_sess_cmds(struct se_session *, int);
+
+int    core_alua_check_nonop_delay(struct se_cmd *);
+
+struct se_tmr_req *core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
+void   core_tmr_release_req(struct se_tmr_req *);
+int    transport_generic_handle_tmr(struct se_cmd *);
+int    transport_lookup_tmr_lun(struct se_cmd *, u32);
+
+struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
+               unsigned char *);
+void   core_tpg_clear_object_luns(struct se_portal_group *);
+struct se_node_acl *core_tpg_add_initiator_node_acl(struct se_portal_group *,
+               struct se_node_acl *, const char *, u32);
+int    core_tpg_del_initiator_node_acl(struct se_portal_group *,
+               struct se_node_acl *, int);
+int    core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
+               unsigned char *, u32, int);
+int    core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *,
+               struct se_portal_group *, void *, int);
+int    core_tpg_deregister(struct se_portal_group *);
+
+/* SAS helpers */
+u8     sas_get_fabric_proto_ident(struct se_portal_group *);
+u32    sas_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
+               struct t10_pr_registration *, int *, unsigned char *);
+u32    sas_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
+               struct t10_pr_registration *, int *);
+char   *sas_parse_pr_out_transport_id(struct se_portal_group *, const char *,
+               u32 *, char **);
+
+/* FC helpers */
+u8     fc_get_fabric_proto_ident(struct se_portal_group *);
+u32    fc_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
+               struct t10_pr_registration *, int *, unsigned char *);
+u32    fc_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
+               struct t10_pr_registration *, int *);
+char   *fc_parse_pr_out_transport_id(struct se_portal_group *, const char *,
+               u32 *, char **);
+
+/* iSCSI helpers */
+u8     iscsi_get_fabric_proto_ident(struct se_portal_group *);
+u32    iscsi_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
+               struct t10_pr_registration *, int *, unsigned char *);
+u32    iscsi_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
+               struct t10_pr_registration *, int *);
+char   *iscsi_parse_pr_out_transport_id(struct se_portal_group *, const char *,
+               u32 *, char **);
+
+#endif /* TARGET_CORE_FABRICH */
diff --git a/include/target/target_core_fabric_lib.h b/include/target/target_core_fabric_lib.h
deleted file mode 100644 (file)
index c2f8d0e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef TARGET_CORE_FABRIC_LIB_H
-#define TARGET_CORE_FABRIC_LIB_H
-
-extern u8 sas_get_fabric_proto_ident(struct se_portal_group *);
-extern u32 sas_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
-                       struct t10_pr_registration *, int *, unsigned char *);
-extern u32 sas_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
-                       struct t10_pr_registration *, int *);
-extern char *sas_parse_pr_out_transport_id(struct se_portal_group *,
-                       const char *, u32 *, char **);
-
-extern u8 fc_get_fabric_proto_ident(struct se_portal_group *);
-extern u32 fc_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
-                       struct t10_pr_registration *, int *, unsigned char *);
-extern u32 fc_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
-                       struct t10_pr_registration *, int *);
-extern char *fc_parse_pr_out_transport_id(struct se_portal_group *,
-                       const char *, u32 *, char **);
-
-extern u8 iscsi_get_fabric_proto_ident(struct se_portal_group *);
-extern u32 iscsi_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
-                       struct t10_pr_registration *, int *, unsigned char *);
-extern u32 iscsi_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
-                       struct t10_pr_registration *, int *);
-extern char *iscsi_parse_pr_out_transport_id(struct se_portal_group *,
-                       const char *, u32 *, char **);
-
-#endif /* TARGET_CORE_FABRIC_LIB_H */
diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h
deleted file mode 100644 (file)
index 0256825..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Defined in target_core_configfs.h */
-struct target_fabric_configfs;
-
-struct target_core_fabric_ops {
-       struct configfs_subsystem *tf_subsys;
-       /*
-        * Optional to signal struct se_task->task_sg[] padding entries
-        * for scatterlist chaining using transport_do_task_sg_link(),
-        * disabled by default
-        */
-       bool task_sg_chaining;
-       char *(*get_fabric_name)(void);
-       u8 (*get_fabric_proto_ident)(struct se_portal_group *);
-       char *(*tpg_get_wwn)(struct se_portal_group *);
-       u16 (*tpg_get_tag)(struct se_portal_group *);
-       u32 (*tpg_get_default_depth)(struct se_portal_group *);
-       u32 (*tpg_get_pr_transport_id)(struct se_portal_group *,
-                               struct se_node_acl *,
-                               struct t10_pr_registration *, int *,
-                               unsigned char *);
-       u32 (*tpg_get_pr_transport_id_len)(struct se_portal_group *,
-                               struct se_node_acl *,
-                               struct t10_pr_registration *, int *);
-       char *(*tpg_parse_pr_out_transport_id)(struct se_portal_group *,
-                               const char *, u32 *, char **);
-       int (*tpg_check_demo_mode)(struct se_portal_group *);
-       int (*tpg_check_demo_mode_cache)(struct se_portal_group *);
-       int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *);
-       int (*tpg_check_prod_mode_write_protect)(struct se_portal_group *);
-       /*
-        * Optionally used by fabrics to allow demo-mode login, but not
-        * expose any TPG LUNs, and return 'not connected' in standard
-        * inquiry response
-        */
-       int (*tpg_check_demo_mode_login_only)(struct se_portal_group *);
-       struct se_node_acl *(*tpg_alloc_fabric_acl)(
-                                       struct se_portal_group *);
-       void (*tpg_release_fabric_acl)(struct se_portal_group *,
-                                       struct se_node_acl *);
-       u32 (*tpg_get_inst_index)(struct se_portal_group *);
-       /*
-        * Optional function pointer for TCM to perform command map
-        * from TCM processing thread context, for those struct se_cmd
-        * initially allocated in interrupt context.
-        */
-       int (*new_cmd_map)(struct se_cmd *);
-       /*
-        * Optional to release struct se_cmd and fabric dependent allocated
-        * I/O descriptor in transport_cmd_check_stop().
-        *
-        * Returning 1 will signal a descriptor has been released.
-        * Returning 0 will signal a descriptor has not been released.
-        */
-       int (*check_stop_free)(struct se_cmd *);
-       /*
-        * Optional check for active I/O shutdown
-        */
-       int (*check_release_cmd)(struct se_cmd *);
-       void (*release_cmd)(struct se_cmd *);
-       /*
-        * Called with spin_lock_bh(struct se_portal_group->session_lock held.
-        */
-       int (*shutdown_session)(struct se_session *);
-       void (*close_session)(struct se_session *);
-       void (*stop_session)(struct se_session *, int, int);
-       void (*fall_back_to_erl0)(struct se_session *);
-       int (*sess_logged_in)(struct se_session *);
-       u32 (*sess_get_index)(struct se_session *);
-       /*
-        * Used only for SCSI fabrics that contain multi-value TransportIDs
-        * (like iSCSI).  All other SCSI fabrics should set this to NULL.
-        */
-       u32 (*sess_get_initiator_sid)(struct se_session *,
-                                     unsigned char *, u32);
-       int (*write_pending)(struct se_cmd *);
-       int (*write_pending_status)(struct se_cmd *);
-       void (*set_default_node_attributes)(struct se_node_acl *);
-       u32 (*get_task_tag)(struct se_cmd *);
-       int (*get_cmd_state)(struct se_cmd *);
-       int (*queue_data_in)(struct se_cmd *);
-       int (*queue_status)(struct se_cmd *);
-       int (*queue_tm_rsp)(struct se_cmd *);
-       u16 (*set_fabric_sense_len)(struct se_cmd *, u32);
-       u16 (*get_fabric_sense_len)(void);
-       int (*is_state_remove)(struct se_cmd *);
-       /*
-        * fabric module calls for target_core_fabric_configfs.c
-        */
-       struct se_wwn *(*fabric_make_wwn)(struct target_fabric_configfs *,
-                               struct config_group *, const char *);
-       void (*fabric_drop_wwn)(struct se_wwn *);
-       struct se_portal_group *(*fabric_make_tpg)(struct se_wwn *,
-                               struct config_group *, const char *);
-       void (*fabric_drop_tpg)(struct se_portal_group *);
-       int (*fabric_post_link)(struct se_portal_group *,
-                               struct se_lun *);
-       void (*fabric_pre_unlink)(struct se_portal_group *,
-                               struct se_lun *);
-       struct se_tpg_np *(*fabric_make_np)(struct se_portal_group *,
-                               struct config_group *, const char *);
-       void (*fabric_drop_np)(struct se_tpg_np *);
-       struct se_node_acl *(*fabric_make_nodeacl)(struct se_portal_group *,
-                               struct config_group *, const char *);
-       void (*fabric_drop_nodeacl)(struct se_node_acl *);
-};
diff --git a/include/target/target_core_tmr.h b/include/target/target_core_tmr.h
deleted file mode 100644 (file)
index d5876e1..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef TARGET_CORE_TMR_H
-#define TARGET_CORE_TMR_H
-
-/* fabric independent task management function values */
-enum tcm_tmreq_table {
-       TMR_ABORT_TASK          = 1,
-       TMR_ABORT_TASK_SET      = 2,
-       TMR_CLEAR_ACA           = 3,
-       TMR_CLEAR_TASK_SET      = 4,
-       TMR_LUN_RESET           = 5,
-       TMR_TARGET_WARM_RESET   = 6,
-       TMR_TARGET_COLD_RESET   = 7,
-       TMR_FABRIC_TMR          = 255,
-};
-
-/* fabric independent task management response values */
-enum tcm_tmrsp_table {
-       TMR_FUNCTION_COMPLETE           = 0,
-       TMR_TASK_DOES_NOT_EXIST         = 1,
-       TMR_LUN_DOES_NOT_EXIST          = 2,
-       TMR_TASK_STILL_ALLEGIANT        = 3,
-       TMR_TASK_FAILOVER_NOT_SUPPORTED = 4,
-       TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED    = 5,
-       TMR_FUNCTION_AUTHORIZATION_FAILED = 6,
-       TMR_FUNCTION_REJECTED           = 255,
-};
-
-extern struct kmem_cache *se_tmr_req_cache;
-
-extern struct se_tmr_req *core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
-extern void core_tmr_release_req(struct se_tmr_req *);
-extern int core_tmr_lun_reset(struct se_device *, struct se_tmr_req *,
-                               struct list_head *, struct se_cmd *);
-
-#endif /* TARGET_CORE_TMR_H */
diff --git a/include/target/target_core_tpg.h b/include/target/target_core_tpg.h
deleted file mode 100644 (file)
index 77e1872..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef TARGET_CORE_TPG_H
-#define TARGET_CORE_TPG_H
-
-extern struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
-                                               const char *);
-extern struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
-                                               unsigned char *);
-extern void core_tpg_add_node_to_devs(struct se_node_acl *,
-                                               struct se_portal_group *);
-extern struct se_node_acl *core_tpg_check_initiator_node_acl(
-                                               struct se_portal_group *,
-                                               unsigned char *);
-extern void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
-extern void core_tpg_wait_for_mib_ref(struct se_node_acl *);
-extern void core_tpg_clear_object_luns(struct se_portal_group *);
-extern struct se_node_acl *core_tpg_add_initiator_node_acl(
-                                       struct se_portal_group *,
-                                       struct se_node_acl *,
-                                       const char *, u32);
-extern int core_tpg_del_initiator_node_acl(struct se_portal_group *,
-                                               struct se_node_acl *, int);
-extern int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
-                                               unsigned char *, u32, int);
-extern int core_tpg_register(struct target_core_fabric_ops *,
-                                       struct se_wwn *,
-                                       struct se_portal_group *, void *,
-                                       int);
-extern int core_tpg_deregister(struct se_portal_group *);
-extern struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
-extern int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *, u32,
-                               void *);
-extern struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *);
-extern int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
-
-#endif /* TARGET_CORE_TPG_H */
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h
deleted file mode 100644 (file)
index dac4f2d..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-#ifndef TARGET_CORE_TRANSPORT_H
-#define TARGET_CORE_TRANSPORT_H
-
-#define TARGET_CORE_VERSION                    TARGET_CORE_MOD_VERSION
-
-/* Attempts before moving from SHORT to LONG */
-#define PYX_TRANSPORT_WINDOW_CLOSED_THRESHOLD  3
-#define PYX_TRANSPORT_WINDOW_CLOSED_WAIT_SHORT 3  /* In milliseconds */
-#define PYX_TRANSPORT_WINDOW_CLOSED_WAIT_LONG  10 /* In milliseconds */
-
-#define PYX_TRANSPORT_STATUS_INTERVAL          5 /* In seconds */
-
-#define TRANSPORT_PLUGIN_PHBA_PDEV             1
-#define TRANSPORT_PLUGIN_VHBA_PDEV             2
-#define TRANSPORT_PLUGIN_VHBA_VDEV             3
-
-/*
- * struct se_subsystem_dev->su_dev_flags
-*/
-#define SDF_FIRMWARE_VPD_UNIT_SERIAL           0x00000001
-#define SDF_EMULATED_VPD_UNIT_SERIAL           0x00000002
-#define SDF_USING_UDEV_PATH                    0x00000004
-#define SDF_USING_ALIAS                                0x00000008
-
-/*
- * struct se_device->dev_flags
- */
-#define DF_READ_ONLY                           0x00000001
-#define DF_SPC2_RESERVATIONS                   0x00000002
-#define DF_SPC2_RESERVATIONS_WITH_ISID         0x00000004
-
-/* struct se_dev_attrib sanity values */
-/* Default max_unmap_lba_count */
-#define DA_MAX_UNMAP_LBA_COUNT                 0
-/* Default max_unmap_block_desc_count */
-#define DA_MAX_UNMAP_BLOCK_DESC_COUNT          0
-/* Default unmap_granularity */
-#define DA_UNMAP_GRANULARITY_DEFAULT           0
-/* Default unmap_granularity_alignment */
-#define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0
-/* Emulation for Direct Page Out */
-#define DA_EMULATE_DPO                         0
-/* Emulation for Forced Unit Access WRITEs */
-#define DA_EMULATE_FUA_WRITE                   1
-/* Emulation for Forced Unit Access READs */
-#define DA_EMULATE_FUA_READ                    0
-/* Emulation for WriteCache and SYNCHRONIZE_CACHE */
-#define DA_EMULATE_WRITE_CACHE                 0
-/* Emulation for UNIT ATTENTION Interlock Control */
-#define DA_EMULATE_UA_INTLLCK_CTRL             0
-/* Emulation for TASK_ABORTED status (TAS) by default */
-#define DA_EMULATE_TAS                         1
-/* Emulation for Thin Provisioning UNMAP using block/blk-lib.c:blkdev_issue_discard() */
-#define DA_EMULATE_TPU                         0
-/*
- * Emulation for Thin Provisioning WRITE_SAME w/ UNMAP=1 bit using
- * block/blk-lib.c:blkdev_issue_discard()
- */
-#define DA_EMULATE_TPWS                                0
-/* No Emulation for PSCSI by default */
-#define DA_EMULATE_RESERVATIONS                        0
-/* No Emulation for PSCSI by default */
-#define DA_EMULATE_ALUA                                0
-/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
-#define DA_ENFORCE_PR_ISIDS                    1
-#define DA_STATUS_MAX_SECTORS_MIN              16
-#define DA_STATUS_MAX_SECTORS_MAX              8192
-/* By default don't report non-rotating (solid state) medium */
-#define DA_IS_NONROT                           0
-/* Queue Algorithm Modifier default for restricted reordering in control mode page */
-#define DA_EMULATE_REST_REORD                  0
-
-#define SE_MODE_PAGE_BUF                       512
-
-#define MOD_MAX_SECTORS(ms, bs)                        (ms % (PAGE_SIZE / bs))
-
-struct se_subsystem_api;
-
-extern int init_se_kmem_caches(void);
-extern void release_se_kmem_caches(void);
-extern u32 scsi_get_new_index(scsi_index_t);
-extern void transport_init_queue_obj(struct se_queue_obj *);
-extern void transport_subsystem_check_init(void);
-extern int transport_subsystem_register(struct se_subsystem_api *);
-extern void transport_subsystem_release(struct se_subsystem_api *);
-extern void transport_load_plugins(void);
-extern struct se_session *transport_init_session(void);
-extern void __transport_register_session(struct se_portal_group *,
-                                       struct se_node_acl *,
-                                       struct se_session *, void *);
-extern void transport_register_session(struct se_portal_group *,
-                                       struct se_node_acl *,
-                                       struct se_session *, void *);
-extern void transport_free_session(struct se_session *);
-extern void transport_deregister_session_configfs(struct se_session *);
-extern void transport_deregister_session(struct se_session *);
-extern void transport_cmd_finish_abort(struct se_cmd *, int);
-extern void transport_complete_sync_cache(struct se_cmd *, int);
-extern void transport_complete_task(struct se_task *, int);
-extern void transport_add_task_to_execute_queue(struct se_task *,
-                                               struct se_task *,
-                                               struct se_device *);
-extern void transport_remove_task_from_execute_queue(struct se_task *,
-                                               struct se_device *);
-extern void __transport_remove_task_from_execute_queue(struct se_task *,
-                                               struct se_device *);
-unsigned char *transport_dump_cmd_direction(struct se_cmd *);
-extern void transport_dump_dev_state(struct se_device *, char *, int *);
-extern void transport_dump_dev_info(struct se_device *, struct se_lun *,
-                                       unsigned long long, char *, int *);
-extern void transport_dump_vpd_proto_id(struct t10_vpd *,
-                                       unsigned char *, int);
-extern void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
-extern int transport_dump_vpd_assoc(struct t10_vpd *,
-                                       unsigned char *, int);
-extern int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
-extern int transport_dump_vpd_ident_type(struct t10_vpd *,
-                                       unsigned char *, int);
-extern int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
-extern int transport_dump_vpd_ident(struct t10_vpd *,
-                                       unsigned char *, int);
-extern int transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
-extern struct se_device *transport_add_device_to_core_hba(struct se_hba *,
-                                       struct se_subsystem_api *,
-                                       struct se_subsystem_dev *, u32,
-                                       void *, struct se_dev_limits *,
-                                       const char *, const char *);
-extern void transport_init_se_cmd(struct se_cmd *,
-                                       struct target_core_fabric_ops *,
-                                       struct se_session *, u32, int, int,
-                                       unsigned char *);
-void *transport_kmap_first_data_page(struct se_cmd *cmd);
-void transport_kunmap_first_data_page(struct se_cmd *cmd);
-extern int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
-extern int transport_handle_cdb_direct(struct se_cmd *);
-extern int transport_generic_handle_cdb_map(struct se_cmd *);
-extern int transport_generic_handle_data(struct se_cmd *);
-extern int transport_generic_handle_tmr(struct se_cmd *);
-extern bool target_stop_task(struct se_task *task, unsigned long *flags);
-extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
-                               struct scatterlist *, u32);
-extern int transport_clear_lun_from_sessions(struct se_lun *);
-extern bool transport_wait_for_tasks(struct se_cmd *);
-extern int transport_check_aborted_status(struct se_cmd *, int);
-extern int transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
-extern void transport_send_task_abort(struct se_cmd *);
-extern void transport_release_cmd(struct se_cmd *);
-extern void transport_generic_free_cmd(struct se_cmd *, int);
-extern void target_get_sess_cmd(struct se_session *, struct se_cmd *);
-extern int target_put_sess_cmd(struct se_session *, struct se_cmd *);
-extern void target_splice_sess_cmd_list(struct se_session *);
-extern void target_wait_for_sess_cmds(struct se_session *, int);
-extern void transport_generic_wait_for_cmds(struct se_cmd *, int);
-extern void transport_do_task_sg_chain(struct se_cmd *);
-extern void transport_generic_process_write(struct se_cmd *);
-extern int transport_generic_new_cmd(struct se_cmd *);
-extern int transport_generic_do_tmr(struct se_cmd *);
-/* From target_core_alua.c */
-extern int core_alua_check_nonop_delay(struct se_cmd *);
-/* From target_core_cdb.c */
-extern int transport_emulate_control_cdb(struct se_task *);
-extern void target_get_task_cdb(struct se_task *task, unsigned char *cdb);
-
-/*
- * Each se_transport_task_t can have N number of possible struct se_task's
- * for the storage transport(s) to possibly execute.
- * Used primarily for splitting up CDBs that exceed the physical storage
- * HBA's maximum sector count per task.
- */
-struct se_mem {
-       struct page     *se_page;
-       u32             se_len;
-       u32             se_off;
-       struct list_head se_list;
-} ____cacheline_aligned;
-
-/*
- *     Each type of disk transport supported MUST have a template defined
- *     within its .h file.
- */
-struct se_subsystem_api {
-       /*
-        * The Name. :-)
-        */
-       char name[16];
-       /*
-        * Transport Type.
-        */
-       u8 transport_type;
-
-       unsigned int fua_write_emulated : 1;
-       unsigned int write_cache_emulated : 1;
-
-       /*
-        * struct module for struct se_hba references
-        */
-       struct module *owner;
-       /*
-        * Used for global se_subsystem_api list_head
-        */
-       struct list_head sub_api_list;
-       /*
-        * attach_hba():
-        */
-       int (*attach_hba)(struct se_hba *, u32);
-       /*
-        * detach_hba():
-        */
-       void (*detach_hba)(struct se_hba *);
-       /*
-        * pmode_hba(): Used for TCM/pSCSI subsystem plugin HBA ->
-        *              Linux/SCSI struct Scsi_Host passthrough
-       */
-       int (*pmode_enable_hba)(struct se_hba *, unsigned long);
-       /*
-        * allocate_virtdevice():
-        */
-       void *(*allocate_virtdevice)(struct se_hba *, const char *);
-       /*
-        * create_virtdevice(): Only for Virtual HBAs
-        */
-       struct se_device *(*create_virtdevice)(struct se_hba *,
-                               struct se_subsystem_dev *, void *);
-       /*
-        * free_device():
-        */
-       void (*free_device)(void *);
-
-       /*
-        * transport_complete():
-        *
-        * Use transport_generic_complete() for majority of DAS transport
-        * drivers.  Provided out of convenience.
-        */
-       int (*transport_complete)(struct se_task *task);
-       struct se_task *(*alloc_task)(unsigned char *cdb);
-       /*
-        * do_task():
-        */
-       int (*do_task)(struct se_task *);
-       /*
-        * Used by virtual subsystem plugins IBLOCK and FILEIO to emulate
-        * UNMAP and WRITE_SAME_* w/ UNMAP=1 <-> Linux/Block Discard
-        */
-       int (*do_discard)(struct se_device *, sector_t, u32);
-       /*
-        * Used  by virtual subsystem plugins IBLOCK and FILEIO to emulate
-        * SYNCHRONIZE_CACHE_* <-> Linux/Block blkdev_issue_flush()
-        */
-       void (*do_sync_cache)(struct se_task *);
-       /*
-        * free_task():
-        */
-       void (*free_task)(struct se_task *);
-       /*
-        * check_configfs_dev_params():
-        */
-       ssize_t (*check_configfs_dev_params)(struct se_hba *, struct se_subsystem_dev *);
-       /*
-        * set_configfs_dev_params():
-        */
-       ssize_t (*set_configfs_dev_params)(struct se_hba *, struct se_subsystem_dev *,
-                                               const char *, ssize_t);
-       /*
-        * show_configfs_dev_params():
-        */
-       ssize_t (*show_configfs_dev_params)(struct se_hba *, struct se_subsystem_dev *,
-                                               char *);
-       /*
-        * get_device_rev():
-        */
-       u32 (*get_device_rev)(struct se_device *);
-       /*
-        * get_device_type():
-        */
-       u32 (*get_device_type)(struct se_device *);
-       /*
-        * Get the sector_t from a subsystem backstore..
-        */
-       sector_t (*get_blocks)(struct se_device *);
-       /*
-        * get_sense_buffer():
-        */
-       unsigned char *(*get_sense_buffer)(struct se_task *);
-} ____cacheline_aligned;
-
-#endif /* TARGET_CORE_TRANSPORT_H */
index b31702ac15beb3f31ea7f2b5c1c36dd2b64b2f70..84f3001a568d9edf435c0465b7d421bbc74e858c 100644 (file)
@@ -16,6 +16,8 @@ struct btrfs_delayed_ref_node;
 struct btrfs_delayed_tree_ref;
 struct btrfs_delayed_data_ref;
 struct btrfs_delayed_ref_head;
+struct btrfs_block_group_cache;
+struct btrfs_free_cluster;
 struct map_lookup;
 struct extent_buffer;
 
@@ -44,6 +46,17 @@ struct extent_buffer;
        obj, ((obj >= BTRFS_DATA_RELOC_TREE_OBJECTID) ||                \
              (obj <= BTRFS_CSUM_TREE_OBJECTID )) ? __show_root_type(obj) : "-"
 
+#define BTRFS_GROUP_FLAGS      \
+       { BTRFS_BLOCK_GROUP_DATA,       "DATA"}, \
+       { BTRFS_BLOCK_GROUP_SYSTEM,     "SYSTEM"}, \
+       { BTRFS_BLOCK_GROUP_METADATA,   "METADATA"}, \
+       { BTRFS_BLOCK_GROUP_RAID0,      "RAID0"}, \
+       { BTRFS_BLOCK_GROUP_RAID1,      "RAID1"}, \
+       { BTRFS_BLOCK_GROUP_DUP,        "DUP"}, \
+       { BTRFS_BLOCK_GROUP_RAID10,     "RAID10"}
+
+#define BTRFS_UUID_SIZE 16
+
 TRACE_EVENT(btrfs_transaction_commit,
 
        TP_PROTO(struct btrfs_root *root),
@@ -621,6 +634,34 @@ TRACE_EVENT(btrfs_cow_block,
                  __entry->cow_level)
 );
 
+TRACE_EVENT(btrfs_space_reservation,
+
+       TP_PROTO(struct btrfs_fs_info *fs_info, char *type, u64 val,
+                u64 bytes, int reserve),
+
+       TP_ARGS(fs_info, type, val, bytes, reserve),
+
+       TP_STRUCT__entry(
+               __array(        u8,     fsid,   BTRFS_UUID_SIZE )
+               __string(       type,   type                    )
+               __field(        u64,    val                     )
+               __field(        u64,    bytes                   )
+               __field(        int,    reserve                 )
+       ),
+
+       TP_fast_assign(
+               memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE);
+               __assign_str(type, type);
+               __entry->val            = val;
+               __entry->bytes          = bytes;
+               __entry->reserve        = reserve;
+       ),
+
+       TP_printk("%pU: %s: %Lu %s %Lu", __entry->fsid, __get_str(type),
+                 __entry->val, __entry->reserve ? "reserve" : "release",
+                 __entry->bytes)
+);
+
 DECLARE_EVENT_CLASS(btrfs__reserved_extent,
 
        TP_PROTO(struct btrfs_root *root, u64 start, u64 len),
@@ -659,6 +700,168 @@ DEFINE_EVENT(btrfs__reserved_extent,  btrfs_reserved_extent_free,
        TP_ARGS(root, start, len)
 );
 
+TRACE_EVENT(find_free_extent,
+
+       TP_PROTO(struct btrfs_root *root, u64 num_bytes, u64 empty_size,
+                u64 data),
+
+       TP_ARGS(root, num_bytes, empty_size, data),
+
+       TP_STRUCT__entry(
+               __field(        u64,    root_objectid           )
+               __field(        u64,    num_bytes               )
+               __field(        u64,    empty_size              )
+               __field(        u64,    data                    )
+       ),
+
+       TP_fast_assign(
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->num_bytes      = num_bytes;
+               __entry->empty_size     = empty_size;
+               __entry->data           = data;
+       ),
+
+       TP_printk("root = %Lu(%s), len = %Lu, empty_size = %Lu, "
+                 "flags = %Lu(%s)", show_root_type(__entry->root_objectid),
+                 __entry->num_bytes, __entry->empty_size, __entry->data,
+                 __print_flags((unsigned long)__entry->data, "|",
+                                BTRFS_GROUP_FLAGS))
+);
+
+DECLARE_EVENT_CLASS(btrfs__reserve_extent,
+
+       TP_PROTO(struct btrfs_root *root,
+                struct btrfs_block_group_cache *block_group, u64 start,
+                u64 len),
+
+       TP_ARGS(root, block_group, start, len),
+
+       TP_STRUCT__entry(
+               __field(        u64,    root_objectid           )
+               __field(        u64,    bg_objectid             )
+               __field(        u64,    flags                   )
+               __field(        u64,    start                   )
+               __field(        u64,    len                     )
+       ),
+
+       TP_fast_assign(
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->bg_objectid    = block_group->key.objectid;
+               __entry->flags          = block_group->flags;
+               __entry->start          = start;
+               __entry->len            = len;
+       ),
+
+       TP_printk("root = %Lu(%s), block_group = %Lu, flags = %Lu(%s), "
+                 "start = %Lu, len = %Lu",
+                 show_root_type(__entry->root_objectid), __entry->bg_objectid,
+                 __entry->flags, __print_flags((unsigned long)__entry->flags,
+                                               "|", BTRFS_GROUP_FLAGS),
+                 __entry->start, __entry->len)
+);
+
+DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent,
+
+       TP_PROTO(struct btrfs_root *root,
+                struct btrfs_block_group_cache *block_group, u64 start,
+                u64 len),
+
+       TP_ARGS(root, block_group, start, len)
+);
+
+DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster,
+
+       TP_PROTO(struct btrfs_root *root,
+                struct btrfs_block_group_cache *block_group, u64 start,
+                u64 len),
+
+       TP_ARGS(root, block_group, start, len)
+);
+
+TRACE_EVENT(btrfs_find_cluster,
+
+       TP_PROTO(struct btrfs_block_group_cache *block_group, u64 start,
+                u64 bytes, u64 empty_size, u64 min_bytes),
+
+       TP_ARGS(block_group, start, bytes, empty_size, min_bytes),
+
+       TP_STRUCT__entry(
+               __field(        u64,    bg_objectid             )
+               __field(        u64,    flags                   )
+               __field(        u64,    start                   )
+               __field(        u64,    bytes                   )
+               __field(        u64,    empty_size              )
+               __field(        u64,    min_bytes               )
+       ),
+
+       TP_fast_assign(
+               __entry->bg_objectid    = block_group->key.objectid;
+               __entry->flags          = block_group->flags;
+               __entry->start          = start;
+               __entry->bytes          = bytes;
+               __entry->empty_size     = empty_size;
+               __entry->min_bytes      = min_bytes;
+       ),
+
+       TP_printk("block_group = %Lu, flags = %Lu(%s), start = %Lu, len = %Lu,"
+                 " empty_size = %Lu, min_bytes = %Lu", __entry->bg_objectid,
+                 __entry->flags,
+                 __print_flags((unsigned long)__entry->flags, "|",
+                               BTRFS_GROUP_FLAGS), __entry->start,
+                 __entry->bytes, __entry->empty_size,  __entry->min_bytes)
+);
+
+TRACE_EVENT(btrfs_failed_cluster_setup,
+
+       TP_PROTO(struct btrfs_block_group_cache *block_group),
+
+       TP_ARGS(block_group),
+
+       TP_STRUCT__entry(
+               __field(        u64,    bg_objectid             )
+       ),
+
+       TP_fast_assign(
+               __entry->bg_objectid    = block_group->key.objectid;
+       ),
+
+       TP_printk("block_group = %Lu", __entry->bg_objectid)
+);
+
+TRACE_EVENT(btrfs_setup_cluster,
+
+       TP_PROTO(struct btrfs_block_group_cache *block_group,
+                struct btrfs_free_cluster *cluster, u64 size, int bitmap),
+
+       TP_ARGS(block_group, cluster, size, bitmap),
+
+       TP_STRUCT__entry(
+               __field(        u64,    bg_objectid             )
+               __field(        u64,    flags                   )
+               __field(        u64,    start                   )
+               __field(        u64,    max_size                )
+               __field(        u64,    size                    )
+               __field(        int,    bitmap                  )
+       ),
+
+       TP_fast_assign(
+               __entry->bg_objectid    = block_group->key.objectid;
+               __entry->flags          = block_group->flags;
+               __entry->start          = cluster->window_start;
+               __entry->max_size       = cluster->max_size;
+               __entry->size           = size;
+               __entry->bitmap         = bitmap;
+       ),
+
+       TP_printk("block_group = %Lu, flags = %Lu(%s), window_start = %Lu, "
+                 "size = %Lu, max_size = %Lu, bitmap = %d",
+                 __entry->bg_objectid,
+                 __entry->flags,
+                 __print_flags((unsigned long)__entry->flags, "|",
+                               BTRFS_GROUP_FLAGS), __entry->start,
+                 __entry->size, __entry->max_size, __entry->bitmap)
+);
+
 #endif /* _TRACE_BTRFS_H */
 
 /* This part must be outside protection */
index 8588a891802339a2939dfc91e5630e3a826781d4..5973410e8f8cf34fd9fb1abaedb7325435716f9a 100644 (file)
@@ -47,7 +47,10 @@ DECLARE_EVENT_CLASS(writeback_work_class,
                __field(int, reason)
        ),
        TP_fast_assign(
-               strncpy(__entry->name, dev_name(bdi->dev), 32);
+               struct device *dev = bdi->dev;
+               if (!dev)
+                       dev = default_backing_dev_info.dev;
+               strncpy(__entry->name, dev_name(dev), 32);
                __entry->nr_pages = work->nr_pages;
                __entry->sb_dev = work->sb ? work->sb->s_dev : 0;
                __entry->sync_mode = work->sync_mode;
@@ -426,7 +429,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
 
        TP_fast_assign(
                strncpy(__entry->name,
-                       dev_name(inode->i_mapping->backing_dev_info->dev), 32);
+                       dev_name(inode_to_bdi(inode)->dev), 32);
                __entry->ino            = inode->i_ino;
                __entry->state          = inode->i_state;
                __entry->dirtied_when   = inode->dirtied_when;
index 062b3b24ff1071047f6c7fe26c80d19c112fe311..483f67caa7ad42b0b360e99a3df2c1502dc1dae1 100644 (file)
@@ -590,6 +590,11 @@ struct omap_dss_device {
        int (*get_backlight)(struct omap_dss_device *dssdev);
 };
 
+struct omap_dss_hdmi_data
+{
+       int hpd_gpio;
+};
+
 struct omap_dss_driver {
        struct device_driver driver;
 
index 6ac2236244c381f3bef900c600d1f9c1ba41c7f5..3f42cd66f0f87a25510dd000aed37de5c0d5cc71 100644 (file)
@@ -355,7 +355,7 @@ config AUDIT
 
 config AUDITSYSCALL
        bool "Enable system-call auditing support"
-       depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH)
+       depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || ARM)
        default y if SECURITY_SELINUX
        help
          Enable low-overhead system-call auditing infrastructure that
@@ -372,6 +372,20 @@ config AUDIT_TREE
        depends on AUDITSYSCALL
        select FSNOTIFY
 
+config AUDIT_LOGINUID_IMMUTABLE
+       bool "Make audit loginuid immutable"
+       depends on AUDIT
+       help
+         The config option toggles if a task setting its loginuid requires
+         CAP_SYS_AUDITCONTROL or if that task should require no special permissions
+         but should instead only allow setting its loginuid if it was never
+         previously set.  On systems which use systemd or a similar central
+         process to restart login services this should be set to true.  On older
+         systems in which an admin would typically have to directly stop and
+         start processes this should be set to false.  Setting this to true allows
+         one to drop potentially dangerous capabilites from the login tasks,
+         but may not be backwards compatible with older init systems.
+
 source "kernel/irq/Kconfig"
 
 menu "RCU Subsystem"
index 9b7c8ab7d75cad27e92272c0a0c81927c9fbaa03..86ee272de210bbae8236d45a4cebda3021afe2e9 100644 (file)
@@ -128,7 +128,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
 
        if (S_ISREG(mode)) {
                struct mqueue_inode_info *info;
-               struct task_struct *p = current;
                unsigned long mq_bytes, mq_msg_tblsz;
 
                inode->i_fop = &mqueue_file_operations;
@@ -159,7 +158,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
 
                spin_lock(&mq_lock);
                if (u->mq_bytes + mq_bytes < u->mq_bytes ||
-                   u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
+                   u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
                        spin_unlock(&mq_lock);
                        /* mqueue_evict_inode() releases info->messages */
                        ret = -EMFILE;
index 02ecf2c078fce9b62ee2b1ec0ef252c0320acdf5..b76be5bda6c2f10fd98019bea5730c24b7614e98 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -870,9 +870,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
        case SHM_LOCK:
        case SHM_UNLOCK:
        {
-               struct file *uninitialized_var(shm_file);
-
-               lru_add_drain_all();  /* drain pagevecs to lru lists */
+               struct file *shm_file;
 
                shp = shm_lock_check(ns, shmid);
                if (IS_ERR(shp)) {
@@ -895,22 +893,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
                err = security_shm_shmctl(shp, cmd);
                if (err)
                        goto out_unlock;
-               
-               if(cmd==SHM_LOCK) {
+
+               shm_file = shp->shm_file;
+               if (is_file_hugepages(shm_file))
+                       goto out_unlock;
+
+               if (cmd == SHM_LOCK) {
                        struct user_struct *user = current_user();
-                       if (!is_file_hugepages(shp->shm_file)) {
-                               err = shmem_lock(shp->shm_file, 1, user);
-                               if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
-                                       shp->shm_perm.mode |= SHM_LOCKED;
-                                       shp->mlock_user = user;
-                               }
+                       err = shmem_lock(shm_file, 1, user);
+                       if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
+                               shp->shm_perm.mode |= SHM_LOCKED;
+                               shp->mlock_user = user;
                        }
-               } else if (!is_file_hugepages(shp->shm_file)) {
-                       shmem_lock(shp->shm_file, 0, shp->mlock_user);
-                       shp->shm_perm.mode &= ~SHM_LOCKED;
-                       shp->mlock_user = NULL;
+                       goto out_unlock;
                }
+
+               /* SHM_UNLOCK */
+               if (!(shp->shm_perm.mode & SHM_LOCKED))
+                       goto out_unlock;
+               shmem_lock(shm_file, 0, shp->mlock_user);
+               shp->shm_perm.mode &= ~SHM_LOCKED;
+               shp->mlock_user = NULL;
+               get_file(shm_file);
                shm_unlock(shp);
+               shmem_unlock_mapping(shm_file->f_mapping);
+               fput(shm_file);
                goto out;
        }
        case IPC_RMID:
index 57e3f5107937f89951be2482040e294bee659bf5..bb0eb5bb9a0a8761286dfc29cd1aa5b8587e2801 100644 (file)
@@ -631,7 +631,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
        }
 
        *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
-       audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u",
+       audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
                         pid, uid, auid, ses);
        if (sid) {
                rc = security_secid_to_secctx(sid, &ctx, &len);
@@ -1423,7 +1423,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
        char *p, *pathname;
 
        if (prefix)
-               audit_log_format(ab, " %s", prefix);
+               audit_log_format(ab, "%s", prefix);
 
        /* We will allow 11 spaces for ' (deleted)' to be appended */
        pathname = kmalloc(PATH_MAX+11, ab->gfp_mask);
index 91e7071c4d2c4f06376e7ad5c485a2aa98294edd..81676680337158e20ce6077a522b64cdfa15f59f 100644 (file)
@@ -36,12 +36,8 @@ enum audit_state {
        AUDIT_DISABLED,         /* Do not create per-task audit_context.
                                 * No syscall-specific audit records can
                                 * be generated. */
-       AUDIT_SETUP_CONTEXT,    /* Create the per-task audit_context,
-                                * but don't necessarily fill it in at
-                                * syscall entry time (i.e., filter
-                                * instead). */
        AUDIT_BUILD_CONTEXT,    /* Create the per-task audit_context,
-                                * and always fill it in at syscall
+                                * and fill it in at syscall
                                 * entry time.  This makes a full
                                 * syscall record available if some
                                 * other part of the kernel decides it
index f8277c80d678bfeaefb74ad02805b0a4a2cebaa2..a6c3f1abd206c9d9736cbe5834483e36fd1d62ff 100644 (file)
@@ -235,13 +235,15 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
        switch(listnr) {
        default:
                goto exit_err;
-       case AUDIT_FILTER_USER:
-       case AUDIT_FILTER_TYPE:
 #ifdef CONFIG_AUDITSYSCALL
        case AUDIT_FILTER_ENTRY:
+               if (rule->action == AUDIT_ALWAYS)
+                       goto exit_err;
        case AUDIT_FILTER_EXIT:
        case AUDIT_FILTER_TASK:
 #endif
+       case AUDIT_FILTER_USER:
+       case AUDIT_FILTER_TYPE:
                ;
        }
        if (unlikely(rule->action == AUDIT_POSSIBLE)) {
@@ -385,7 +387,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                                goto exit_free;
                        break;
                case AUDIT_FILETYPE:
-                       if ((f->val & ~S_IFMT) > S_IFMT)
+                       if (f->val & ~S_IFMT)
                                goto exit_free;
                        break;
                case AUDIT_INODE:
@@ -459,6 +461,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_ARG1:
                case AUDIT_ARG2:
                case AUDIT_ARG3:
+               case AUDIT_OBJ_UID:
+               case AUDIT_OBJ_GID:
                        break;
                case AUDIT_ARCH:
                        entry->rule.arch_f = f;
@@ -522,7 +526,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                goto exit_free;
                        break;
                case AUDIT_FILTERKEY:
-                       err = -EINVAL;
                        if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
                                goto exit_free;
                        str = audit_unpack_string(&bufp, &remain, f->val);
@@ -536,7 +539,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                goto exit_free;
                        break;
                case AUDIT_FILETYPE:
-                       if ((f->val & ~S_IFMT) > S_IFMT)
+                       if (f->val & ~S_IFMT)
+                               goto exit_free;
+                       break;
+               case AUDIT_FIELD_COMPARE:
+                       if (f->val > AUDIT_MAX_FIELD_COMPARE)
                                goto exit_free;
                        break;
                default:
index e7fe2b0d29b3cd0676caccc6af116a76afee947e..af1de0f34eaed8dbf3dfb0057cd5c200da70b47a 100644 (file)
 
 #include "audit.h"
 
+/* flags stating the success for a syscall */
+#define AUDITSC_INVALID 0
+#define AUDITSC_SUCCESS 1
+#define AUDITSC_FAILURE 2
+
 /* AUDIT_NAMES is the number of slots we reserve in the audit_context
- * for saving names from getname(). */
-#define AUDIT_NAMES    20
+ * for saving names from getname().  If we get more names we will allocate
+ * a name dynamically and also add those to the list anchored by names_list. */
+#define AUDIT_NAMES    5
 
 /* Indicates that audit should log the full pathname. */
 #define AUDIT_NAME_FULL -1
@@ -101,9 +107,8 @@ struct audit_cap_data {
  *
  * Further, in fs/namei.c:path_lookup() we store the inode and device. */
 struct audit_names {
+       struct list_head list;          /* audit_context->names_list */
        const char      *name;
-       int             name_len;       /* number of name's characters to log */
-       unsigned        name_put;       /* call __putname() for this name */
        unsigned long   ino;
        dev_t           dev;
        umode_t         mode;
@@ -113,6 +118,14 @@ struct audit_names {
        u32             osid;
        struct audit_cap_data fcap;
        unsigned int    fcap_ver;
+       int             name_len;       /* number of name's characters to log */
+       bool            name_put;       /* call __putname() for this name */
+       /*
+        * This was an allocated audit_names and not from the array of
+        * names allocated in the task audit context.  Thus this name
+        * should be freed on syscall exit
+        */
+       bool            should_free;
 };
 
 struct audit_aux_data {
@@ -174,8 +187,17 @@ struct audit_context {
        long                return_code;/* syscall return code */
        u64                 prio;
        int                 return_valid; /* return code is valid */
-       int                 name_count;
-       struct audit_names  names[AUDIT_NAMES];
+       /*
+        * The names_list is the list of all audit_names collected during this
+        * syscall.  The first AUDIT_NAMES entries in the names_list will
+        * actually be from the preallocated_names array for performance
+        * reasons.  Except during allocation they should never be referenced
+        * through the preallocated_names array and should only be found/used
+        * by running the names_list.
+        */
+       struct audit_names  preallocated_names[AUDIT_NAMES];
+       int                 name_count; /* total records in names_list */
+       struct list_head    names_list; /* anchor for struct audit_names->list */
        char *              filterkey;  /* key for rule that triggered record */
        struct path         pwd;
        struct audit_context *previous; /* For nested syscalls */
@@ -305,21 +327,21 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
        }
 }
 
-static int audit_match_filetype(struct audit_context *ctx, int which)
+static int audit_match_filetype(struct audit_context *ctx, int val)
 {
-       unsigned index = which & ~S_IFMT;
-       umode_t mode = which & S_IFMT;
+       struct audit_names *n;
+       umode_t mode = (umode_t)val;
 
        if (unlikely(!ctx))
                return 0;
 
-       if (index >= ctx->name_count)
-               return 0;
-       if (ctx->names[index].ino == -1)
-               return 0;
-       if ((ctx->names[index].mode ^ mode) & S_IFMT)
-               return 0;
-       return 1;
+       list_for_each_entry(n, &ctx->names_list, list) {
+               if ((n->ino != -1) &&
+                   ((n->mode & S_IFMT) == mode))
+                       return 1;
+       }
+
+       return 0;
 }
 
 /*
@@ -441,6 +463,134 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
        return 0;
 }
 
+static int audit_compare_id(uid_t uid1,
+                           struct audit_names *name,
+                           unsigned long name_offset,
+                           struct audit_field *f,
+                           struct audit_context *ctx)
+{
+       struct audit_names *n;
+       unsigned long addr;
+       uid_t uid2;
+       int rc;
+
+       BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
+
+       if (name) {
+               addr = (unsigned long)name;
+               addr += name_offset;
+
+               uid2 = *(uid_t *)addr;
+               rc = audit_comparator(uid1, f->op, uid2);
+               if (rc)
+                       return rc;
+       }
+
+       if (ctx) {
+               list_for_each_entry(n, &ctx->names_list, list) {
+                       addr = (unsigned long)n;
+                       addr += name_offset;
+
+                       uid2 = *(uid_t *)addr;
+
+                       rc = audit_comparator(uid1, f->op, uid2);
+                       if (rc)
+                               return rc;
+               }
+       }
+       return 0;
+}
+
+static int audit_field_compare(struct task_struct *tsk,
+                              const struct cred *cred,
+                              struct audit_field *f,
+                              struct audit_context *ctx,
+                              struct audit_names *name)
+{
+       switch (f->val) {
+       /* process to file object comparisons */
+       case AUDIT_COMPARE_UID_TO_OBJ_UID:
+               return audit_compare_id(cred->uid,
+                                       name, offsetof(struct audit_names, uid),
+                                       f, ctx);
+       case AUDIT_COMPARE_GID_TO_OBJ_GID:
+               return audit_compare_id(cred->gid,
+                                       name, offsetof(struct audit_names, gid),
+                                       f, ctx);
+       case AUDIT_COMPARE_EUID_TO_OBJ_UID:
+               return audit_compare_id(cred->euid,
+                                       name, offsetof(struct audit_names, uid),
+                                       f, ctx);
+       case AUDIT_COMPARE_EGID_TO_OBJ_GID:
+               return audit_compare_id(cred->egid,
+                                       name, offsetof(struct audit_names, gid),
+                                       f, ctx);
+       case AUDIT_COMPARE_AUID_TO_OBJ_UID:
+               return audit_compare_id(tsk->loginuid,
+                                       name, offsetof(struct audit_names, uid),
+                                       f, ctx);
+       case AUDIT_COMPARE_SUID_TO_OBJ_UID:
+               return audit_compare_id(cred->suid,
+                                       name, offsetof(struct audit_names, uid),
+                                       f, ctx);
+       case AUDIT_COMPARE_SGID_TO_OBJ_GID:
+               return audit_compare_id(cred->sgid,
+                                       name, offsetof(struct audit_names, gid),
+                                       f, ctx);
+       case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
+               return audit_compare_id(cred->fsuid,
+                                       name, offsetof(struct audit_names, uid),
+                                       f, ctx);
+       case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
+               return audit_compare_id(cred->fsgid,
+                                       name, offsetof(struct audit_names, gid),
+                                       f, ctx);
+       /* uid comparisons */
+       case AUDIT_COMPARE_UID_TO_AUID:
+               return audit_comparator(cred->uid, f->op, tsk->loginuid);
+       case AUDIT_COMPARE_UID_TO_EUID:
+               return audit_comparator(cred->uid, f->op, cred->euid);
+       case AUDIT_COMPARE_UID_TO_SUID:
+               return audit_comparator(cred->uid, f->op, cred->suid);
+       case AUDIT_COMPARE_UID_TO_FSUID:
+               return audit_comparator(cred->uid, f->op, cred->fsuid);
+       /* auid comparisons */
+       case AUDIT_COMPARE_AUID_TO_EUID:
+               return audit_comparator(tsk->loginuid, f->op, cred->euid);
+       case AUDIT_COMPARE_AUID_TO_SUID:
+               return audit_comparator(tsk->loginuid, f->op, cred->suid);
+       case AUDIT_COMPARE_AUID_TO_FSUID:
+               return audit_comparator(tsk->loginuid, f->op, cred->fsuid);
+       /* euid comparisons */
+       case AUDIT_COMPARE_EUID_TO_SUID:
+               return audit_comparator(cred->euid, f->op, cred->suid);
+       case AUDIT_COMPARE_EUID_TO_FSUID:
+               return audit_comparator(cred->euid, f->op, cred->fsuid);
+       /* suid comparisons */
+       case AUDIT_COMPARE_SUID_TO_FSUID:
+               return audit_comparator(cred->suid, f->op, cred->fsuid);
+       /* gid comparisons */
+       case AUDIT_COMPARE_GID_TO_EGID:
+               return audit_comparator(cred->gid, f->op, cred->egid);
+       case AUDIT_COMPARE_GID_TO_SGID:
+               return audit_comparator(cred->gid, f->op, cred->sgid);
+       case AUDIT_COMPARE_GID_TO_FSGID:
+               return audit_comparator(cred->gid, f->op, cred->fsgid);
+       /* egid comparisons */
+       case AUDIT_COMPARE_EGID_TO_SGID:
+               return audit_comparator(cred->egid, f->op, cred->sgid);
+       case AUDIT_COMPARE_EGID_TO_FSGID:
+               return audit_comparator(cred->egid, f->op, cred->fsgid);
+       /* sgid comparison */
+       case AUDIT_COMPARE_SGID_TO_FSGID:
+               return audit_comparator(cred->sgid, f->op, cred->fsgid);
+       default:
+               WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
+               return 0;
+       }
+       return 0;
+}
+
 /* Determine if any context name data matches a rule's watch data */
 /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
  * otherwise.
@@ -457,13 +607,14 @@ static int audit_filter_rules(struct task_struct *tsk,
                              bool task_creation)
 {
        const struct cred *cred;
-       int i, j, need_sid = 1;
+       int i, need_sid = 1;
        u32 sid;
 
        cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);
 
        for (i = 0; i < rule->field_count; i++) {
                struct audit_field *f = &rule->fields[i];
+               struct audit_names *n;
                int result = 0;
 
                switch (f->type) {
@@ -522,12 +673,14 @@ static int audit_filter_rules(struct task_struct *tsk,
                        }
                        break;
                case AUDIT_DEVMAJOR:
-                       if (name)
-                               result = audit_comparator(MAJOR(name->dev),
-                                                         f->op, f->val);
-                       else if (ctx) {
-                               for (j = 0; j < ctx->name_count; j++) {
-                                       if (audit_comparator(MAJOR(ctx->names[j].dev),  f->op, f->val)) {
+                       if (name) {
+                               if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
+                                   audit_comparator(MAJOR(name->rdev), f->op, f->val))
+                                       ++result;
+                       } else if (ctx) {
+                               list_for_each_entry(n, &ctx->names_list, list) {
+                                       if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
+                                           audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
                                                ++result;
                                                break;
                                        }
@@ -535,12 +688,14 @@ static int audit_filter_rules(struct task_struct *tsk,
                        }
                        break;
                case AUDIT_DEVMINOR:
-                       if (name)
-                               result = audit_comparator(MINOR(name->dev),
-                                                         f->op, f->val);
-                       else if (ctx) {
-                               for (j = 0; j < ctx->name_count; j++) {
-                                       if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
+                       if (name) {
+                               if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
+                                   audit_comparator(MINOR(name->rdev), f->op, f->val))
+                                       ++result;
+                       } else if (ctx) {
+                               list_for_each_entry(n, &ctx->names_list, list) {
+                                       if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
+                                           audit_comparator(MINOR(n->rdev), f->op, f->val)) {
                                                ++result;
                                                break;
                                        }
@@ -551,8 +706,32 @@ static int audit_filter_rules(struct task_struct *tsk,
                        if (name)
                                result = (name->ino == f->val);
                        else if (ctx) {
-                               for (j = 0; j < ctx->name_count; j++) {
-                                       if (audit_comparator(ctx->names[j].ino, f->op, f->val)) {
+                               list_for_each_entry(n, &ctx->names_list, list) {
+                                       if (audit_comparator(n->ino, f->op, f->val)) {
+                                               ++result;
+                                               break;
+                                       }
+                               }
+                       }
+                       break;
+               case AUDIT_OBJ_UID:
+                       if (name) {
+                               result = audit_comparator(name->uid, f->op, f->val);
+                       } else if (ctx) {
+                               list_for_each_entry(n, &ctx->names_list, list) {
+                                       if (audit_comparator(n->uid, f->op, f->val)) {
+                                               ++result;
+                                               break;
+                                       }
+                               }
+                       }
+                       break;
+               case AUDIT_OBJ_GID:
+                       if (name) {
+                               result = audit_comparator(name->gid, f->op, f->val);
+                       } else if (ctx) {
+                               list_for_each_entry(n, &ctx->names_list, list) {
+                                       if (audit_comparator(n->gid, f->op, f->val)) {
                                                ++result;
                                                break;
                                        }
@@ -607,11 +786,10 @@ static int audit_filter_rules(struct task_struct *tsk,
                                                   name->osid, f->type, f->op,
                                                   f->lsm_rule, ctx);
                                } else if (ctx) {
-                                       for (j = 0; j < ctx->name_count; j++) {
-                                               if (security_audit_rule_match(
-                                                     ctx->names[j].osid,
-                                                     f->type, f->op,
-                                                     f->lsm_rule, ctx)) {
+                                       list_for_each_entry(n, &ctx->names_list, list) {
+                                               if (security_audit_rule_match(n->osid, f->type,
+                                                                             f->op, f->lsm_rule,
+                                                                             ctx)) {
                                                        ++result;
                                                        break;
                                                }
@@ -643,8 +821,10 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_FILETYPE:
                        result = audit_match_filetype(ctx, f->val);
                        break;
+               case AUDIT_FIELD_COMPARE:
+                       result = audit_field_compare(tsk, cred, f, ctx, name);
+                       break;
                }
-
                if (!result)
                        return 0;
        }
@@ -722,40 +902,53 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
        return AUDIT_BUILD_CONTEXT;
 }
 
-/* At syscall exit time, this filter is called if any audit_names[] have been
+/*
+ * Given an audit_name check the inode hash table to see if they match.
+ * Called holding the rcu read lock to protect the use of audit_inode_hash
+ */
+static int audit_filter_inode_name(struct task_struct *tsk,
+                                  struct audit_names *n,
+                                  struct audit_context *ctx) {
+       int word, bit;
+       int h = audit_hash_ino((u32)n->ino);
+       struct list_head *list = &audit_inode_hash[h];
+       struct audit_entry *e;
+       enum audit_state state;
+
+       word = AUDIT_WORD(ctx->major);
+       bit  = AUDIT_BIT(ctx->major);
+
+       if (list_empty(list))
+               return 0;
+
+       list_for_each_entry_rcu(e, list, list) {
+               if ((e->rule.mask[word] & bit) == bit &&
+                   audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
+                       ctx->current_state = state;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* At syscall exit time, this filter is called if any audit_names have been
  * collected during syscall processing.  We only check rules in sublists at hash
- * buckets applicable to the inode numbers in audit_names[].
+ * buckets applicable to the inode numbers in audit_names.
  * Regarding audit_state, same rules apply as for audit_filter_syscall().
  */
 void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
 {
-       int i;
-       struct audit_entry *e;
-       enum audit_state state;
+       struct audit_names *n;
 
        if (audit_pid && tsk->tgid == audit_pid)
                return;
 
        rcu_read_lock();
-       for (i = 0; i < ctx->name_count; i++) {
-               int word = AUDIT_WORD(ctx->major);
-               int bit  = AUDIT_BIT(ctx->major);
-               struct audit_names *n = &ctx->names[i];
-               int h = audit_hash_ino((u32)n->ino);
-               struct list_head *list = &audit_inode_hash[h];
-
-               if (list_empty(list))
-                       continue;
 
-               list_for_each_entry_rcu(e, list, list) {
-                       if ((e->rule.mask[word] & bit) == bit &&
-                           audit_filter_rules(tsk, &e->rule, ctx, n,
-                                              &state, false)) {
-                               rcu_read_unlock();
-                               ctx->current_state = state;
-                               return;
-                       }
-               }
+       list_for_each_entry(n, &ctx->names_list, list) {
+               if (audit_filter_inode_name(tsk, n, ctx))
+                       break;
        }
        rcu_read_unlock();
 }
@@ -766,7 +959,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
 {
        struct audit_context *context = tsk->audit_context;
 
-       if (likely(!context))
+       if (!context)
                return NULL;
        context->return_valid = return_valid;
 
@@ -799,7 +992,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
 
 static inline void audit_free_names(struct audit_context *context)
 {
-       int i;
+       struct audit_names *n, *next;
 
 #if AUDIT_DEBUG == 2
        if (context->put_count + context->ino_count != context->name_count) {
@@ -810,10 +1003,9 @@ static inline void audit_free_names(struct audit_context *context)
                       context->serial, context->major, context->in_syscall,
                       context->name_count, context->put_count,
                       context->ino_count);
-               for (i = 0; i < context->name_count; i++) {
+               list_for_each_entry(n, &context->names_list, list) {
                        printk(KERN_ERR "names[%d] = %p = %s\n", i,
-                              context->names[i].name,
-                              context->names[i].name ?: "(null)");
+                              n->name, n->name ?: "(null)");
                }
                dump_stack();
                return;
@@ -824,9 +1016,12 @@ static inline void audit_free_names(struct audit_context *context)
        context->ino_count  = 0;
 #endif
 
-       for (i = 0; i < context->name_count; i++) {
-               if (context->names[i].name && context->names[i].name_put)
-                       __putname(context->names[i].name);
+       list_for_each_entry_safe(n, next, &context->names_list, list) {
+               list_del(&n->list);
+               if (n->name && n->name_put)
+                       __putname(n->name);
+               if (n->should_free)
+                       kfree(n);
        }
        context->name_count = 0;
        path_put(&context->pwd);
@@ -864,6 +1059,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
                return NULL;
        audit_zero_context(context, state);
        INIT_LIST_HEAD(&context->killed_trees);
+       INIT_LIST_HEAD(&context->names_list);
        return context;
 }
 
@@ -886,7 +1082,7 @@ int audit_alloc(struct task_struct *tsk)
                return 0; /* Return if not auditing. */
 
        state = audit_filter_task(tsk, &key);
-       if (likely(state == AUDIT_DISABLED))
+       if (state == AUDIT_DISABLED)
                return 0;
 
        if (!(context = audit_alloc_context(state))) {
@@ -975,7 +1171,7 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
                while (vma) {
                        if ((vma->vm_flags & VM_EXECUTABLE) &&
                            vma->vm_file) {
-                               audit_log_d_path(ab, "exe=",
+                               audit_log_d_path(ab, " exe=",
                                                 &vma->vm_file->f_path);
                                break;
                        }
@@ -1166,8 +1362,8 @@ static void audit_log_execve_info(struct audit_context *context,
                                  struct audit_buffer **ab,
                                  struct audit_aux_data_execve *axi)
 {
-       int i;
-       size_t len, len_sent = 0;
+       int i, len;
+       size_t len_sent = 0;
        const char __user *p;
        char *buf;
 
@@ -1324,6 +1520,68 @@ static void show_special(struct audit_context *context, int *call_panic)
        audit_log_end(ab);
 }
 
+static void audit_log_name(struct audit_context *context, struct audit_names *n,
+                          int record_num, int *call_panic)
+{
+       struct audit_buffer *ab;
+       ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
+       if (!ab)
+               return; /* audit_panic has been called */
+
+       audit_log_format(ab, "item=%d", record_num);
+
+       if (n->name) {
+               switch (n->name_len) {
+               case AUDIT_NAME_FULL:
+                       /* log the full path */
+                       audit_log_format(ab, " name=");
+                       audit_log_untrustedstring(ab, n->name);
+                       break;
+               case 0:
+                       /* name was specified as a relative path and the
+                        * directory component is the cwd */
+                       audit_log_d_path(ab, " name=", &context->pwd);
+                       break;
+               default:
+                       /* log the name's directory component */
+                       audit_log_format(ab, " name=");
+                       audit_log_n_untrustedstring(ab, n->name,
+                                                   n->name_len);
+               }
+       } else
+               audit_log_format(ab, " name=(null)");
+
+       if (n->ino != (unsigned long)-1) {
+               audit_log_format(ab, " inode=%lu"
+                                " dev=%02x:%02x mode=%#ho"
+                                " ouid=%u ogid=%u rdev=%02x:%02x",
+                                n->ino,
+                                MAJOR(n->dev),
+                                MINOR(n->dev),
+                                n->mode,
+                                n->uid,
+                                n->gid,
+                                MAJOR(n->rdev),
+                                MINOR(n->rdev));
+       }
+       if (n->osid != 0) {
+               char *ctx = NULL;
+               u32 len;
+               if (security_secid_to_secctx(
+                       n->osid, &ctx, &len)) {
+                       audit_log_format(ab, " osid=%u", n->osid);
+                       *call_panic = 2;
+               } else {
+                       audit_log_format(ab, " obj=%s", ctx);
+                       security_release_secctx(ctx, len);
+               }
+       }
+
+       audit_log_fcaps(ab, n);
+
+       audit_log_end(ab);
+}
+
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
        const struct cred *cred;
@@ -1331,6 +1589,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
        struct audit_buffer *ab;
        struct audit_aux_data *aux;
        const char *tty;
+       struct audit_names *n;
 
        /* tsk == current */
        context->pid = tsk->pid;
@@ -1466,70 +1725,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
        if (context->pwd.dentry && context->pwd.mnt) {
                ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
                if (ab) {
-                       audit_log_d_path(ab, "cwd=", &context->pwd);
+                       audit_log_d_path(ab, " cwd=", &context->pwd);
                        audit_log_end(ab);
                }
        }
-       for (i = 0; i < context->name_count; i++) {
-               struct audit_names *n = &context->names[i];
 
-               ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
-               if (!ab)
-                       continue; /* audit_panic has been called */
-
-               audit_log_format(ab, "item=%d", i);
-
-               if (n->name) {
-                       switch(n->name_len) {
-                       case AUDIT_NAME_FULL:
-                               /* log the full path */
-                               audit_log_format(ab, " name=");
-                               audit_log_untrustedstring(ab, n->name);
-                               break;
-                       case 0:
-                               /* name was specified as a relative path and the
-                                * directory component is the cwd */
-                               audit_log_d_path(ab, "name=", &context->pwd);
-                               break;
-                       default:
-                               /* log the name's directory component */
-                               audit_log_format(ab, " name=");
-                               audit_log_n_untrustedstring(ab, n->name,
-                                                           n->name_len);
-                       }
-               } else
-                       audit_log_format(ab, " name=(null)");
-
-               if (n->ino != (unsigned long)-1) {
-                       audit_log_format(ab, " inode=%lu"
-                                        " dev=%02x:%02x mode=%#ho"
-                                        " ouid=%u ogid=%u rdev=%02x:%02x",
-                                        n->ino,
-                                        MAJOR(n->dev),
-                                        MINOR(n->dev),
-                                        n->mode,
-                                        n->uid,
-                                        n->gid,
-                                        MAJOR(n->rdev),
-                                        MINOR(n->rdev));
-               }
-               if (n->osid != 0) {
-                       char *ctx = NULL;
-                       u32 len;
-                       if (security_secid_to_secctx(
-                               n->osid, &ctx, &len)) {
-                               audit_log_format(ab, " osid=%u", n->osid);
-                               call_panic = 2;
-                       } else {
-                               audit_log_format(ab, " obj=%s", ctx);
-                               security_release_secctx(ctx, len);
-                       }
-               }
-
-               audit_log_fcaps(ab, n);
-
-               audit_log_end(ab);
-       }
+       i = 0;
+       list_for_each_entry(n, &context->names_list, list)
+               audit_log_name(context, n, i++, &call_panic);
 
        /* Send end of event record to help user space know we are finished */
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
@@ -1545,12 +1748,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
  *
  * Called from copy_process and do_exit
  */
-void audit_free(struct task_struct *tsk)
+void __audit_free(struct task_struct *tsk)
 {
        struct audit_context *context;
 
        context = audit_get_context(tsk, 0, 0);
-       if (likely(!context))
+       if (!context)
                return;
 
        /* Check for system calls that do not go through the exit
@@ -1583,7 +1786,7 @@ void audit_free(struct task_struct *tsk)
  * will only be written if another part of the kernel requests that it
  * be written).
  */
-void audit_syscall_entry(int arch, int major,
+void __audit_syscall_entry(int arch, int major,
                         unsigned long a1, unsigned long a2,
                         unsigned long a3, unsigned long a4)
 {
@@ -1591,7 +1794,7 @@ void audit_syscall_entry(int arch, int major,
        struct audit_context *context = tsk->audit_context;
        enum audit_state     state;
 
-       if (unlikely(!context))
+       if (!context)
                return;
 
        /*
@@ -1648,7 +1851,7 @@ void audit_syscall_entry(int arch, int major,
                context->prio = 0;
                state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
        }
-       if (likely(state == AUDIT_DISABLED))
+       if (state == AUDIT_DISABLED)
                return;
 
        context->serial     = 0;
@@ -1658,45 +1861,29 @@ void audit_syscall_entry(int arch, int major,
        context->ppid       = 0;
 }
 
-void audit_finish_fork(struct task_struct *child)
-{
-       struct audit_context *ctx = current->audit_context;
-       struct audit_context *p = child->audit_context;
-       if (!p || !ctx)
-               return;
-       if (!ctx->in_syscall || ctx->current_state != AUDIT_RECORD_CONTEXT)
-               return;
-       p->arch = ctx->arch;
-       p->major = ctx->major;
-       memcpy(p->argv, ctx->argv, sizeof(ctx->argv));
-       p->ctime = ctx->ctime;
-       p->dummy = ctx->dummy;
-       p->in_syscall = ctx->in_syscall;
-       p->filterkey = kstrdup(ctx->filterkey, GFP_KERNEL);
-       p->ppid = current->pid;
-       p->prio = ctx->prio;
-       p->current_state = ctx->current_state;
-}
-
 /**
  * audit_syscall_exit - deallocate audit context after a system call
- * @valid: success/failure flag
- * @return_code: syscall return value
+ * @success: success value of the syscall
+ * @return_code: return value of the syscall
  *
  * Tear down after system call.  If the audit context has been marked as
  * auditable (either because of the AUDIT_RECORD_CONTEXT state from
- * filtering, or because some other part of the kernel write an audit
+ * filtering, or because some other part of the kernel wrote an audit
  * message), then write out the syscall information.  In call cases,
  * free the names stored from getname().
  */
-void audit_syscall_exit(int valid, long return_code)
+void __audit_syscall_exit(int success, long return_code)
 {
        struct task_struct *tsk = current;
        struct audit_context *context;
 
-       context = audit_get_context(tsk, valid, return_code);
+       if (success)
+               success = AUDITSC_SUCCESS;
+       else
+               success = AUDITSC_FAILURE;
 
-       if (likely(!context))
+       context = audit_get_context(tsk, success, return_code);
+       if (!context)
                return;
 
        if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
@@ -1821,6 +2008,30 @@ retry:
 #endif
 }
 
+static struct audit_names *audit_alloc_name(struct audit_context *context)
+{
+       struct audit_names *aname;
+
+       if (context->name_count < AUDIT_NAMES) {
+               aname = &context->preallocated_names[context->name_count];
+               memset(aname, 0, sizeof(*aname));
+       } else {
+               aname = kzalloc(sizeof(*aname), GFP_NOFS);
+               if (!aname)
+                       return NULL;
+               aname->should_free = true;
+       }
+
+       aname->ino = (unsigned long)-1;
+       list_add_tail(&aname->list, &context->names_list);
+
+       context->name_count++;
+#if AUDIT_DEBUG
+       context->ino_count++;
+#endif
+       return aname;
+}
+
 /**
  * audit_getname - add a name to the list
  * @name: name to add
@@ -1831,9 +2042,7 @@ retry:
 void __audit_getname(const char *name)
 {
        struct audit_context *context = current->audit_context;
-
-       if (IS_ERR(name) || !name)
-               return;
+       struct audit_names *n;
 
        if (!context->in_syscall) {
 #if AUDIT_DEBUG == 2
@@ -1843,13 +2052,15 @@ void __audit_getname(const char *name)
 #endif
                return;
        }
-       BUG_ON(context->name_count >= AUDIT_NAMES);
-       context->names[context->name_count].name = name;
-       context->names[context->name_count].name_len = AUDIT_NAME_FULL;
-       context->names[context->name_count].name_put = 1;
-       context->names[context->name_count].ino  = (unsigned long)-1;
-       context->names[context->name_count].osid = 0;
-       ++context->name_count;
+
+       n = audit_alloc_name(context);
+       if (!n)
+               return;
+
+       n->name = name;
+       n->name_len = AUDIT_NAME_FULL;
+       n->name_put = true;
+
        if (!context->pwd.dentry)
                get_fs_pwd(current->fs, &context->pwd);
 }
@@ -1871,12 +2082,13 @@ void audit_putname(const char *name)
                printk(KERN_ERR "%s:%d(:%d): __putname(%p)\n",
                       __FILE__, __LINE__, context->serial, name);
                if (context->name_count) {
+                       struct audit_names *n;
                        int i;
-                       for (i = 0; i < context->name_count; i++)
+
+                       list_for_each_entry(n, &context->names_list, list)
                                printk(KERN_ERR "name[%d] = %p = %s\n", i,
-                                      context->names[i].name,
-                                      context->names[i].name ?: "(null)");
-               }
+                                      n->name, n->name ?: "(null)");
+                       }
 #endif
                __putname(name);
        }
@@ -1897,39 +2109,11 @@ void audit_putname(const char *name)
 #endif
 }
 
-static int audit_inc_name_count(struct audit_context *context,
-                               const struct inode *inode)
-{
-       if (context->name_count >= AUDIT_NAMES) {
-               if (inode)
-                       printk(KERN_DEBUG "audit: name_count maxed, losing inode data: "
-                              "dev=%02x:%02x, inode=%lu\n",
-                              MAJOR(inode->i_sb->s_dev),
-                              MINOR(inode->i_sb->s_dev),
-                              inode->i_ino);
-
-               else
-                       printk(KERN_DEBUG "name_count maxed, losing inode data\n");
-               return 1;
-       }
-       context->name_count++;
-#if AUDIT_DEBUG
-       context->ino_count++;
-#endif
-       return 0;
-}
-
-
 static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry)
 {
        struct cpu_vfs_cap_data caps;
        int rc;
 
-       memset(&name->fcap.permitted, 0, sizeof(kernel_cap_t));
-       memset(&name->fcap.inheritable, 0, sizeof(kernel_cap_t));
-       name->fcap.fE = 0;
-       name->fcap_ver = 0;
-
        if (!dentry)
                return 0;
 
@@ -1969,30 +2153,25 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent
  */
 void __audit_inode(const char *name, const struct dentry *dentry)
 {
-       int idx;
        struct audit_context *context = current->audit_context;
        const struct inode *inode = dentry->d_inode;
+       struct audit_names *n;
 
        if (!context->in_syscall)
                return;
-       if (context->name_count
-           && context->names[context->name_count-1].name
-           && context->names[context->name_count-1].name == name)
-               idx = context->name_count - 1;
-       else if (context->name_count > 1
-                && context->names[context->name_count-2].name
-                && context->names[context->name_count-2].name == name)
-               idx = context->name_count - 2;
-       else {
-               /* FIXME: how much do we care about inodes that have no
-                * associated name? */
-               if (audit_inc_name_count(context, inode))
-                       return;
-               idx = context->name_count - 1;
-               context->names[idx].name = NULL;
+
+       list_for_each_entry_reverse(n, &context->names_list, list) {
+               if (n->name && (n->name == name))
+                       goto out;
        }
+
+       /* unable to find the name from a previous getname() */
+       n = audit_alloc_name(context);
+       if (!n)
+               return;
+out:
        handle_path(dentry);
-       audit_copy_inode(&context->names[idx], dentry, inode);
+       audit_copy_inode(n, dentry, inode);
 }
 
 /**
@@ -2011,11 +2190,11 @@ void __audit_inode(const char *name, const struct dentry *dentry)
 void __audit_inode_child(const struct dentry *dentry,
                         const struct inode *parent)
 {
-       int idx;
        struct audit_context *context = current->audit_context;
        const char *found_parent = NULL, *found_child = NULL;
        const struct inode *inode = dentry->d_inode;
        const char *dname = dentry->d_name.name;
+       struct audit_names *n;
        int dirlen = 0;
 
        if (!context->in_syscall)
@@ -2025,9 +2204,7 @@ void __audit_inode_child(const struct dentry *dentry,
                handle_one(inode);
 
        /* parent is more likely, look for it first */
-       for (idx = 0; idx < context->name_count; idx++) {
-               struct audit_names *n = &context->names[idx];
-
+       list_for_each_entry(n, &context->names_list, list) {
                if (!n->name)
                        continue;
 
@@ -2040,9 +2217,7 @@ void __audit_inode_child(const struct dentry *dentry,
        }
 
        /* no matching parent, look for matching child */
-       for (idx = 0; idx < context->name_count; idx++) {
-               struct audit_names *n = &context->names[idx];
-
+       list_for_each_entry(n, &context->names_list, list) {
                if (!n->name)
                        continue;
 
@@ -2060,34 +2235,29 @@ void __audit_inode_child(const struct dentry *dentry,
 
 add_names:
        if (!found_parent) {
-               if (audit_inc_name_count(context, parent))
+               n = audit_alloc_name(context);
+               if (!n)
                        return;
-               idx = context->name_count - 1;
-               context->names[idx].name = NULL;
-               audit_copy_inode(&context->names[idx], NULL, parent);
+               audit_copy_inode(n, NULL, parent);
        }
 
        if (!found_child) {
-               if (audit_inc_name_count(context, inode))
+               n = audit_alloc_name(context);
+               if (!n)
                        return;
-               idx = context->name_count - 1;
 
                /* Re-use the name belonging to the slot for a matching parent
                 * directory. All names for this context are relinquished in
                 * audit_free_names() */
                if (found_parent) {
-                       context->names[idx].name = found_parent;
-                       context->names[idx].name_len = AUDIT_NAME_FULL;
+                       n->name = found_parent;
+                       n->name_len = AUDIT_NAME_FULL;
                        /* don't call __putname() */
-                       context->names[idx].name_put = 0;
-               } else {
-                       context->names[idx].name = NULL;
+                       n->name_put = false;
                }
 
                if (inode)
-                       audit_copy_inode(&context->names[idx], NULL, inode);
-               else
-                       context->names[idx].ino = (unsigned long)-1;
+                       audit_copy_inode(n, NULL, inode);
        }
 }
 EXPORT_SYMBOL_GPL(__audit_inode_child);
@@ -2121,19 +2291,28 @@ int auditsc_get_stamp(struct audit_context *ctx,
 static atomic_t session_id = ATOMIC_INIT(0);
 
 /**
- * audit_set_loginuid - set a task's audit_context loginuid
- * @task: task whose audit context is being modified
+ * audit_set_loginuid - set current task's audit_context loginuid
  * @loginuid: loginuid value
  *
  * Returns 0.
  *
  * Called (set) from fs/proc/base.c::proc_loginuid_write().
  */
-int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
+int audit_set_loginuid(uid_t loginuid)
 {
-       unsigned int sessionid = atomic_inc_return(&session_id);
+       struct task_struct *task = current;
        struct audit_context *context = task->audit_context;
+       unsigned int sessionid;
+
+#ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE
+       if (task->loginuid != -1)
+               return -EPERM;
+#else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */
+       if (!capable(CAP_AUDIT_CONTROL))
+               return -EPERM;
+#endif  /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */
 
+       sessionid = atomic_inc_return(&session_id);
        if (context && context->in_syscall) {
                struct audit_buffer *ab;
 
@@ -2271,14 +2450,11 @@ void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mo
        context->ipc.has_perm = 1;
 }
 
-int audit_bprm(struct linux_binprm *bprm)
+int __audit_bprm(struct linux_binprm *bprm)
 {
        struct audit_aux_data_execve *ax;
        struct audit_context *context = current->audit_context;
 
-       if (likely(!audit_enabled || !context || context->dummy))
-               return 0;
-
        ax = kmalloc(sizeof(*ax), GFP_KERNEL);
        if (!ax)
                return -ENOMEM;
@@ -2299,13 +2475,10 @@ int audit_bprm(struct linux_binprm *bprm)
  * @args: args array
  *
  */
-void audit_socketcall(int nargs, unsigned long *args)
+void __audit_socketcall(int nargs, unsigned long *args)
 {
        struct audit_context *context = current->audit_context;
 
-       if (likely(!context || context->dummy))
-               return;
-
        context->type = AUDIT_SOCKETCALL;
        context->socketcall.nargs = nargs;
        memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
@@ -2331,13 +2504,10 @@ void __audit_fd_pair(int fd1, int fd2)
  *
  * Returns 0 for success or NULL context or < 0 on error.
  */
-int audit_sockaddr(int len, void *a)
+int __audit_sockaddr(int len, void *a)
 {
        struct audit_context *context = current->audit_context;
 
-       if (likely(!context || context->dummy))
-               return 0;
-
        if (!context->sockaddr) {
                void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
                if (!p)
@@ -2499,6 +2669,25 @@ void __audit_mmap_fd(int fd, int flags)
        context->type = AUDIT_MMAP;
 }
 
+static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+{
+       uid_t auid, uid;
+       gid_t gid;
+       unsigned int sessionid;
+
+       auid = audit_get_loginuid(current);
+       sessionid = audit_get_sessionid(current);
+       current_uid_gid(&uid, &gid);
+
+       audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
+                        auid, uid, gid, sessionid);
+       audit_log_task_context(ab);
+       audit_log_format(ab, " pid=%d comm=", current->pid);
+       audit_log_untrustedstring(ab, current->comm);
+       audit_log_format(ab, " reason=");
+       audit_log_string(ab, reason);
+       audit_log_format(ab, " sig=%ld", signr);
+}
 /**
  * audit_core_dumps - record information about processes that end abnormally
  * @signr: signal value
@@ -2509,10 +2698,6 @@ void __audit_mmap_fd(int fd, int flags)
 void audit_core_dumps(long signr)
 {
        struct audit_buffer *ab;
-       u32 sid;
-       uid_t auid = audit_get_loginuid(current), uid;
-       gid_t gid;
-       unsigned int sessionid = audit_get_sessionid(current);
 
        if (!audit_enabled)
                return;
@@ -2521,24 +2706,17 @@ void audit_core_dumps(long signr)
                return;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
-       current_uid_gid(&uid, &gid);
-       audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
-                        auid, uid, gid, sessionid);
-       security_task_getsecid(current, &sid);
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
+       audit_log_abend(ab, "memory violation", signr);
+       audit_log_end(ab);
+}
 
-               if (security_secid_to_secctx(sid, &ctx, &len))
-                       audit_log_format(ab, " ssid=%u", sid);
-               else {
-                       audit_log_format(ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
-       audit_log_format(ab, " pid=%d comm=", current->pid);
-       audit_log_untrustedstring(ab, current->comm);
-       audit_log_format(ab, " sig=%ld", signr);
+void __audit_seccomp(unsigned long syscall)
+{
+       struct audit_buffer *ab;
+
+       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+       audit_log_abend(ab, "seccomp", SIGKILL);
+       audit_log_format(ab, " syscall=%ld", syscall);
        audit_log_end(ab);
 }
 
index 0fcf1c14a297c57d7cda541b71438441dd1adbde..3f1adb6c647015d80aa6b5b138f118fde7484d11 100644 (file)
@@ -384,7 +384,7 @@ bool ns_capable(struct user_namespace *ns, int cap)
                BUG();
        }
 
-       if (has_ns_capability(current, ns, cap)) {
+       if (security_capable(current_cred(), ns, cap) == 0) {
                current->flags |= PF_SUPERPRIV;
                return true;
        }
index 057e24b665cf7f5633bc43b752202af38c14d413..6581a040f39926dd46878640413bfd180922415a 100644 (file)
@@ -115,8 +115,6 @@ int get_callchain_buffers(void)
        }
 
        err = alloc_callchain_buffers();
-       if (err)
-               release_callchain_buffers();
 exit:
        mutex_unlock(&callchain_mutex);
 
index a8f4ac001a00796da1621b8363cc9bdc9bd2d474..1b5c081d8b9f9c8ea05f1a8ecaf861f80ab7ba1c 100644 (file)
@@ -815,7 +815,7 @@ static void update_event_times(struct perf_event *event)
         * here.
         */
        if (is_cgroup_event(event))
-               run_end = perf_event_time(event);
+               run_end = perf_cgroup_event_time(event);
        else if (ctx->is_active)
                run_end = ctx->time;
        else
@@ -2300,7 +2300,10 @@ do {                                     \
        return div64_u64(dividend, divisor);
 }
 
-static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
+static DEFINE_PER_CPU(int, perf_throttled_count);
+static DEFINE_PER_CPU(u64, perf_throttled_seq);
+
+static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bool disable)
 {
        struct hw_perf_event *hwc = &event->hw;
        s64 period, sample_period;
@@ -2319,22 +2322,40 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
        hwc->sample_period = sample_period;
 
        if (local64_read(&hwc->period_left) > 8*sample_period) {
-               event->pmu->stop(event, PERF_EF_UPDATE);
+               if (disable)
+                       event->pmu->stop(event, PERF_EF_UPDATE);
+
                local64_set(&hwc->period_left, 0);
-               event->pmu->start(event, PERF_EF_RELOAD);
+
+               if (disable)
+                       event->pmu->start(event, PERF_EF_RELOAD);
        }
 }
 
-static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
+/*
+ * combine freq adjustment with unthrottling to avoid two passes over the
+ * events. At the same time, make sure, having freq events does not change
+ * the rate of unthrottling as that would introduce bias.
+ */
+static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
+                                          int needs_unthr)
 {
        struct perf_event *event;
        struct hw_perf_event *hwc;
-       u64 interrupts, now;
+       u64 now, period = TICK_NSEC;
        s64 delta;
 
-       if (!ctx->nr_freq)
+       /*
+        * only need to iterate over all events iff:
+        * - context have events in frequency mode (needs freq adjust)
+        * - there are events to unthrottle on this cpu
+        */
+       if (!(ctx->nr_freq || needs_unthr))
                return;
 
+       raw_spin_lock(&ctx->lock);
+       perf_pmu_disable(ctx->pmu);
+
        list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
                if (event->state != PERF_EVENT_STATE_ACTIVE)
                        continue;
@@ -2344,13 +2365,8 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
 
                hwc = &event->hw;
 
-               interrupts = hwc->interrupts;
-               hwc->interrupts = 0;
-
-               /*
-                * unthrottle events on the tick
-                */
-               if (interrupts == MAX_INTERRUPTS) {
+               if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) {
+                       hwc->interrupts = 0;
                        perf_log_throttle(event, 1);
                        event->pmu->start(event, 0);
                }
@@ -2358,14 +2374,30 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
                if (!event->attr.freq || !event->attr.sample_freq)
                        continue;
 
-               event->pmu->read(event);
+               /*
+                * stop the event and update event->count
+                */
+               event->pmu->stop(event, PERF_EF_UPDATE);
+
                now = local64_read(&event->count);
                delta = now - hwc->freq_count_stamp;
                hwc->freq_count_stamp = now;
 
+               /*
+                * restart the event
+                * reload only if value has changed
+                * we have stopped the event so tell that
+                * to perf_adjust_period() to avoid stopping it
+                * twice.
+                */
                if (delta > 0)
-                       perf_adjust_period(event, period, delta);
+                       perf_adjust_period(event, period, delta, false);
+
+               event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
        }
+
+       perf_pmu_enable(ctx->pmu);
+       raw_spin_unlock(&ctx->lock);
 }
 
 /*
@@ -2388,16 +2420,13 @@ static void rotate_ctx(struct perf_event_context *ctx)
  */
 static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 {
-       u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;
        struct perf_event_context *ctx = NULL;
-       int rotate = 0, remove = 1, freq = 0;
+       int rotate = 0, remove = 1;
 
        if (cpuctx->ctx.nr_events) {
                remove = 0;
                if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
                        rotate = 1;
-               if (cpuctx->ctx.nr_freq)
-                       freq = 1;
        }
 
        ctx = cpuctx->task_ctx;
@@ -2405,37 +2434,26 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
                remove = 0;
                if (ctx->nr_events != ctx->nr_active)
                        rotate = 1;
-               if (ctx->nr_freq)
-                       freq = 1;
        }
 
-       if (!rotate && !freq)
+       if (!rotate)
                goto done;
 
        perf_ctx_lock(cpuctx, cpuctx->task_ctx);
        perf_pmu_disable(cpuctx->ctx.pmu);
 
-       if (freq) {
-               perf_ctx_adjust_freq(&cpuctx->ctx, interval);
-               if (ctx)
-                       perf_ctx_adjust_freq(ctx, interval);
-       }
-
-       if (rotate) {
-               cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
-               if (ctx)
-                       ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
+       cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
+       if (ctx)
+               ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
 
-               rotate_ctx(&cpuctx->ctx);
-               if (ctx)
-                       rotate_ctx(ctx);
+       rotate_ctx(&cpuctx->ctx);
+       if (ctx)
+               rotate_ctx(ctx);
 
-               perf_event_sched_in(cpuctx, ctx, current);
-       }
+       perf_event_sched_in(cpuctx, ctx, current);
 
        perf_pmu_enable(cpuctx->ctx.pmu);
        perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-
 done:
        if (remove)
                list_del_init(&cpuctx->rotation_list);
@@ -2445,10 +2463,22 @@ void perf_event_task_tick(void)
 {
        struct list_head *head = &__get_cpu_var(rotation_list);
        struct perf_cpu_context *cpuctx, *tmp;
+       struct perf_event_context *ctx;
+       int throttled;
 
        WARN_ON(!irqs_disabled());
 
+       __this_cpu_inc(perf_throttled_seq);
+       throttled = __this_cpu_xchg(perf_throttled_count, 0);
+
        list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
+               ctx = &cpuctx->ctx;
+               perf_adjust_freq_unthr_context(ctx, throttled);
+
+               ctx = cpuctx->task_ctx;
+               if (ctx)
+                       perf_adjust_freq_unthr_context(ctx, throttled);
+
                if (cpuctx->jiffies_interval == 1 ||
                                !(jiffies % cpuctx->jiffies_interval))
                        perf_rotate_context(cpuctx);
@@ -4509,6 +4539,7 @@ static int __perf_event_overflow(struct perf_event *event,
 {
        int events = atomic_read(&event->event_limit);
        struct hw_perf_event *hwc = &event->hw;
+       u64 seq;
        int ret = 0;
 
        /*
@@ -4518,14 +4549,20 @@ static int __perf_event_overflow(struct perf_event *event,
        if (unlikely(!is_sampling_event(event)))
                return 0;
 
-       if (unlikely(hwc->interrupts >= max_samples_per_tick)) {
-               if (throttle) {
+       seq = __this_cpu_read(perf_throttled_seq);
+       if (seq != hwc->interrupts_seq) {
+               hwc->interrupts_seq = seq;
+               hwc->interrupts = 1;
+       } else {
+               hwc->interrupts++;
+               if (unlikely(throttle
+                            && hwc->interrupts >= max_samples_per_tick)) {
+                       __this_cpu_inc(perf_throttled_count);
                        hwc->interrupts = MAX_INTERRUPTS;
                        perf_log_throttle(event, 0);
                        ret = 1;
                }
-       } else
-               hwc->interrupts++;
+       }
 
        if (event->attr.freq) {
                u64 now = perf_clock();
@@ -4534,7 +4571,7 @@ static int __perf_event_overflow(struct perf_event *event,
                hwc->freq_time_stamp = now;
 
                if (delta > 0 && delta < 2*TICK_NSEC)
-                       perf_adjust_period(event, delta, hwc->last_period);
+                       perf_adjust_period(event, delta, hwc->last_period, true);
        }
 
        /*
index c44738267be770118b64203eb3cbd411d9656686..4b4042f9bc6ade78a14199eb4ce96dc4ce6236b3 100644 (file)
@@ -964,8 +964,7 @@ void do_exit(long code)
        acct_collect(code, group_dead);
        if (group_dead)
                tty_audit_exit();
-       if (unlikely(tsk->audit_context))
-               audit_free(tsk);
+       audit_free(tsk);
 
        tsk->exit_code = code;
        taskstats_exit(tsk, group_dead);
@@ -1039,6 +1038,22 @@ void do_exit(long code)
        if (tsk->nr_dirtied)
                __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
        exit_rcu();
+
+       /*
+        * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+        * when the following two conditions become true.
+        *   - There is race condition of mmap_sem (It is acquired by
+        *     exit_mm()), and
+        *   - SMI occurs before setting TASK_RUNINNG.
+        *     (or hypervisor of virtual machine switches to other guest)
+        *  As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+        *
+        * To avoid it, we have to wait for releasing tsk->pi_lock which
+        * is held by try_to_wake_up()
+        */
+       smp_mb();
+       raw_spin_unlock_wait(&tsk->pi_lock);
+
        /* causes final put_task_struct in finish_task_switch(). */
        tsk->state = TASK_DEAD;
        tsk->flags |= PF_NOFREEZE;      /* tell freezer to ignore us */
index f3fa18887cc9b8d7fbde14f0e6fe36f57f791b96..b77fd559c78e6bbe6f92a2dfa26542a0714db083 100644 (file)
@@ -647,6 +647,26 @@ struct mm_struct *get_task_mm(struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(get_task_mm);
 
+struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
+{
+       struct mm_struct *mm;
+       int err;
+
+       err =  mutex_lock_killable(&task->signal->cred_guard_mutex);
+       if (err)
+               return ERR_PTR(err);
+
+       mm = get_task_mm(task);
+       if (mm && mm != current->mm &&
+                       !ptrace_may_access(task, mode)) {
+               mmput(mm);
+               mm = ERR_PTR(-EACCES);
+       }
+       mutex_unlock(&task->signal->cred_guard_mutex);
+
+       return mm;
+}
+
 /* Please note the differences between mmput and mm_release.
  * mmput is called whenever we stop holding onto a mm_struct,
  * error success whatever.
@@ -890,7 +910,7 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
                        return -ENOMEM;
 
                new_ioc->ioprio = ioc->ioprio;
-               put_io_context(new_ioc, NULL);
+               put_io_context(new_ioc);
        }
 #endif
        return 0;
@@ -1527,8 +1547,6 @@ long do_fork(unsigned long clone_flags,
                        init_completion(&vfork);
                }
 
-               audit_finish_fork(p);
-
                /*
                 * We set PF_STARTING at creation in case tracing wants to
                 * use this to distinguish a fully live task from one that
index 95dd7212e610b5a3da4ce97997a88f5c67d89b2d..9788c0ec6f4378f19cd80e873d42a0aec7171548 100644 (file)
@@ -1077,6 +1077,7 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
                /* Early boot.  kretprobe_table_locks not yet initialized. */
                return;
 
+       INIT_HLIST_HEAD(&empty_rp);
        hash = hash_ptr(tk, KPROBE_HASH_BITS);
        head = &kretprobe_inst_table[hash];
        kretprobe_table_lock(hash, &flags);
@@ -1085,7 +1086,6 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
                        recycle_rp_inst(ri, &empty_rp);
        }
        kretprobe_table_unlock(hash, &flags);
-       INIT_HLIST_HEAD(&empty_rp);
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
                hlist_del(&ri->hlist);
                kfree(ri);
@@ -1673,8 +1673,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
                ri->rp = rp;
                ri->task = current;
 
-               if (rp->entry_handler && rp->entry_handler(ri, regs))
+               if (rp->entry_handler && rp->entry_handler(ri, regs)) {
+                       raw_spin_lock_irqsave(&rp->lock, flags);
+                       hlist_add_head(&ri->hlist, &rp->free_instances);
+                       raw_spin_unlock_irqrestore(&rp->lock, flags);
                        return 0;
+               }
 
                arch_prepare_kretprobe(ri, regs);
 
index 32ee04308285c051a4521a192d80dc89f34e1d59..4bc965d8a1fe8d66b66b7e7e220c08104084205a 100644 (file)
@@ -97,7 +97,8 @@ static int parse_one(char *param,
        for (i = 0; i < num_params; i++) {
                if (parameq(param, params[i].name)) {
                        /* No one handled NULL, so do it here. */
-                       if (!val && params[i].ops->set != param_set_bool)
+                       if (!val && params[i].ops->set != param_set_bool
+                           && params[i].ops->set != param_set_bint)
                                return -EINVAL;
                        pr_debug("They are equal!  Calling %p\n",
                               params[i].ops->set);
index ce8e00deaccb38452188436438dc942313bd6c44..9f08dfabaf13af1f79a8ae4c5bb87a4434736d18 100644 (file)
@@ -543,12 +543,12 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
  */
 void __init pidhash_init(void)
 {
-       int i, pidhash_size;
+       unsigned int i, pidhash_size;
 
        pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18,
                                           HASH_EARLY | HASH_SMALL,
                                           &pidhash_shift, NULL, 4096);
-       pidhash_size = 1 << pidhash_shift;
+       pidhash_size = 1U << pidhash_shift;
 
        for (i = 0; i < pidhash_size; i++)
                INIT_HLIST_HEAD(&pid_hash[i]);
index 0c4defe6d3b873443e927c63755e27ffa9db051b..21724eee5206f7ffe6f780ba6c0c8acb8e7a0930 100644 (file)
@@ -231,8 +231,28 @@ extern int pm_test_level;
 #ifdef CONFIG_SUSPEND_FREEZER
 static inline int suspend_freeze_processes(void)
 {
-       int error = freeze_processes();
-       return error ? : freeze_kernel_threads();
+       int error;
+
+       error = freeze_processes();
+
+       /*
+        * freeze_processes() automatically thaws every task if freezing
+        * fails. So we need not do anything extra upon error.
+        */
+       if (error)
+               goto Finish;
+
+       error = freeze_kernel_threads();
+
+       /*
+        * freeze_kernel_threads() thaws only kernel threads upon freezing
+        * failure. So we have to thaw the userspace tasks ourselves.
+        */
+       if (error)
+               thaw_processes();
+
+ Finish:
+       return error;
 }
 
 static inline void suspend_thaw_processes(void)
index 77274c9ba2f1a95862787e041254f736539a1264..7e426459e60a21633d8eeff0d9751455303bdf97 100644 (file)
@@ -143,7 +143,10 @@ int freeze_processes(void)
 /**
  * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
  *
- * On success, returns 0.  On failure, -errno and system is fully thawed.
+ * On success, returns 0.  On failure, -errno and only the kernel threads are
+ * thawed, so as to give a chance to the caller to do additional cleanups
+ * (if any) before thawing the userspace tasks. So, it is the responsibility
+ * of the caller to thaw the userspace tasks, when the time is right.
  */
 int freeze_kernel_threads(void)
 {
@@ -159,7 +162,7 @@ int freeze_kernel_threads(void)
        BUG_ON(in_atomic());
 
        if (error)
-               thaw_processes();
+               thaw_kernel_threads();
        return error;
 }
 
@@ -188,3 +191,22 @@ void thaw_processes(void)
        printk("done.\n");
 }
 
+void thaw_kernel_threads(void)
+{
+       struct task_struct *g, *p;
+
+       pm_nosig_freezing = false;
+       printk("Restarting kernel threads ... ");
+
+       thaw_workqueues();
+
+       read_lock(&tasklist_lock);
+       do_each_thread(g, p) {
+               if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
+                       __thaw_task(p);
+       } while_each_thread(g, p);
+       read_unlock(&tasklist_lock);
+
+       schedule();
+       printk("done.\n");
+}
index 1cf88900ec4fdc162b6ad1250d2c4d13d3895458..6a768e537001ce653e61c080baec76fbc5570da0 100644 (file)
@@ -812,7 +812,8 @@ unsigned int snapshot_additional_pages(struct zone *zone)
        unsigned int res;
 
        res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK);
-       res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE);
+       res += DIV_ROUND_UP(res * sizeof(struct bm_block),
+                           LINKED_PAGE_DATA_SIZE);
        return 2 * res;
 }
 
index 6b1ab7a88522827cc1ec5cdd3f0cdfa62d56accf..3e100075b13cb6ab449034af458266e20dcaa369 100644 (file)
@@ -249,13 +249,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                }
                pm_restore_gfp_mask();
                error = hibernation_snapshot(data->platform_support);
-               if (!error) {
+               if (error) {
+                       thaw_kernel_threads();
+               } else {
                        error = put_user(in_suspend, (int __user *)arg);
                        if (!error && !freezer_test_done)
                                data->ready = 1;
                        if (freezer_test_done) {
                                freezer_test_done = false;
-                               thaw_processes();
+                               thaw_kernel_threads();
                        }
                }
                break;
@@ -274,6 +276,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                swsusp_free();
                memset(&data->handle, 0, sizeof(struct snapshot_handle));
                data->ready = 0;
+               /*
+                * It is necessary to thaw kernel threads here, because
+                * SNAPSHOT_CREATE_IMAGE may be invoked directly after
+                * SNAPSHOT_FREE.  In that case, if kernel threads were not
+                * thawed, the preallocation of memory carried out by
+                * hibernation_snapshot() might run into problems (i.e. it
+                * might fail or even deadlock).
+                */
+               thaw_kernel_threads();
                break;
 
        case SNAPSHOT_PREF_IMAGE_SIZE:
index 88f17b8a3b1dac38abbdb42c6916bd52cea5f2b1..a58ac285fc69bb48d085708caf786f6f39413474 100644 (file)
@@ -56,8 +56,8 @@ static int nreaders = -1;     /* # reader threads, defaults to 2*ncpus */
 static int nfakewriters = 4;   /* # fake writer threads */
 static int stat_interval;      /* Interval between stats, in seconds. */
                                /*  Defaults to "only at end of test". */
-static int verbose;            /* Print more debug info. */
-static int test_no_idle_hz;    /* Test RCU's support for tickless idle CPUs. */
+static bool verbose;           /* Print more debug info. */
+static bool test_no_idle_hz;   /* Test RCU's support for tickless idle CPUs. */
 static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
 static int stutter = 5;                /* Start/stop testing interval (in sec) */
 static int irqreader = 1;      /* RCU readers from irq (timers). */
@@ -1399,7 +1399,7 @@ rcu_torture_shutdown(void *arg)
  * Execute random CPU-hotplug operations at the interval specified
  * by the onoff_interval.
  */
-static int
+static int __cpuinit
 rcu_torture_onoff(void *arg)
 {
        int cpu;
@@ -1447,7 +1447,7 @@ rcu_torture_onoff(void *arg)
        return 0;
 }
 
-static int
+static int __cpuinit
 rcu_torture_onoff_init(void)
 {
        if (onoff_interval <= 0)
index 4335e1d7ee2d722c94507775b4c8d7c3cd21d567..ab56a1764d4db8c6a5136cd3b636dc330648783b 100644 (file)
@@ -164,10 +164,14 @@ depopulate:
  */
 static struct rchan_buf *relay_create_buf(struct rchan *chan)
 {
-       struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
-       if (!buf)
+       struct rchan_buf *buf;
+
+       if (chan->n_subbufs > UINT_MAX / sizeof(size_t *))
                return NULL;
 
+       buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
+       if (!buf)
+               return NULL;
        buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
        if (!buf->padding)
                goto free_buf;
@@ -574,6 +578,8 @@ struct rchan *relay_open(const char *base_filename,
 
        if (!(subbuf_size && n_subbufs))
                return NULL;
+       if (subbuf_size > UINT_MAX / n_subbufs)
+               return NULL;
 
        chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
        if (!chan)
index 6d269cce7aa13c4593540f6aa80be389e3ffc720..d508363858b3a147cf757ae06080dde035842091 100644 (file)
@@ -66,6 +66,31 @@ done:
        return ret;
 }
 
+int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
+                             struct res_counter **limit_fail_at)
+{
+       int ret, r;
+       unsigned long flags;
+       struct res_counter *c;
+
+       r = ret = 0;
+       *limit_fail_at = NULL;
+       local_irq_save(flags);
+       for (c = counter; c != NULL; c = c->parent) {
+               spin_lock(&c->lock);
+               r = res_counter_charge_locked(c, val);
+               if (r)
+                       c->usage += val;
+               spin_unlock(&c->lock);
+               if (r < 0 && ret == 0) {
+                       *limit_fail_at = c;
+                       ret = r;
+               }
+       }
+       local_irq_restore(flags);
+
+       return ret;
+}
 void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
 {
        if (WARN_ON(counter->usage < val))
index df00cb09263e093b2c0a9c73a20e16b6602a70ea..5255c9d2e053225173dfea134e7e243ad0e80891 100644 (file)
@@ -74,6 +74,7 @@
 
 #include <asm/tlb.h>
 #include <asm/irq_regs.h>
+#include <asm/mutex.h>
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #endif
@@ -723,9 +724,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
        p->sched_class->dequeue_task(rq, p, flags);
 }
 
-/*
- * activate_task - move a task to the runqueue.
- */
 void activate_task(struct rq *rq, struct task_struct *p, int flags)
 {
        if (task_contributes_to_load(p))
@@ -734,9 +732,6 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags)
        enqueue_task(rq, p, flags);
 }
 
-/*
- * deactivate_task - remove a task from the runqueue.
- */
 void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
 {
        if (task_contributes_to_load(p))
@@ -4134,7 +4129,7 @@ recheck:
        on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
-               deactivate_task(rq, p, 0);
+               dequeue_task(rq, p, 0);
        if (running)
                p->sched_class->put_prev_task(rq, p);
 
@@ -4147,7 +4142,7 @@ recheck:
        if (running)
                p->sched_class->set_curr_task(rq);
        if (on_rq)
-               activate_task(rq, p, 0);
+               enqueue_task(rq, p, 0);
 
        check_class_changed(rq, p, prev_class, oldprio);
        task_rq_unlock(rq, p, &flags);
@@ -4998,9 +4993,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
         * placed properly.
         */
        if (p->on_rq) {
-               deactivate_task(rq_src, p, 0);
+               dequeue_task(rq_src, p, 0);
                set_task_cpu(p, dest_cpu);
-               activate_task(rq_dest, p, 0);
+               enqueue_task(rq_dest, p, 0);
                check_preempt_curr(rq_dest, p, 0);
        }
 done:
@@ -7032,10 +7027,10 @@ static void normalize_task(struct rq *rq, struct task_struct *p)
 
        on_rq = p->on_rq;
        if (on_rq)
-               deactivate_task(rq, p, 0);
+               dequeue_task(rq, p, 0);
        __setscheduler(rq, p, SCHED_NORMAL, 0);
        if (on_rq) {
-               activate_task(rq, p, 0);
+               enqueue_task(rq, p, 0);
                resched_task(rq->curr);
        }
 
index b0d798eaf1302b6b2f93836be0cc232b4614709f..d72586fdf6607db63c5f43a2e1fbbb32ff0ac2c7 100644 (file)
@@ -129,7 +129,7 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
  * cpupri_set - update the cpu priority setting
  * @cp: The cpupri context
  * @cpu: The target cpu
- * @pri: The priority (INVALID-RT99) to assign to this CPU
+ * @newpri: The priority (INVALID-RT99) to assign to this CPU
  *
  * Note: Assumes cpu_rq(cpu)->lock is locked
  *
@@ -200,7 +200,6 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri)
 /**
  * cpupri_init - initialize the cpupri structure
  * @cp: The cpupri context
- * @bootmem: true if allocations need to use bootmem
  *
  * Returns: -ENOMEM if memory fails.
  */
index 84adb2d66cbd3dc15e653532462203f8c73bba18..7c6414fc669de4f09dc03fc763aaddd8040f98bf 100644 (file)
@@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu)
        return;
 }
 
+static inline void clear_nohz_tick_stopped(int cpu)
+{
+       if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
+               cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+               atomic_dec(&nohz.nr_cpus);
+               clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
+       }
+}
+
 static inline void set_cpu_sd_state_busy(void)
 {
        struct sched_domain *sd;
@@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick)
 {
        int cpu = smp_processor_id();
 
+       /*
+        * If this cpu is going down, then nothing needs to be done.
+        */
+       if (!cpu_active(cpu))
+               return;
+
        if (stop_tick) {
                if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
                        return;
@@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick)
        }
        return;
 }
+
+static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb,
+                                       unsigned long action, void *hcpu)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DYING:
+               clear_nohz_tick_stopped(smp_processor_id());
+               return NOTIFY_OK;
+       default:
+               return NOTIFY_DONE;
+       }
+}
 #endif
 
 static DEFINE_SPINLOCK(balancing);
@@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
        * busy tick after returning from idle, we will update the busy stats.
        */
        set_cpu_sd_state_busy();
-       if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
-               clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
-               cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
-               atomic_dec(&nohz.nr_cpus);
-       }
+       clear_nohz_tick_stopped(cpu);
 
        /*
         * None are in tickless mode and hence no need for NOHZ idle load
@@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void)
 
 #ifdef CONFIG_NO_HZ
        zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
+       cpu_notifier(sched_ilb_notifier, 0);
 #endif
 #endif /* SMP */
 
index 3640ebbb466b0bb82d2894ec8223c96bfe502b74..f42ae7fb5ec555a42fe0b63376891aaf8b756af5 100644 (file)
@@ -1587,6 +1587,11 @@ static int push_rt_task(struct rq *rq)
        if (!next_task)
                return 0;
 
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+       if (unlikely(task_running(rq, next_task)))
+               return 0;
+#endif
+
 retry:
        if (unlikely(next_task == rq->curr)) {
                WARN_ON(1);
index 57d4b13b631de36161349feb99ae6f76a2984b06..e8d76c5895ea15f3bb4867a85f48851dedf90cd4 100644 (file)
@@ -6,6 +6,7 @@
  * This defines a simple but solid secure-computing mode.
  */
 
+#include <linux/audit.h>
 #include <linux/seccomp.h>
 #include <linux/sched.h>
 #include <linux/compat.h>
@@ -54,6 +55,7 @@ void __secure_computing(int this_syscall)
 #ifdef SECCOMP_DEBUG
        dump_stack();
 #endif
+       audit_seccomp(this_syscall);
        do_exit(SIGKILL);
 }
 
index db110b8ae0309a39cfdef20e75351b989431cf2a..f1539decd99d853d1a5c44fb3296072444aabf1a 100644 (file)
@@ -634,10 +634,11 @@ static int tracepoint_module_coming(struct module *mod)
        int ret = 0;
 
        /*
-        * We skip modules that tain the kernel, especially those with different
-        * module header (for forced load), to make sure we don't cause a crash.
+        * We skip modules that taint the kernel, especially those with different
+        * module headers (for forced load), to make sure we don't cause a crash.
+        * Staging and out-of-tree GPL modules are fine.
         */
-       if (mod->taints)
+       if (mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP)))
                return 0;
        mutex_lock(&tracepoints_mutex);
        tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL);
index 1d7bca7f4f527c2f25b741da9fc914980a0c43bb..d117262deba305400ba768b1f7cecc945f3faba8 100644 (file)
@@ -296,7 +296,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
                if (__this_cpu_read(soft_watchdog_warn) == true)
                        return HRTIMER_RESTART;
 
-               printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
+               printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
                        smp_processor_id(), duration,
                        current->comm, task_pid_nr(current));
                print_modules();
index 201e1b33d721bf2ff83e6cd5ca817ea243861c39..028aba9e72af98b402aeec059e0800681e1fad5a 100644 (file)
@@ -19,6 +19,9 @@ config RATIONAL
 config GENERIC_FIND_FIRST_BIT
        bool
 
+config NO_GENERIC_PCI_IOPORT_MAP
+       bool
+
 config GENERIC_PCI_IOMAP
        bool
 
@@ -279,6 +282,9 @@ config AVERAGE
 
          If unsure, say N.
 
+config CLZ_TAB
+       bool
+
 config CORDIC
        tristate "CORDIC algorithm"
        help
@@ -286,25 +292,25 @@ config CORDIC
          calculations are in fixed point. Module will be called cordic.
 
 config MPILIB
-       tristate "Multiprecision maths library"
+       tristate
+       select CLZ_TAB
        help
          Multiprecision maths library from GnuPG.
          It is used to implement RSA digital signature verification,
          which is used by IMA/EVM digital signature extension.
 
 config MPILIB_EXTRA
-       bool "Multiprecision maths library - additional sources"
+       bool
        depends on MPILIB
        help
-         Multiprecision maths library from GnuPG.
-         It is used to implement RSA digital signature verification,
-         which is used by IMA/EVM digital signature extension.
-         This code in unnecessary for RSA digital signature verification,
-         and can be compiled if needed.
+         Additional sources of multiprecision maths library from GnuPG.
+         This code is unnecessary for RSA digital signature verification,
+         but can be compiled if needed.
 
-config DIGSIG
-       tristate "In-kernel signature checker"
-       depends on KEYS
+config SIGNATURE
+       tristate
+       depends on KEYS && CRYPTO
+       select CRYPTO_SHA1
        select MPILIB
        help
          Digital signature verification. Currently only RSA is supported.
index dace162c7e1c2f063498ded701e5576f3c16b75a..18515f0267c41591a198a1df9b3c7950a56a16cf 100644 (file)
@@ -119,7 +119,9 @@ obj-$(CONFIG_CORDIC) += cordic.o
 obj-$(CONFIG_DQL) += dynamic_queue_limits.o
 
 obj-$(CONFIG_MPILIB) += mpi/
-obj-$(CONFIG_DIGSIG) += digsig.o
+obj-$(CONFIG_SIGNATURE) += digsig.o
+
+obj-$(CONFIG_CLZ_TAB) += clz_tab.o
 
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
index 19552096d16b06bd2dac2a9b10212e482a4d0da3..a28c1415357cac9d30fc09195652fbfd099bc421 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -169,7 +169,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
                return BUG_TRAP_TYPE_WARN;
        }
 
-       printk(KERN_EMERG "------------[ cut here ]------------\n");
+       printk(KERN_DEFAULT "------------[ cut here ]------------\n");
 
        if (file)
                printk(KERN_CRIT "kernel BUG at %s:%u!\n",
diff --git a/lib/clz_tab.c b/lib/clz_tab.c
new file mode 100644 (file)
index 0000000..7287b4a
--- /dev/null
@@ -0,0 +1,18 @@
+const unsigned char __clz_tab[] = {
+       0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+           5, 5, 5, 5, 5, 5, 5, 5,
+       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+           6, 6, 6, 6, 6, 6, 6, 6,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+           7, 7, 7, 7, 7, 7, 7, 7,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+           7, 7, 7, 7, 7, 7, 7, 7,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+};
index fd2402f67f89a0d740fc5cc1fbb4a27dbe420a39..286d558033e270524ff3fdeac9c96393b81170a6 100644 (file)
@@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
                        unsigned long  msglen,
                        unsigned long  modulus_bitlen,
                        unsigned char *out,
-                       unsigned long *outlen,
-                       int *is_valid)
+                       unsigned long *outlen)
 {
        unsigned long modulus_len, ps_len, i;
-       int result;
-
-       /* default to invalid packet */
-       *is_valid = 0;
 
        modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
 
@@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
                return -EINVAL;
 
        /* separate encoded message */
-       if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) {
-               result = -EINVAL;
-               goto bail;
-       }
+       if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
+               return -EINVAL;
 
        for (i = 2; i < modulus_len - 1; i++)
                if (msg[i] != 0xFF)
                        break;
 
        /* separator check */
-       if (msg[i] != 0) {
+       if (msg[i] != 0)
                /* There was no octet with hexadecimal value 0x00
                to separate ps from m. */
-               result = -EINVAL;
-               goto bail;
-       }
+               return -EINVAL;
 
        ps_len = i - 2;
 
        if (*outlen < (msglen - (2 + ps_len + 1))) {
                *outlen = msglen - (2 + ps_len + 1);
-               result = -EOVERFLOW;
-               goto bail;
+               return -EOVERFLOW;
        }
 
        *outlen = (msglen - (2 + ps_len + 1));
        memcpy(out, &msg[2 + ps_len + 1], *outlen);
 
-       /* valid packet */
-       *is_valid = 1;
-       result    = 0;
-bail:
-       return result;
+       return 0;
 }
 
 /*
@@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key,
        unsigned long len;
        unsigned long mlen, mblen;
        unsigned nret, l;
-       int valid, head, i;
+       int head, i;
        unsigned char *out1 = NULL, *out2 = NULL;
        MPI in = NULL, res = NULL, pkey[2];
        uint8_t *p, *datap, *endp;
@@ -105,6 +91,10 @@ static int digsig_verify_rsa(struct key *key,
 
        down_read(&key->sem);
        ukp = key->payload.data;
+
+       if (ukp->datalen < sizeof(*pkh))
+               goto err1;
+
        pkh = (struct pubkey_hdr *)ukp->data;
 
        if (pkh->version != 1)
@@ -117,18 +107,23 @@ static int digsig_verify_rsa(struct key *key,
                goto err1;
 
        datap = pkh->mpi;
-       endp = datap + ukp->datalen;
+       endp = ukp->data + ukp->datalen;
+
+       err = -ENOMEM;
 
        for (i = 0; i < pkh->nmpi; i++) {
                unsigned int remaining = endp - datap;
                pkey[i] = mpi_read_from_buffer(datap, &remaining);
+               if (!pkey[i])
+                       goto err;
                datap += remaining;
        }
 
        mblen = mpi_get_nbits(pkey[0]);
        mlen = (mblen + 7)/8;
 
-       err = -ENOMEM;
+       if (mlen == 0)
+               goto err;
 
        out1 = kzalloc(mlen, GFP_KERNEL);
        if (!out1)
@@ -167,10 +162,9 @@ static int digsig_verify_rsa(struct key *key,
        memset(out1, 0, head);
        memcpy(out1 + head, p, l);
 
-       err = -EINVAL;
-       pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid);
+       err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
 
-       if (valid && len == hlen)
+       if (!err && len == hlen)
                err = memcmp(out2, h, hlen);
 
 err:
@@ -178,8 +172,8 @@ err:
        mpi_free(res);
        kfree(out1);
        kfree(out2);
-       mpi_free(pkey[0]);
-       mpi_free(pkey[1]);
+       while (--i >= 0)
+               mpi_free(pkey[i]);
 err1:
        up_read(&key->sem);
 
index 7a94c8f14e295faaa2a80958081f961dba6561ce..b1dd3e7d88cb8b1379d6bdde8b130034ce5e36ac 100644 (file)
@@ -44,12 +44,13 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
  *
  * Don't you dare use this function.
  */
-unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res)
+unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
 {
+       unsigned long long res;
        unsigned int rv;
        int overflow;
 
-       *res = 0;
+       res = 0;
        rv = 0;
        overflow = 0;
        while (*s) {
@@ -64,12 +65,19 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long
 
                if (val >= base)
                        break;
-               if (*res > div_u64(ULLONG_MAX - val, base))
-                       overflow = 1;
-               *res = *res * base + val;
+               /*
+                * Check for overflow only if we are within range of
+                * it in the max base we support (16)
+                */
+               if (unlikely(res & (~0ull << 60))) {
+                       if (res > div_u64(ULLONG_MAX - val, base))
+                               overflow = 1;
+               }
+               res = res * base + val;
                rv++;
                s++;
        }
+       *p = res;
        if (overflow)
                rv |= KSTRTOX_OVERFLOW;
        return rv;
index b87487b40a8b910d01c6c4f9395081e4d05f3d1a..29f98624ef93a706b4fa302972669c83f70bd49d 100644 (file)
@@ -1200,18 +1200,40 @@ do { \
        "r" ((USItype)(v)) \
        : "%g1", "%g2" __AND_CLOBBER_CC)
 #define UMUL_TIME 39           /* 39 instructions */
-#endif
-#ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
+/* It's quite necessary to add this much assembler for the sparc.
+   The default udiv_qrnnd (in C) is more than 10 times slower!  */
 #define udiv_qrnnd(q, r, n1, n0, d) \
-do { USItype __r; \
-       (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
-       (r) = __r; \
-} while (0)
-       extern USItype __udiv_qrnnd();
-#define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
-#endif /* udiv_qrnnd */
+  __asm__ ("! Inlined udiv_qrnnd\n\t"                                  \
+          "mov 32,%%g1\n\t"                                            \
+          "subcc       %1,%2,%%g0\n\t"                                 \
+          "1:  bcs     5f\n\t"                                         \
+          "addxcc %0,%0,%0     ! shift n1n0 and a q-bit in lsb\n\t"    \
+          "sub %1,%2,%1        ! this kills msb of n\n\t"              \
+          "addx        %1,%1,%1        ! so this can't give carry\n\t" \
+          "subcc       %%g1,1,%%g1\n\t"                                \
+          "2:  bne     1b\n\t"                                         \
+          "subcc       %1,%2,%%g0\n\t"                                 \
+          "bcs 3f\n\t"                                                 \
+          "addxcc %0,%0,%0     ! shift n1n0 and a q-bit in lsb\n\t"    \
+          "b           3f\n\t"                                         \
+          "sub %1,%2,%1        ! this kills msb of n\n\t"              \
+          "4:  sub     %1,%2,%1\n\t"                                   \
+          "5:  addxcc  %1,%1,%1\n\t"                                   \
+          "bcc 2b\n\t"                                                 \
+          "subcc       %%g1,1,%%g1\n\t"                                \
+          "! Got carry from n.  Subtract next step to cancel this carry.\n\t" \
+          "bne 4b\n\t"                                                 \
+          "addcc       %0,%0,%0        ! shift n1n0 and a 0-bit in lsb\n\t" \
+          "sub %1,%2,%1\n\t"                                           \
+          "3:  xnor    %0,0,%0\n\t"                                    \
+          "! End of inline udiv_qrnnd\n"                               \
+          : "=&r" ((USItype)(q)),                                      \
+            "=&r" ((USItype)(r))                                       \
+          : "r" ((USItype)(d)),                                        \
+            "1" ((USItype)(n1)),                                       \
+            "0" ((USItype)(n0)) : "%g1", "cc")
+#define UDIV_TIME (3+7*32)      /* 7 instructions/iteration. 32 iterations.  */
+#endif
 #endif /* __sparc__ */
 
 /***************************************
index 854c9c6da025ef905178cd1b568ff0cbeb1609f2..2f526627e4f575c50468b51015270c35d2179721 100644 (file)
 #include "mpi-internal.h"
 #include "longlong.h"
 
-const unsigned char __clz_tab[] = {
-       0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
-           5, 5, 5, 5, 5, 5, 5, 5,
-       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-           6, 6, 6, 6, 6, 6, 6, 6,
-       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-           7, 7, 7, 7, 7, 7, 7, 7,
-       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-           7, 7, 7, 7, 7, 7, 7, 7,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-           8, 8, 8, 8, 8, 8, 8, 8,
-};
-
 #define A_LIMB_1 ((mpi_limb_t) 1)
 
 /****************
index c3087d1390ce5d1b669ce7f1326b4eaf079d2caa..f68cbbb4d4a4ec74246be1559e2beaa0c1ce5284 100644 (file)
@@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
        mpi_ptr_t marker[5];
        int markidx = 0;
 
+       if (!dsize)
+               return -EINVAL;
+
        memset(marker, 0, sizeof(marker));
 
        /* Ensure space is enough for quotient and remainder.
@@ -207,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
                 * numerator would be gradually overwritten by the quotient limbs.  */
                if (qp == np) { /* Copy NP object to temporary space.  */
                        np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+                       if (!np)
+                               goto nomem;
                        MPN_COPY(np, qp, nsize);
                }
        } else                  /* Put quotient at top of remainder. */
index b04a3cf8008083d8e54f861df465b1f831b98df3..67f3e79af9140e0160a4264b506b41344304e916 100644 (file)
@@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
        ep = exp->d;
 
        if (!msize)
-               msize = 1 / msize;      /* provoke a signal */
+               return -EINVAL;
 
        if (!esize) {
                /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
index fe84bb978e3b5c42befda57c206edd0b68d61684..f26b41fcb48c694c06fdcea18b55bdfd3788fb6d 100644 (file)
 
 #include "mpi-internal.h"
 
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
 #define MAX_EXTERN_MPI_BITS 16384
 
-static uint8_t asn[15] =       /* Object ID is 1.3.14.3.2.26 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
-       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
-MPI do_encode_md(const void *sha_buffer, unsigned nbits)
-{
-       int nframe = (nbits + 7) / 8;
-       uint8_t *frame, *fr_pt;
-       int i = 0, n;
-       size_t asnlen = DIM(asn);
-       MPI a = MPI_NULL;
-
-       if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
-               pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
-                      (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
-
-       /* We encode the MD in this way:
-        *
-        *       0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
-        *
-        * PAD consists of FF bytes.
-        */
-       frame = kmalloc(nframe, GFP_KERNEL);
-       if (!frame)
-               return MPI_NULL;
-       n = 0;
-       frame[n++] = 0;
-       frame[n++] = 1;         /* block type */
-       i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
-
-       if (i <= 1) {
-               pr_info("MPI: message digest encoding failed\n");
-               kfree(frame);
-               return a;
-       }
-
-       memset(frame + n, 0xff, i);
-       n += i;
-       frame[n++] = 0;
-       memcpy(frame + n, &asn, asnlen);
-       n += asnlen;
-       memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
-       n += SHA1_DIGEST_LENGTH;
-
-       i = nframe;
-       fr_pt = frame;
-
-       if (n != nframe) {
-               printk
-                   ("MPI: message digest encoding failed, frame length is wrong\n");
-               kfree(frame);
-               return a;
-       }
-
-       a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
-       mpi_set_buffer(a, frame, nframe, 0);
-       kfree(frame);
-
-       return a;
-}
-
 MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
 {
        const uint8_t *buffer = xbuffer;
        int i, j;
        unsigned nbits, nbytes, nlimbs, nread = 0;
        mpi_limb_t a;
-       MPI val = MPI_NULL;
+       MPI val = NULL;
 
        if (*ret_nread < 2)
                goto leave;
@@ -108,7 +45,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
        nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
        val = mpi_alloc(nlimbs);
        if (!val)
-               return MPI_NULL;
+               return NULL;
        i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
        i %= BYTES_PER_MPI_LIMB;
        val->nbits = nbits;
@@ -211,30 +148,6 @@ int mpi_fromstr(MPI val, const char *str)
 }
 EXPORT_SYMBOL_GPL(mpi_fromstr);
 
-/****************
- * Special function to get the low 8 bytes from an mpi.
- * This can be used as a keyid; KEYID is an 2 element array.
- * Return the low 4 bytes.
- */
-u32 mpi_get_keyid(const MPI a, u32 *keyid)
-{
-#if BYTES_PER_MPI_LIMB == 4
-       if (keyid) {
-               keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
-               keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
-       }
-       return a->nlimbs >= 1 ? a->d[0] : 0;
-#elif BYTES_PER_MPI_LIMB == 8
-       if (keyid) {
-               keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
-               keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-       }
-       return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-#else
-#error Make this function work with other LIMB sizes
-#endif
-}
-
 /****************
  * Return an allocated buffer with the MPI (msb first).
  * NBYTES receives the length of this buffer. Caller must free the
@@ -255,6 +168,8 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
        if (!n)
                n++;            /* avoid zero length allocation */
        p = buffer = kmalloc(n, GFP_KERNEL);
+       if (!p)
+               return NULL;
 
        for (i = a->nlimbs - 1; i >= 0; i--) {
                alimb = a->d[i];
index 87ede162dfabee78a4cad86e850fdefa06f622f8..cde1aaec18da9d179853724b3928c5be8a4508d6 100644 (file)
@@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
        case 0:
                /* We are asked to divide by zero, so go ahead and do it!  (To make
                   the compiler not remove this statement, return the value.)  */
+               /*
+                * existing clients of this function have been modified
+                * not to call it with dsize == 0, so this should not happen
+                */
                return 1 / dsize;
 
        case 1:
index eefc55d6b7f5b8a732992c070d5bca4bac65c374..26e4ed31e256f793d4bdc21ea81f7f6a8ca4bf71 100644 (file)
@@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)
 {
        size_t len = nlimbs * sizeof(mpi_limb_t);
 
+       if (!len)
+               return NULL;
+
        return kmalloc(len, GFP_KERNEL);
 }
 
@@ -135,7 +138,7 @@ int mpi_copy(MPI *copied, const MPI a)
        size_t i;
        MPI b;
 
-       *copied = MPI_NULL;
+       *copied = NULL;
 
        if (a) {
                b = mpi_alloc(a->nlimbs);
index 4b0fdc22e688d3869c9e62005af933f8dcdd096a..0d83ea8a9605429aa5e79262bef539e51bfec456 100644 (file)
@@ -34,7 +34,7 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
        if (maxlen && len > maxlen)
                len = maxlen;
        if (flags & IORESOURCE_IO)
-               return ioport_map(start, len);
+               return __pci_ioport_map(dev, start, len);
        if (flags & IORESOURCE_MEM) {
                if (flags & IORESOURCE_CACHEABLE)
                        return ioremap(start, len);
index 7ba8feae11b8a5e1a33f002a6efc0ca9f3a82dde..dd8e2aafb07e1aecae5e42ac403d9915caa7e698 100644 (file)
@@ -318,7 +318,7 @@ static void wakeup_timer_fn(unsigned long data)
        if (bdi->wb.task) {
                trace_writeback_wake_thread(bdi);
                wake_up_process(bdi->wb.task);
-       } else {
+       } else if (bdi->dev) {
                /*
                 * When bdi tasks are inactive for long time, they are killed.
                 * In this case we have to wake-up the forker thread which
@@ -584,6 +584,8 @@ EXPORT_SYMBOL(bdi_register_dev);
  */
 static void bdi_wb_shutdown(struct backing_dev_info *bdi)
 {
+       struct task_struct *task;
+
        if (!bdi_cap_writeback_dirty(bdi))
                return;
 
@@ -602,8 +604,13 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
         * Finally, kill the kernel thread. We don't need to be RCU
         * safe anymore, since the bdi is gone from visibility.
         */
-       if (bdi->wb.task)
-               kthread_stop(bdi->wb.task);
+       spin_lock_bh(&bdi->wb_lock);
+       task = bdi->wb.task;
+       bdi->wb.task = NULL;
+       spin_unlock_bh(&bdi->wb_lock);
+
+       if (task)
+               kthread_stop(task);
 }
 
 /*
@@ -623,7 +630,9 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
 
 void bdi_unregister(struct backing_dev_info *bdi)
 {
-       if (bdi->dev) {
+       struct device *dev = bdi->dev;
+
+       if (dev) {
                bdi_set_min_ratio(bdi, 0);
                trace_writeback_bdi_unregister(bdi);
                bdi_prune_sb(bdi);
@@ -632,8 +641,12 @@ void bdi_unregister(struct backing_dev_info *bdi)
                if (!bdi_cap_flush_forker(bdi))
                        bdi_wb_shutdown(bdi);
                bdi_debug_unregister(bdi);
-               device_unregister(bdi->dev);
+
+               spin_lock_bh(&bdi->wb_lock);
                bdi->dev = NULL;
+               spin_unlock_bh(&bdi->wb_lock);
+
+               device_unregister(dev);
        }
 }
 EXPORT_SYMBOL(bdi_unregister);
index 71a58f67f4817720a4eca34678b2353fa96863e6..d9ebebe1a2aaaea69074fe3615faeddd41a4feb7 100644 (file)
@@ -313,12 +313,34 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
                } else if (!locked)
                        spin_lock_irq(&zone->lru_lock);
 
+               /*
+                * migrate_pfn does not necessarily start aligned to a
+                * pageblock. Ensure that pfn_valid is called when moving
+                * into a new MAX_ORDER_NR_PAGES range in case of large
+                * memory holes within the zone
+                */
+               if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) {
+                       if (!pfn_valid(low_pfn)) {
+                               low_pfn += MAX_ORDER_NR_PAGES - 1;
+                               continue;
+                       }
+               }
+
                if (!pfn_valid_within(low_pfn))
                        continue;
                nr_scanned++;
 
-               /* Get the page and skip if free */
+               /*
+                * Get the page and ensure the page is within the same zone.
+                * See the comment in isolate_freepages about overlapping
+                * nodes. It is deliberate that the new zone lock is not taken
+                * as memory compaction should not move pages between nodes.
+                */
                page = pfn_to_page(low_pfn);
+               if (page_zone(page) != zone)
+                       continue;
+
+               /* Skip if free */
                if (PageBuddy(page))
                        continue;
 
index 97f49ed35bd24fba29677857433814103949dd14..b66275757c281b39e1d7cc0fecf6465bea5b4257 100644 (file)
@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
        unsigned long seg = 0;
        size_t count;
        loff_t *ppos = &iocb->ki_pos;
-       struct blk_plug plug;
 
        count = 0;
        retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
        if (retval)
                return retval;
 
-       blk_start_plug(&plug);
-
        /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
        if (filp->f_flags & O_DIRECT) {
                loff_t size;
@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                        retval = filemap_write_and_wait_range(mapping, pos,
                                        pos + iov_length(iov, nr_segs) - 1);
                        if (!retval) {
+                               struct blk_plug plug;
+
+                               blk_start_plug(&plug);
                                retval = mapping->a_ops->direct_IO(READ, iocb,
                                                        iov, pos, nr_segs);
+                               blk_finish_plug(&plug);
                        }
                        if (retval > 0) {
                                *ppos = pos + retval;
@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                        break;
        }
 out:
-       blk_finish_plug(&plug);
        return retval;
 }
 EXPORT_SYMBOL(generic_file_aio_read);
index f91b2f687343315741c9519670a96435329390f1..a4eb3113222912c9aada14bd92c6b68d01577b73 100644 (file)
@@ -263,7 +263,12 @@ found:
                                                        xip_pfn);
                if (err == -ENOMEM)
                        return VM_FAULT_OOM;
-               BUG_ON(err);
+               /*
+                * err == -EBUSY is fine, we've raced against another thread
+                * that faulted-in the same page
+                */
+               if (err != -EBUSY)
+                       BUG_ON(err);
                return VM_FAULT_NOPAGE;
        } else {
                int err, ret = VM_FAULT_OOM;
index b3ffc21ce8010b9de9c92004e2a364326af8dc1b..91d3efb25d15472332e1f2d9c382a5732629ce69 100644 (file)
@@ -2083,7 +2083,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)
 {
        struct mm_struct *mm = mm_slot->mm;
 
-       VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+       VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
 
        if (khugepaged_test_exit(mm)) {
                /* free mm_slot */
@@ -2113,7 +2113,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
        int progress = 0;
 
        VM_BUG_ON(!pages);
-       VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+       VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
 
        if (khugepaged_scan.mm_slot)
                mm_slot = khugepaged_scan.mm_slot;
index ea8c3a4cd2ae8acdf52a7a4e862e277f2390c265..5f34bd8dda34bbc8224303ad080103f224fa5ad6 100644 (file)
@@ -2508,6 +2508,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 {
        struct hstate *h = hstate_vma(vma);
        int ret = VM_FAULT_SIGBUS;
+       int anon_rmap = 0;
        pgoff_t idx;
        unsigned long size;
        struct page *page;
@@ -2562,14 +2563,13 @@ retry:
                        spin_lock(&inode->i_lock);
                        inode->i_blocks += blocks_per_huge_page(h);
                        spin_unlock(&inode->i_lock);
-                       page_dup_rmap(page);
                } else {
                        lock_page(page);
                        if (unlikely(anon_vma_prepare(vma))) {
                                ret = VM_FAULT_OOM;
                                goto backout_unlocked;
                        }
-                       hugepage_add_new_anon_rmap(page, vma, address);
+                       anon_rmap = 1;
                }
        } else {
                /*
@@ -2582,7 +2582,6 @@ retry:
                              VM_FAULT_SET_HINDEX(h - hstates);
                        goto backout_unlocked;
                }
-               page_dup_rmap(page);
        }
 
        /*
@@ -2606,6 +2605,10 @@ retry:
        if (!huge_pte_none(huge_ptep_get(ptep)))
                goto backout;
 
+       if (anon_rmap)
+               hugepage_add_new_anon_rmap(page, vma, address);
+       else
+               page_dup_rmap(page);
        new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
                                && (vma->vm_flags & VM_SHARED)));
        set_huge_pte_at(mm, address, ptep, new_pte);
index c833addd94d74703a90e9bed51d759726e77f280..45eb6217bf38e764bfb65d90f29ae2bb46f77886 100644 (file)
@@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
        pr_debug("%s(0x%p)\n", __func__, ptr);
 
-       if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+       if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr))
                add_scan_area((unsigned long)ptr, size, gfp);
        else if (atomic_read(&kmemleak_early_log))
                log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
@@ -1757,6 +1757,7 @@ void __init kmemleak_init(void)
 
 #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
        if (!kmemleak_skip_disable) {
+               atomic_set(&kmemleak_early_log, 0);
                kmemleak_disable();
                return;
        }
index 2f55f19b7c86517bb5b23680c1b062f7efe2795a..77b5f227e1d86d9228ae6a67f52f18418a2beb98 100644 (file)
@@ -106,14 +106,17 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
        if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
                end = memblock.current_limit;
 
-       /* adjust @start to avoid underflow and allocating the first page */
-       start = max3(start, size, (phys_addr_t)PAGE_SIZE);
+       /* avoid allocating the first page */
+       start = max_t(phys_addr_t, start, PAGE_SIZE);
        end = max(start, end);
 
        for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
                this_start = clamp(this_start, start, end);
                this_end = clamp(this_end, start, end);
 
+               if (this_end < size)
+                       continue;
+
                cand = round_down(this_end - size, align);
                if (cand >= this_start)
                        return cand;
index 602207be985379f7e15e94ea546b8d70b0b2a7b9..6728a7ae6f2d1eb42c8ac183ec69098aa80d2d6c 100644 (file)
@@ -373,14 +373,13 @@ static void mem_cgroup_put(struct mem_cgroup *memcg);
 
 /* Writing them here to avoid exposing memcg's inner layout */
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
-#ifdef CONFIG_INET
 #include <net/sock.h>
 #include <net/ip.h>
 
 static bool mem_cgroup_is_root(struct mem_cgroup *memcg);
 void sock_update_memcg(struct sock *sk)
 {
-       if (static_branch(&memcg_socket_limit_enabled)) {
+       if (mem_cgroup_sockets_enabled) {
                struct mem_cgroup *memcg;
 
                BUG_ON(!sk->sk_prot->proto_cgroup);
@@ -412,7 +411,7 @@ EXPORT_SYMBOL(sock_update_memcg);
 
 void sock_release_memcg(struct sock *sk)
 {
-       if (static_branch(&memcg_socket_limit_enabled) && sk->sk_cgrp) {
+       if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
                struct mem_cgroup *memcg;
                WARN_ON(!sk->sk_cgrp->memcg);
                memcg = sk->sk_cgrp->memcg;
@@ -420,6 +419,7 @@ void sock_release_memcg(struct sock *sk)
        }
 }
 
+#ifdef CONFIG_INET
 struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg)
 {
        if (!memcg || mem_cgroup_is_root(memcg))
@@ -776,7 +776,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
        /* threshold event is triggered in finer grain than soft limit */
        if (unlikely(mem_cgroup_event_ratelimit(memcg,
                                                MEM_CGROUP_TARGET_THRESH))) {
-               bool do_softlimit, do_numainfo;
+               bool do_softlimit;
+               bool do_numainfo __maybe_unused;
 
                do_softlimit = mem_cgroup_event_ratelimit(memcg,
                                                MEM_CGROUP_TARGET_SOFTLIMIT);
@@ -3247,7 +3248,7 @@ int mem_cgroup_prepare_migration(struct page *page,
                ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
        else
                ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-       __mem_cgroup_commit_charge(memcg, page, 1, pc, ctype);
+       __mem_cgroup_commit_charge(memcg, newpage, 1, pc, ctype);
        return ret;
 }
 
index 5e30583c2605d7b791d907ae8a5e07be2d9ad5b6..fa2f04e0337c437e739e75a683ff5b80a070a95a 100644 (file)
@@ -878,15 +878,24 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                        }
                        if (likely(!non_swap_entry(entry)))
                                rss[MM_SWAPENTS]++;
-                       else if (is_write_migration_entry(entry) &&
-                                       is_cow_mapping(vm_flags)) {
-                               /*
-                                * COW mappings require pages in both parent
-                                * and child to be set to read.
-                                */
-                               make_migration_entry_read(&entry);
-                               pte = swp_entry_to_pte(entry);
-                               set_pte_at(src_mm, addr, src_pte, pte);
+                       else if (is_migration_entry(entry)) {
+                               page = migration_entry_to_page(entry);
+
+                               if (PageAnon(page))
+                                       rss[MM_ANONPAGES]++;
+                               else
+                                       rss[MM_FILEPAGES]++;
+
+                               if (is_write_migration_entry(entry) &&
+                                   is_cow_mapping(vm_flags)) {
+                                       /*
+                                        * COW mappings require pages in both
+                                        * parent and child to be set to read.
+                                        */
+                                       make_migration_entry_read(&entry);
+                                       pte = swp_entry_to_pte(entry);
+                                       set_pte_at(src_mm, addr, src_pte, pte);
+                               }
                        }
                }
                goto out_set_pte;
@@ -1191,6 +1200,16 @@ again:
 
                        if (!non_swap_entry(entry))
                                rss[MM_SWAPENTS]--;
+                       else if (is_migration_entry(entry)) {
+                               struct page *page;
+
+                               page = migration_entry_to_page(entry);
+
+                               if (PageAnon(page))
+                                       rss[MM_ANONPAGES]--;
+                               else
+                                       rss[MM_FILEPAGES]--;
+                       }
                        if (unlikely(!free_swap_and_cache(entry)))
                                print_bad_pte(vma, addr, ptent, NULL);
                }
index 9871a56d82c30b1390ea268fddd9b3bc4b83c8da..df141f60289eef61c7d278080e8290c3dfc717b9 100644 (file)
@@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page)
        ClearPageSwapCache(page);
        ClearPagePrivate(page);
        set_page_private(page, 0);
-       page->mapping = NULL;
 
        /*
         * If any waiters have accumulated on the new page then
@@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
        } else {
                if (remap_swapcache)
                        remove_migration_ptes(page, newpage);
+               page->mapping = NULL;
        }
 
        unlock_page(newpage);
index 0027d8f4a1bb8b1423f42e4d52cb3547debc315f..a13ded1938f0bacd90a438d983e3d301a649bfe9 100644 (file)
@@ -5236,6 +5236,7 @@ void *__init alloc_large_system_hash(const char *tablename,
                max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
                do_div(max, bucketsize);
        }
+       max = min(max, 0x80000000ULL);
 
        if (numentries > max)
                numentries = max;
@@ -5413,7 +5414,25 @@ __count_immobile_pages(struct zone *zone, struct page *page, int count)
 
 bool is_pageblock_removable_nolock(struct page *page)
 {
-       struct zone *zone = page_zone(page);
+       struct zone *zone;
+       unsigned long pfn;
+
+       /*
+        * We have to be careful here because we are iterating over memory
+        * sections which are not zone aware so we might end up outside of
+        * the zone but still within the section.
+        * We have to take care about the node as well. If the node is offline
+        * its NODE_DATA will be NULL - see page_zone.
+        */
+       if (!node_online(page_to_nid(page)))
+               return false;
+
+       zone = page_zone(page);
+       pfn = page_to_pfn(page);
+       if (zone->zone_start_pfn > pfn ||
+                       zone->zone_start_pfn + zone->spanned_pages <= pfn)
+               return false;
+
        return __count_immobile_pages(zone, page, 0);
 }
 
index e920aa3ce104c35b902e8412864c78102fa3177e..c20ff48994c29050953c79fcdb0633e690bb653e 100644 (file)
@@ -298,23 +298,18 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec,
                goto free_proc_pages;
        }
 
-       task_lock(task);
-       if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
-               task_unlock(task);
-               rc = -EPERM;
-               goto put_task_struct;
-       }
-       mm = task->mm;
-
-       if (!mm || (task->flags & PF_KTHREAD)) {
-               task_unlock(task);
-               rc = -EINVAL;
+       mm = mm_access(task, PTRACE_MODE_ATTACH);
+       if (!mm || IS_ERR(mm)) {
+               rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
+               /*
+                * Explicitly map EACCES to EPERM as EPERM is a more a
+                * appropriate error code for process_vw_readv/writev
+                */
+               if (rc == -EACCES)
+                       rc = -EPERM;
                goto put_task_struct;
        }
 
-       atomic_inc(&mm->mm_users);
-       task_unlock(task);
-
        for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) {
                rc = process_vm_rw_single_vec(
                        (unsigned long)rvec[i].iov_base, rvec[i].iov_len,
index feead1943d927f6c2660791bab30a370c3f8027c..269d049294abca49b518f158ef7e65fd7cb2547e 100644 (file)
@@ -379,7 +379,7 @@ static int shmem_free_swap(struct address_space *mapping,
 /*
  * Pagevec may contain swap entries, so shuffle up pages before releasing.
  */
-static void shmem_pagevec_release(struct pagevec *pvec)
+static void shmem_deswap_pagevec(struct pagevec *pvec)
 {
        int i, j;
 
@@ -389,7 +389,36 @@ static void shmem_pagevec_release(struct pagevec *pvec)
                        pvec->pages[j++] = page;
        }
        pvec->nr = j;
-       pagevec_release(pvec);
+}
+
+/*
+ * SysV IPC SHM_UNLOCK restore Unevictable pages to their evictable lists.
+ */
+void shmem_unlock_mapping(struct address_space *mapping)
+{
+       struct pagevec pvec;
+       pgoff_t indices[PAGEVEC_SIZE];
+       pgoff_t index = 0;
+
+       pagevec_init(&pvec, 0);
+       /*
+        * Minor point, but we might as well stop if someone else SHM_LOCKs it.
+        */
+       while (!mapping_unevictable(mapping)) {
+               /*
+                * Avoid pagevec_lookup(): find_get_pages() returns 0 as if it
+                * has finished, if it hits a row of PAGEVEC_SIZE swap entries.
+                */
+               pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
+                                       PAGEVEC_SIZE, pvec.pages, indices);
+               if (!pvec.nr)
+                       break;
+               index = indices[pvec.nr - 1] + 1;
+               shmem_deswap_pagevec(&pvec);
+               check_move_unevictable_pages(pvec.pages, pvec.nr);
+               pagevec_release(&pvec);
+               cond_resched();
+       }
 }
 
 /*
@@ -440,7 +469,8 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
                        }
                        unlock_page(page);
                }
-               shmem_pagevec_release(&pvec);
+               shmem_deswap_pagevec(&pvec);
+               pagevec_release(&pvec);
                mem_cgroup_uncharge_end();
                cond_resched();
                index++;
@@ -470,7 +500,8 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
                        continue;
                }
                if (index == start && indices[0] > end) {
-                       shmem_pagevec_release(&pvec);
+                       shmem_deswap_pagevec(&pvec);
+                       pagevec_release(&pvec);
                        break;
                }
                mem_cgroup_uncharge_start();
@@ -494,7 +525,8 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
                        }
                        unlock_page(page);
                }
-               shmem_pagevec_release(&pvec);
+               shmem_deswap_pagevec(&pvec);
+               pagevec_release(&pvec);
                mem_cgroup_uncharge_end();
                index++;
        }
@@ -1068,13 +1100,6 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
                user_shm_unlock(inode->i_size, user);
                info->flags &= ~VM_LOCKED;
                mapping_clear_unevictable(file->f_mapping);
-               /*
-                * Ensure that a racing putback_lru_page() can see
-                * the pages of this mapping are evictable when we
-                * skip them due to !PageLRU during the scan.
-                */
-               smp_mb__after_clear_bit();
-               scan_mapping_unevictable_pages(file->f_mapping);
        }
        retval = 0;
 
@@ -2445,6 +2470,10 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
        return 0;
 }
 
+void shmem_unlock_mapping(struct address_space *mapping)
+{
+}
+
 void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 {
        truncate_inode_pages_range(inode->i_mapping, lstart, lend);
index b0f529b38979447d0ec192f8b6434af5bab28e02..fff1ff7fb9ada36fca1be10d33dec593486f50a6 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -659,7 +659,7 @@ void lru_add_page_tail(struct zone* zone,
        VM_BUG_ON(!PageHead(page));
        VM_BUG_ON(PageCompound(page_tail));
        VM_BUG_ON(PageLRU(page_tail));
-       VM_BUG_ON(!spin_is_locked(&zone->lru_lock));
+       VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&zone->lru_lock));
 
        SetPageLRU(page_tail);
 
index 2880396f7953b03476db86957c66a3787b40cb8c..c52b23552659af5bce0038dd6fa7ac10d044be40 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/buffer_head.h> /* for try_to_release_page(),
                                        buffer_heads_over_limit */
 #include <linux/mm_inline.h>
-#include <linux/pagevec.h>
 #include <linux/backing-dev.h>
 #include <linux/rmap.h>
 #include <linux/topology.h>
@@ -661,7 +660,7 @@ redo:
                 * When racing with an mlock or AS_UNEVICTABLE clearing
                 * (page is unlocked) make sure that if the other thread
                 * does not observe our setting of PG_lru and fails
-                * isolation/check_move_unevictable_page,
+                * isolation/check_move_unevictable_pages,
                 * we see PG_mlocked/AS_UNEVICTABLE cleared below and move
                 * the page back to the evictable list.
                 *
@@ -3499,100 +3498,61 @@ int page_evictable(struct page *page, struct vm_area_struct *vma)
        return 1;
 }
 
+#ifdef CONFIG_SHMEM
 /**
- * check_move_unevictable_page - check page for evictability and move to appropriate zone lru list
- * @page: page to check evictability and move to appropriate lru list
- * @zone: zone page is in
+ * check_move_unevictable_pages - check pages for evictability and move to appropriate zone lru list
+ * @pages:     array of pages to check
+ * @nr_pages:  number of pages to check
  *
- * Checks a page for evictability and moves the page to the appropriate
- * zone lru list.
+ * Checks pages for evictability and moves them to the appropriate lru list.
  *
- * Restrictions: zone->lru_lock must be held, page must be on LRU and must
- * have PageUnevictable set.
+ * This function is only used for SysV IPC SHM_UNLOCK.
  */
-static void check_move_unevictable_page(struct page *page, struct zone *zone)
+void check_move_unevictable_pages(struct page **pages, int nr_pages)
 {
        struct lruvec *lruvec;
+       struct zone *zone = NULL;
+       int pgscanned = 0;
+       int pgrescued = 0;
+       int i;
 
-       VM_BUG_ON(PageActive(page));
-retry:
-       ClearPageUnevictable(page);
-       if (page_evictable(page, NULL)) {
-               enum lru_list l = page_lru_base_type(page);
-
-               __dec_zone_state(zone, NR_UNEVICTABLE);
-               lruvec = mem_cgroup_lru_move_lists(zone, page,
-                                                  LRU_UNEVICTABLE, l);
-               list_move(&page->lru, &lruvec->lists[l]);
-               __inc_zone_state(zone, NR_INACTIVE_ANON + l);
-               __count_vm_event(UNEVICTABLE_PGRESCUED);
-       } else {
-               /*
-                * rotate unevictable list
-                */
-               SetPageUnevictable(page);
-               lruvec = mem_cgroup_lru_move_lists(zone, page, LRU_UNEVICTABLE,
-                                                  LRU_UNEVICTABLE);
-               list_move(&page->lru, &lruvec->lists[LRU_UNEVICTABLE]);
-               if (page_evictable(page, NULL))
-                       goto retry;
-       }
-}
-
-/**
- * scan_mapping_unevictable_pages - scan an address space for evictable pages
- * @mapping: struct address_space to scan for evictable pages
- *
- * Scan all pages in mapping.  Check unevictable pages for
- * evictability and move them to the appropriate zone lru list.
- */
-void scan_mapping_unevictable_pages(struct address_space *mapping)
-{
-       pgoff_t next = 0;
-       pgoff_t end   = (i_size_read(mapping->host) + PAGE_CACHE_SIZE - 1) >>
-                        PAGE_CACHE_SHIFT;
-       struct zone *zone;
-       struct pagevec pvec;
-
-       if (mapping->nrpages == 0)
-               return;
-
-       pagevec_init(&pvec, 0);
-       while (next < end &&
-               pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
-               int i;
-               int pg_scanned = 0;
-
-               zone = NULL;
-
-               for (i = 0; i < pagevec_count(&pvec); i++) {
-                       struct page *page = pvec.pages[i];
-                       pgoff_t page_index = page->index;
-                       struct zone *pagezone = page_zone(page);
+       for (i = 0; i < nr_pages; i++) {
+               struct page *page = pages[i];
+               struct zone *pagezone;
 
-                       pg_scanned++;
-                       if (page_index > next)
-                               next = page_index;
-                       next++;
+               pgscanned++;
+               pagezone = page_zone(page);
+               if (pagezone != zone) {
+                       if (zone)
+                               spin_unlock_irq(&zone->lru_lock);
+                       zone = pagezone;
+                       spin_lock_irq(&zone->lru_lock);
+               }
 
-                       if (pagezone != zone) {
-                               if (zone)
-                                       spin_unlock_irq(&zone->lru_lock);
-                               zone = pagezone;
-                               spin_lock_irq(&zone->lru_lock);
-                       }
+               if (!PageLRU(page) || !PageUnevictable(page))
+                       continue;
 
-                       if (PageLRU(page) && PageUnevictable(page))
-                               check_move_unevictable_page(page, zone);
+               if (page_evictable(page, NULL)) {
+                       enum lru_list lru = page_lru_base_type(page);
+
+                       VM_BUG_ON(PageActive(page));
+                       ClearPageUnevictable(page);
+                       __dec_zone_state(zone, NR_UNEVICTABLE);
+                       lruvec = mem_cgroup_lru_move_lists(zone, page,
+                                               LRU_UNEVICTABLE, lru);
+                       list_move(&page->lru, &lruvec->lists[lru]);
+                       __inc_zone_state(zone, NR_INACTIVE_ANON + lru);
+                       pgrescued++;
                }
-               if (zone)
-                       spin_unlock_irq(&zone->lru_lock);
-               pagevec_release(&pvec);
-
-               count_vm_events(UNEVICTABLE_PGSCANNED, pg_scanned);
        }
 
+       if (zone) {
+               __count_vm_events(UNEVICTABLE_PGRESCUED, pgrescued);
+               __count_vm_events(UNEVICTABLE_PGSCANNED, pgscanned);
+               spin_unlock_irq(&zone->lru_lock);
+       }
 }
+#endif /* CONFIG_SHMEM */
 
 static void warn_scan_unevictable_pages(void)
 {
index 845da3ee56a0d3966bdeb5ab627ef3dc49c8dead..9de93714213a1be51542af9f8ff94cc6f3ac9fea 100644 (file)
@@ -55,7 +55,7 @@
 
 #define AUTO_OFF_TIMEOUT 2000
 
-int enable_hs;
+bool enable_hs;
 
 static void hci_rx_work(struct work_struct *work);
 static void hci_cmd_work(struct work_struct *work);
index f963f6b1884fd96dc12a96743a2f04669194cb3a..5ba0c844d508cbe549788e2219b4dd9ab1383149 100644 (file)
@@ -146,7 +146,7 @@ void br_fdb_cleanup(unsigned long _data)
        unsigned long next_timer = jiffies + br->ageing_time;
        int i;
 
-       spin_lock_bh(&br->hash_lock);
+       spin_lock(&br->hash_lock);
        for (i = 0; i < BR_HASH_SIZE; i++) {
                struct net_bridge_fdb_entry *f;
                struct hlist_node *h, *n;
@@ -162,7 +162,7 @@ void br_fdb_cleanup(unsigned long _data)
                                next_timer = this_timer;
                }
        }
-       spin_unlock_bh(&br->hash_lock);
+       spin_unlock(&br->hash_lock);
 
        mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
 }
index 61570ee76fe6eca7824431663917a32827c90c9b..82c57069415fe6644b1c64eff665846b87c63f7a 100644 (file)
@@ -59,8 +59,6 @@ struct cfcnfg *get_cfcnfg(struct net *net)
 {
        struct caif_net *caifn;
        caifn = net_generic(net, caif_net_id);
-       if (!caifn)
-               return NULL;
        return caifn->cfg;
 }
 EXPORT_SYMBOL(get_cfcnfg);
@@ -69,8 +67,6 @@ static struct caif_device_entry_list *caif_device_list(struct net *net)
 {
        struct caif_net *caifn;
        caifn = net_generic(net, caif_net_id);
-       if (!caifn)
-               return NULL;
        return &caifn->caifdevs;
 }
 
@@ -99,8 +95,6 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
        struct caif_device_entry *caifd;
 
        caifdevs = caif_device_list(dev_net(dev));
-       if (!caifdevs)
-               return NULL;
 
        caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
        if (!caifd)
@@ -120,8 +114,6 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
        struct caif_device_entry_list *caifdevs =
            caif_device_list(dev_net(dev));
        struct caif_device_entry *caifd;
-       if (!caifdevs)
-               return NULL;
 
        list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
                if (caifd->netdev == dev)
@@ -146,15 +138,17 @@ void caif_flow_cb(struct sk_buff *skb)
        spin_lock_bh(&caifd->flow_lock);
        send_xoff = caifd->xoff;
        caifd->xoff = 0;
-       if (!WARN_ON(caifd->xoff_skb_dtor == NULL)) {
-               WARN_ON(caifd->xoff_skb != skb);
-               dtor = caifd->xoff_skb_dtor;
-               caifd->xoff_skb = NULL;
-               caifd->xoff_skb_dtor = NULL;
-       }
+       dtor = caifd->xoff_skb_dtor;
+
+       if (WARN_ON(caifd->xoff_skb != skb))
+               skb = NULL;
+
+       caifd->xoff_skb = NULL;
+       caifd->xoff_skb_dtor = NULL;
+
        spin_unlock_bh(&caifd->flow_lock);
 
-       if (dtor)
+       if (dtor && skb)
                dtor(skb);
 
        if (send_xoff)
@@ -319,8 +313,6 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
        struct caif_device_entry_list *caifdevs;
 
        caifdevs = caif_device_list(dev_net(dev));
-       if (!cfg || !caifdevs)
-               return;
        caifd = caif_device_alloc(dev);
        if (!caifd)
                return;
@@ -372,8 +364,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
 
        cfg = get_cfcnfg(dev_net(dev));
        caifdevs = caif_device_list(dev_net(dev));
-       if (!cfg || !caifdevs)
-               return 0;
 
        caifd = caif_get(dev);
        if (caifd == NULL && dev->type != ARPHRD_CAIF)
@@ -505,9 +495,6 @@ static struct notifier_block caif_device_notifier = {
 static int caif_init_net(struct net *net)
 {
        struct caif_net *caifn = net_generic(net, caif_net_id);
-       if (WARN_ON(!caifn))
-               return -EINVAL;
-
        INIT_LIST_HEAD(&caifn->caifdevs.list);
        mutex_init(&caifn->caifdevs.lock);
 
@@ -525,9 +512,6 @@ static void caif_exit_net(struct net *net)
            caif_device_list(net);
        struct cfcnfg *cfg =  get_cfcnfg(net);
 
-       if (!cfg || !caifdevs)
-               return;
-
        rtnl_lock();
        mutex_lock(&caifdevs->lock);
 
@@ -567,7 +551,7 @@ static int __init caif_device_init(void)
 {
        int result;
 
-       result = register_pernet_device(&caif_net_ops);
+       result = register_pernet_subsys(&caif_net_ops);
 
        if (result)
                return result;
@@ -580,7 +564,7 @@ static int __init caif_device_init(void)
 
 static void __exit caif_device_exit(void)
 {
-       unregister_pernet_device(&caif_net_ops);
+       unregister_pernet_subsys(&caif_net_ops);
        unregister_netdevice_notifier(&caif_device_notifier);
        dev_remove_pack(&caif_packet_type);
 }
index a986280864523d431e8f30f96af1a346abe2b784..a97d97a3a512706a2e37ecf873407f9b87482409 100644 (file)
@@ -539,8 +539,10 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,
        pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
        memset(skb->cb, 0, sizeof(struct caif_payload_info));
 
-       if (cf_sk->layer.dn == NULL)
+       if (cf_sk->layer.dn == NULL) {
+               kfree_skb(skb);
                return -EINVAL;
+       }
 
        return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
 }
@@ -683,10 +685,10 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
                }
                err = transmit_skb(skb, cf_sk,
                                msg->msg_flags&MSG_DONTWAIT, timeo);
-               if (err < 0) {
-                       kfree_skb(skb);
+               if (err < 0)
+                       /* skb is already freed */
                        goto pipe_err;
-               }
+
                sent += size;
        }
 
index 5fc9eca8cd4149b2cc102ea32b0ae131db4e8452..fd7cbf5aa8956732f51637eeab3f512e00743fcb 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/slab.h>
-#include <linux/netdevice.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/usb/usbnet.h>
@@ -27,7 +26,7 @@ MODULE_LICENSE("GPL");
 #define CFUSB_ALIGNMENT 4      /* Number of bytes to align. */
 #define CFUSB_MAX_HEADLEN (CFUSB_PAD_DESCR_SZ + CFUSB_ALIGNMENT-1)
 #define STE_USB_VID 0x04cc     /* USB Product ID for ST-Ericsson */
-#define STE_USB_PID_CAIF 0x2306        /* Product id for CAIF Modems */
+#define STE_USB_PID_CAIF 0x230f        /* Product id for CAIF Modems */
 
 struct cfusbl {
        struct cflayer layer;
index 598aafb4cb5169e799148ffd6b33d351b702be7d..ba9cfd47778aa808ff35939458f8c59a52e71a56 100644 (file)
@@ -309,7 +309,6 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
        int err;
        struct cfctrl_link_param param;
        struct cfcnfg *cfg = get_cfcnfg(net);
-       caif_assert(cfg != NULL);
 
        rcu_read_lock();
        err = caif_connect_req_to_link_param(cfg, conn_req, &param);
index b36f24a4c8e74951f07bb06f2dfd6b6c3f81bfa4..94b08612a4d8d76e7056cef299ea58f6b38598d6 100644 (file)
@@ -248,7 +248,6 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
 {
        struct cfmuxl *muxl = container_obj(layr);
        struct cflayer *layer;
-       int idx;
 
        rcu_read_lock();
        list_for_each_entry_rcu(layer, &muxl->srvl_list, node) {
@@ -257,14 +256,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
 
                        if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND ||
                                ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) &&
-                                       layer->id != 0) {
-
-                               idx = layer->id % UP_CACHE_SIZE;
-                               spin_lock_bh(&muxl->receive_lock);
-                               RCU_INIT_POINTER(muxl->up_cache[idx], NULL);
-                               list_del_rcu(&layer->node);
-                               spin_unlock_bh(&muxl->receive_lock);
-                       }
+                                       layer->id != 0)
+                               cfmuxl_remove_uplayer(layr, layer->id);
+
                        /* NOTE: ctrlcmd is not allowed to block */
                        layer->ctrlcmd(layer, ctrl, phyid);
                }
index 97f70e50ad3bb4ed806534fbc74d8a5230000acf..761ad9d6cc3b12fc4d6d8c10022e4c877559f5c8 100644 (file)
@@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
        } else {
                pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
                memcpy(&client->fsid, fsid, sizeof(*fsid));
-               ceph_debugfs_client_init(client);
-               client->have_fsid = true;
        }
        return 0;
 }
index 0b62deae42bd88930f408e0473f13c11b0c252bd..1845cde2622740162fdb5e42a7663072d072ebf8 100644 (file)
@@ -8,8 +8,8 @@
 
 #include <linux/ceph/mon_client.h>
 #include <linux/ceph/libceph.h>
+#include <linux/ceph/debugfs.h>
 #include <linux/ceph/decode.h>
-
 #include <linux/ceph/auth.h>
 
 /*
@@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
        client->monc.monmap = monmap;
        kfree(old);
 
+       if (!client->have_fsid) {
+               client->have_fsid = true;
+               mutex_unlock(&monc->mutex);
+               /*
+                * do debugfs initialization without mutex to avoid
+                * creating a locking dependency
+                */
+               ceph_debugfs_client_init(client);
+               goto out_unlocked;
+       }
 out:
        mutex_unlock(&monc->mutex);
+out_unlocked:
        wake_up_all(&client->auth_wq);
 }
 
index f494675471a91b7f093665e6098ee7b3a91e6e4e..6ca32f6b3105da687bb03e951ac8cb91224b3268 100644 (file)
@@ -1887,6 +1887,23 @@ void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
 EXPORT_SYMBOL(skb_set_dev);
 #endif /* CONFIG_NET_NS */
 
+static void skb_warn_bad_offload(const struct sk_buff *skb)
+{
+       static const netdev_features_t null_features = 0;
+       struct net_device *dev = skb->dev;
+       const char *driver = "";
+
+       if (dev && dev->dev.parent)
+               driver = dev_driver_string(dev->dev.parent);
+
+       WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d gso_size=%d "
+            "gso_type=%d ip_summed=%d\n",
+            driver, dev ? &dev->features : &null_features,
+            skb->sk ? &skb->sk->sk_route_caps : &null_features,
+            skb->len, skb->data_len, skb_shinfo(skb)->gso_size,
+            skb_shinfo(skb)->gso_type, skb->ip_summed);
+}
+
 /*
  * Invalidate hardware checksum when packet is to be mangled, and
  * complete checksum manually on outgoing path.
@@ -1900,8 +1917,8 @@ int skb_checksum_help(struct sk_buff *skb)
                goto out_set_summed;
 
        if (unlikely(skb_shinfo(skb)->gso_size)) {
-               /* Let GSO fix up the checksum. */
-               goto out_set_summed;
+               skb_warn_bad_offload(skb);
+               return -EINVAL;
        }
 
        offset = skb_checksum_start_offset(skb);
@@ -1961,16 +1978,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
        __skb_pull(skb, skb->mac_len);
 
        if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
-               struct net_device *dev = skb->dev;
-               struct ethtool_drvinfo info = {};
-
-               if (dev && dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
-                       dev->ethtool_ops->get_drvinfo(dev, &info);
-
-               WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d ip_summed=%d\n",
-                    info.driver, dev ? &dev->features : NULL,
-                    skb->sk ? &skb->sk->sk_route_caps : NULL,
-                    skb->len, skb->data_len, skb->ip_summed);
+               skb_warn_bad_offload(skb);
 
                if (skb_header_cloned(skb) &&
                    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
@@ -3492,14 +3500,20 @@ static inline gro_result_t
 __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff *p;
+       unsigned int maclen = skb->dev->hard_header_len;
 
        for (p = napi->gro_list; p; p = p->next) {
                unsigned long diffs;
 
                diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
                diffs |= p->vlan_tci ^ skb->vlan_tci;
-               diffs |= compare_ether_header(skb_mac_header(p),
-                                             skb_gro_mac_header(skb));
+               if (maclen == ETH_HLEN)
+                       diffs |= compare_ether_header(skb_mac_header(p),
+                                                     skb_gro_mac_header(skb));
+               else if (!diffs)
+                       diffs = memcmp(skb_mac_header(p),
+                                      skb_gro_mac_header(skb),
+                                      maclen);
                NAPI_GRO_CB(p)->same_flow = !diffs;
                NAPI_GRO_CB(p)->flush = 0;
        }
index 921aa2b4b4158ab1aefab67c474a58065d43c77f..3f79db1b612a6f1042c3eb0e98e980c62e8d2c02 100644 (file)
@@ -1190,6 +1190,8 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev,
        if (!dev->ethtool_ops->flash_device)
                return -EOPNOTSUPP;
 
+       efl.data[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
+
        return dev->ethtool_ops->flash_device(dev, &efl);
 }
 
@@ -1311,6 +1313,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
        case ETHTOOL_GRXCSUM:
        case ETHTOOL_GTXCSUM:
        case ETHTOOL_GSG:
+       case ETHTOOL_GSSET_INFO:
        case ETHTOOL_GSTRINGS:
        case ETHTOOL_GTSO:
        case ETHTOOL_GPERMADDR:
index 0985b9b14b804737888a59591d242a550ddc0556..a225089df5b6693a715f95ab89de71be4a400338 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/skbuff.h>
+#include <linux/export.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/if_vlan.h>
index f3dbd4f596a4904a99650d18ae73c9a963126aa8..a1727cda03d7bec9b565de4647dd3cff754fcbe8 100644 (file)
@@ -929,7 +929,7 @@ static ssize_t bql_show_inflight(struct netdev_queue *queue,
 }
 
 static struct netdev_queue_attribute bql_inflight_attribute =
-       __ATTR(inflight, S_IRUGO | S_IWUSR, bql_show_inflight, NULL);
+       __ATTR(inflight, S_IRUGO, bql_show_inflight, NULL);
 
 #define BQL_ATTR(NAME, FIELD)                                          \
 static ssize_t bql_show_ ## NAME(struct netdev_queue *queue,           \
index aefcd7acbffa9ff0ae028cc0d5cb2eb662ced477..0e950fda9a0abc88ffaa9e3e62b2a11c023a7b8b 100644 (file)
@@ -30,6 +30,20 @@ EXPORT_SYMBOL(init_net);
 
 #define INITIAL_NET_GEN_PTRS   13 /* +1 for len +2 for rcu_head */
 
+static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
+
+static struct net_generic *net_alloc_generic(void)
+{
+       struct net_generic *ng;
+       size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
+
+       ng = kzalloc(generic_size, GFP_KERNEL);
+       if (ng)
+               ng->len = max_gen_ptrs;
+
+       return ng;
+}
+
 static int net_assign_generic(struct net *net, int id, void *data)
 {
        struct net_generic *ng, *old_ng;
@@ -43,8 +57,7 @@ static int net_assign_generic(struct net *net, int id, void *data)
        if (old_ng->len >= id)
                goto assign;
 
-       ng = kzalloc(sizeof(struct net_generic) +
-                       id * sizeof(void *), GFP_KERNEL);
+       ng = net_alloc_generic();
        if (ng == NULL)
                return -ENOMEM;
 
@@ -59,7 +72,6 @@ static int net_assign_generic(struct net *net, int id, void *data)
         * the old copy for kfree after a grace period.
         */
 
-       ng->len = id;
        memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
 
        rcu_assign_pointer(net->gen, ng);
@@ -161,18 +173,6 @@ out_undo:
        goto out;
 }
 
-static struct net_generic *net_alloc_generic(void)
-{
-       struct net_generic *ng;
-       size_t generic_size = sizeof(struct net_generic) +
-               INITIAL_NET_GEN_PTRS * sizeof(void *);
-
-       ng = kzalloc(generic_size, GFP_KERNEL);
-       if (ng)
-               ng->len = INITIAL_NET_GEN_PTRS;
-
-       return ng;
-}
 
 #ifdef CONFIG_NET_NS
 static struct kmem_cache *net_cachep;
@@ -483,6 +483,7 @@ again:
                        }
                        return error;
                }
+               max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
        }
        error = __register_pernet_operations(list, ops);
        if (error) {
index 556b082986696d8b80b09c4f687cff23bc540a45..ddefc513b44a6faf99a7878f6fe651147feaa0cc 100644 (file)
@@ -194,7 +194,7 @@ static void netpoll_poll_dev(struct net_device *dev)
 
        poll_napi(dev);
 
-       if (dev->priv_flags & IFF_SLAVE) {
+       if (dev->flags & IFF_SLAVE) {
                if (dev->npinfo) {
                        struct net_device *bond_dev = dev->master;
                        struct sk_buff *skb;
index 3a9fd4826b75da9c6c11157f17db2c4d04f76bd5..4dacc44637ef8b908d339ab4898cbcf86eb817b9 100644 (file)
@@ -58,11 +58,12 @@ static int get_prioidx(u32 *prio)
 
        spin_lock_irqsave(&prioidx_map_lock, flags);
        prioidx = find_first_zero_bit(prioidx_map, sizeof(unsigned long) * PRIOIDX_SZ);
+       if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ) {
+               spin_unlock_irqrestore(&prioidx_map_lock, flags);
+               return -ENOSPC;
+       }
        set_bit(prioidx, prioidx_map);
        spin_unlock_irqrestore(&prioidx_map_lock, flags);
-       if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ)
-               return -ENOSPC;
-
        atomic_set(&max_prioidx, prioidx);
        *prio = prioidx;
        return 0;
@@ -107,7 +108,7 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)
 static void update_netdev_tables(void)
 {
        struct net_device *dev;
-       u32 max_len = atomic_read(&max_prioidx);
+       u32 max_len = atomic_read(&max_prioidx) + 1;
        struct netprio_map *map;
 
        rtnl_lock();
@@ -270,7 +271,6 @@ static int netprio_device_event(struct notifier_block *unused,
 {
        struct net_device *dev = ptr;
        struct netprio_map *old;
-       u32 max_len = atomic_read(&max_prioidx);
 
        /*
         * Note this is called with rtnl_lock held so we have update side
@@ -278,11 +278,6 @@ static int netprio_device_event(struct notifier_block *unused,
         */
 
        switch (event) {
-
-       case NETDEV_REGISTER:
-               if (max_len)
-                       extend_netdev_table(dev, max_len);
-               break;
        case NETDEV_UNREGISTER:
                old = rtnl_dereference(dev->priomap);
                RCU_INIT_POINTER(dev->priomap, NULL);
index 65f80c7b1656b81fd5646c8caf24016ce3782ffa..4d8ce93cd5039b191b468fcb87f23ee0457c5cc4 100644 (file)
@@ -767,8 +767,8 @@ done:
        return i;
 }
 
-static unsigned long num_arg(const char __user * user_buffer,
-                            unsigned long maxlen, unsigned long *num)
+static long num_arg(const char __user *user_buffer, unsigned long maxlen,
+                               unsigned long *num)
 {
        int i;
        *num = 0;
index f16444bc6cbb1ca25e57df0d18e7d267ceedf1f9..65aebd45002786f4c00f6a5b4bc6ac45026f7f86 100644 (file)
@@ -1509,6 +1509,9 @@ errout:
 
        if (send_addr_notify)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+       min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev),
+                                    min_ifinfo_dump_size);
+
        return err;
 }
 
index 6fd44606fdd130a12712ac3f67ea6f92befab574..99b2596531bbc2a9a714bf262a8c79c61f1726b5 100644 (file)
@@ -46,7 +46,7 @@ __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
 
        memcpy(hash, saddr, 16);
        for (i = 0; i < 4; i++)
-               secret[i] = net_secret[i] + daddr[i];
+               secret[i] = net_secret[i] + (__force u32)daddr[i];
        secret[4] = net_secret[4] +
                (((__force u16)sport << 16) + (__force u16)dport);
        for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
index 5c5af9988f941c9ee4eef4769127d3ce21f2f8cd..02f8dfe320b771ee96ba3bb5bae52b2974608bd8 100644 (file)
@@ -1171,13 +1171,10 @@ EXPORT_SYMBOL(sock_update_classid);
 
 void sock_update_netprioidx(struct sock *sk)
 {
-       struct cgroup_netprio_state *state;
        if (in_interrupt())
                return;
-       rcu_read_lock();
-       state = task_netprio_state(current);
-       sk->sk_cgrp_prioidx = state ? state->prioidx : 0;
-       rcu_read_unlock();
+
+       sk->sk_cgrp_prioidx = task_netprioidx(current);
 }
 EXPORT_SYMBOL_GPL(sock_update_netprioidx);
 #endif
@@ -1827,7 +1824,7 @@ suppress_allocation:
        /* Alas. Undo changes. */
        sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
 
-       sk_memory_allocated_sub(sk, amt, parent_status);
+       sk_memory_allocated_sub(sk, amt);
 
        return 0;
 }
@@ -1840,7 +1837,7 @@ EXPORT_SYMBOL(__sk_mem_schedule);
 void __sk_mem_reclaim(struct sock *sk)
 {
        sk_memory_allocated_sub(sk,
-                               sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, 0);
+                               sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT);
        sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
 
        if (sk_under_memory_pressure(sk) &&
index aa2a2c79776f897e31456c27acd81896c7607ced..d183262943d9fcb25e3b31a44857d27fe6447818 100644 (file)
@@ -409,7 +409,7 @@ config INET_TCP_DIAG
 
 config INET_UDP_DIAG
        tristate "UDP: socket monitoring interface"
-       depends on INET_DIAG
+       depends on INET_DIAG && (IPV6 || IPV6=n)
        default n
        ---help---
          Support for UDP socket monitoring interface used by the ss tool.
index 59402be133f0b4cced6dac7d22fea61fcf89dda6..63e49890ad31df807d50c93a9618622dab2c2103 100644 (file)
@@ -863,7 +863,8 @@ static int arp_process(struct sk_buff *skb)
                        if (addr_type == RTN_UNICAST  &&
                            (arp_fwd_proxy(in_dev, dev, rt) ||
                             arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
-                            pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
+                            (rt->dst.dev != dev &&
+                             pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
                                n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
                                if (n)
                                        neigh_release(n);
index 2e4e24476c4c3ba1b1abb1463ff2f4123180ccad..19d66cefd7d34beae89c617a10f195f2f097770f 100644 (file)
@@ -123,11 +123,14 @@ again:
                                                smallest_size = tb->num_owners;
                                                smallest_rover = rover;
                                                if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
-                                                       spin_unlock(&head->lock);
                                                        snum = smallest_rover;
-                                                       goto have_snum;
+                                                       goto tb_found;
                                                }
                                        }
+                                       if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+                                               snum = rover;
+                                               goto tb_found;
+                                       }
                                        goto next;
                                }
                        break;
index 86f13c67ea8579d32a4f076063ea1777c75e166b..bf4a9c4808e1faaa7461a472f224a4d3c8edf379 100644 (file)
@@ -136,7 +136,7 @@ static int addr_compare(const struct inetpeer_addr *a,
        for (i = 0; i < n; i++) {
                if (a->addr.a6[i] == b->addr.a6[i])
                        continue;
-               if (a->addr.a6[i] < b->addr.a6[i])
+               if ((__force u32)a->addr.a6[i] < (__force u32)b->addr.a6[i])
                        return -1;
                return 1;
        }
@@ -447,6 +447,7 @@ relookup:
                p->rate_last = 0;
                p->pmtu_expires = 0;
                p->pmtu_orig = 0;
+               p->redirect_genid = 0;
                memset(&p->redirect_learned, 0, sizeof(p->redirect_learned));
 
 
index 2b53a1f7abf6bf57509279cff831b7082040e558..6b3ca5ba4450599e15ebe8b3ed5597a51051821f 100644 (file)
@@ -422,6 +422,10 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
        if (register_netdevice(dev) < 0)
                goto failed_free;
 
+       /* Can use a lockless transmit, unless we generate output sequences */
+       if (!(nt->parms.o_flags & GRE_SEQ))
+               dev->features |= NETIF_F_LLTX;
+
        dev_hold(dev);
        ipgre_tunnel_link(ign, nt);
        return nt;
index 1e60f7679075b660f489bcd1a9f462c832c5e77e..42dd1a90edea0916379f41d9722d5b574f7b69e2 100644 (file)
@@ -573,8 +573,8 @@ void ip_forward_options(struct sk_buff *skb)
                }
                if (srrptr + 3 <= srrspace) {
                        opt->is_changed = 1;
-                       ip_rt_get_source(&optptr[srrptr-1], skb, rt);
                        ip_hdr(skb)->daddr = opt->nexthop;
+                       ip_rt_get_source(&optptr[srrptr-1], skb, rt);
                        optptr[2] = srrptr+4;
                } else if (net_ratelimit())
                        printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
index 7e4ec9fc2cef3c38bd0e659a8c36548ff25fe429..6e412a60a91f27acb3ea2241a860c6a18401fed8 100644 (file)
@@ -141,7 +141,7 @@ __be32 ic_servaddr = NONE;  /* Boot server IP address */
 __be32 root_server_addr = NONE;        /* Address of NFS server */
 u8 root_server_path[256] = { 0, };     /* Path to mount as root */
 
-u32 ic_dev_xid;                /* Device under configuration */
+__be32 ic_dev_xid;             /* Device under configuration */
 
 /* vendor class identifier */
 static char vendor_class_identifier[253] __initdata;
@@ -859,9 +859,9 @@ static int __init ic_bootp_string(char *dest, char *src, int len, int max)
  */
 static void __init ic_do_bootp_ext(u8 *ext)
 {
-       u8 servers;
-       int i;
-       u16 mtu;
+       u8 servers;
+       int i;
+       __be16 mtu;
 
 #ifdef IPCONFIG_DEBUG
        u8 *c;
index 43d4c3b223699aee36de3c3c79c6d82b5236a4c0..aea5a199c37a341be3fab08500f1c35a34cbf215 100644 (file)
@@ -140,13 +140,14 @@ static void ping_v4_unhash(struct sock *sk)
                write_lock_bh(&ping_table.lock);
                hlist_nulls_del(&sk->sk_nulls_node);
                sock_put(sk);
-               isk->inet_num = isk->inet_sport = 0;
+               isk->inet_num = 0;
+               isk->inet_sport = 0;
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
                write_unlock_bh(&ping_table.lock);
        }
 }
 
-static struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr,
+static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr,
                                   u16 ident, int dif)
 {
        struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident);
@@ -154,15 +155,15 @@ static struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr,
        struct inet_sock *isk;
        struct hlist_nulls_node *hnode;
 
-       pr_debug("try to find: num = %d, daddr = %ld, dif = %d\n",
-                        (int)ident, (unsigned long)daddr, dif);
+       pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n",
+                        (int)ident, &daddr, dif);
        read_lock_bh(&ping_table.lock);
 
        ping_portaddr_for_each_entry(sk, hnode, hslot) {
                isk = inet_sk(sk);
 
-               pr_debug("found: %p: num = %d, daddr = %ld, dif = %d\n", sk,
-                        (int)isk->inet_num, (unsigned long)isk->inet_rcv_saddr,
+               pr_debug("found: %p: num = %d, daddr = %pI4, dif = %d\n", sk,
+                        (int)isk->inet_num, &isk->inet_rcv_saddr,
                         sk->sk_bound_dev_if);
 
                pr_debug("iterate\n");
@@ -254,7 +255,7 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                sk, addr->sin_addr.s_addr, ntohs(addr->sin_port));
 
        chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
-       if (addr->sin_addr.s_addr == INADDR_ANY)
+       if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
                chk_addr_ret = RTN_LOCAL;
 
        if ((sysctl_ip_nonlocal_bind == 0 &&
@@ -278,9 +279,9 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                goto out;
        }
 
-       pr_debug("after bind(): num = %d, daddr = %ld, dif = %d\n",
+       pr_debug("after bind(): num = %d, daddr = %pI4, dif = %d\n",
                (int)isk->inet_num,
-               (unsigned long) isk->inet_rcv_saddr,
+               &isk->inet_rcv_saddr,
                (int)sk->sk_bound_dev_if);
 
        err = 0;
@@ -407,7 +408,7 @@ out:
 struct pingfakehdr {
        struct icmphdr icmph;
        struct iovec *iov;
-       u32 wcheck;
+       __wsum wcheck;
 };
 
 static int ping_getfrag(void *from, char * to,
@@ -459,7 +460,7 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct rtable *rt = NULL;
        struct ip_options_data opt_copy;
        int free = 0;
-       u32 saddr, daddr, faddr;
+       __be32 saddr, daddr, faddr;
        u8  tos;
        int err;
 
@@ -696,8 +697,8 @@ void ping_rcv(struct sk_buff *skb)
        struct net *net = dev_net(skb->dev);
        struct iphdr *iph = ip_hdr(skb);
        struct icmphdr *icmph = icmp_hdr(skb);
-       u32 saddr = iph->saddr;
-       u32 daddr = iph->daddr;
+       __be32 saddr = iph->saddr;
+       __be32 daddr = iph->daddr;
 
        /* We assume the packet has already been checked by icmp_rcv */
 
index 3569d8ecaeac55e546912729322f1b15160d2c0c..6afc807ee2ad66991f0e41d5a46602c4f3729310 100644 (file)
@@ -216,7 +216,6 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPPartialUndo", LINUX_MIB_TCPPARTIALUNDO),
        SNMP_MIB_ITEM("TCPDSACKUndo", LINUX_MIB_TCPDSACKUNDO),
        SNMP_MIB_ITEM("TCPLossUndo", LINUX_MIB_TCPLOSSUNDO),
-       SNMP_MIB_ITEM("TCPLoss", LINUX_MIB_TCPLOSS),
        SNMP_MIB_ITEM("TCPLostRetransmit", LINUX_MIB_TCPLOSTRETRANSMIT),
        SNMP_MIB_ITEM("TCPRenoFailures", LINUX_MIB_TCPRENOFAILURES),
        SNMP_MIB_ITEM("TCPSackFailures", LINUX_MIB_TCPSACKFAILURES),
index 4aa7e9dc0cbb961ab75fedea9944304a609dd2fc..7a7724da9bff61eb51cb2ad70f8a92c135f1dcfa 100644 (file)
@@ -778,7 +778,6 @@ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
 static __net_init int ipv4_sysctl_init_net(struct net *net)
 {
        struct ctl_table *table;
-       unsigned long limit;
 
        table = ipv4_net_table;
        if (!net_eq(net, &init_net)) {
@@ -814,11 +813,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
 
        net->ipv4.sysctl_rt_cache_rebuild_count = 4;
 
-       limit = nr_free_buffer_pages() / 8;
-       limit = max(limit, 128UL);
-       net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
-       net->ipv4.sysctl_tcp_mem[1] = limit;
-       net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
+       tcp_init_mem(net);
 
        net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
                        net_ipv4_ctl_path, table);
index 9bcdec3ad772171a6aa71584b86bc5c1c998db83..22ef5f9fd2ff2e92dc4955dc9a2ac450d8a435fa 100644 (file)
@@ -1876,6 +1876,20 @@ void tcp_shutdown(struct sock *sk, int how)
 }
 EXPORT_SYMBOL(tcp_shutdown);
 
+bool tcp_check_oom(struct sock *sk, int shift)
+{
+       bool too_many_orphans, out_of_socket_memory;
+
+       too_many_orphans = tcp_too_many_orphans(sk, shift);
+       out_of_socket_memory = tcp_out_of_memory(sk);
+
+       if (too_many_orphans && net_ratelimit())
+               pr_info("TCP: too many orphaned sockets\n");
+       if (out_of_socket_memory && net_ratelimit())
+               pr_info("TCP: out of memory -- consider tuning tcp_mem\n");
+       return too_many_orphans || out_of_socket_memory;
+}
+
 void tcp_close(struct sock *sk, long timeout)
 {
        struct sk_buff *skb;
@@ -2015,10 +2029,7 @@ adjudge_to_death:
        }
        if (sk->sk_state != TCP_CLOSE) {
                sk_mem_reclaim(sk);
-               if (tcp_too_many_orphans(sk, 0)) {
-                       if (net_ratelimit())
-                               printk(KERN_INFO "TCP: too many of orphaned "
-                                      "sockets\n");
+               if (tcp_check_oom(sk, 0)) {
                        tcp_set_state(sk, TCP_CLOSE);
                        tcp_send_active_reset(sk, GFP_ATOMIC);
                        NET_INC_STATS_BH(sock_net(sk),
@@ -3216,11 +3227,21 @@ static int __init set_thash_entries(char *str)
 }
 __setup("thash_entries=", set_thash_entries);
 
+void tcp_init_mem(struct net *net)
+{
+       unsigned long limit = nr_free_buffer_pages() / 8;
+       limit = max(limit, 128UL);
+       net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
+       net->ipv4.sysctl_tcp_mem[1] = limit;
+       net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
+}
+
 void __init tcp_init(void)
 {
        struct sk_buff *skb = NULL;
        unsigned long limit;
-       int i, max_share, cnt;
+       int max_share, cnt;
+       unsigned int i;
        unsigned long jiffy = jiffies;
 
        BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -3263,7 +3284,7 @@ void __init tcp_init(void)
                                        &tcp_hashinfo.bhash_size,
                                        NULL,
                                        64 * 1024);
-       tcp_hashinfo.bhash_size = 1 << tcp_hashinfo.bhash_size;
+       tcp_hashinfo.bhash_size = 1U << tcp_hashinfo.bhash_size;
        for (i = 0; i < tcp_hashinfo.bhash_size; i++) {
                spin_lock_init(&tcp_hashinfo.bhash[i].lock);
                INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
@@ -3276,9 +3297,10 @@ void __init tcp_init(void)
        sysctl_tcp_max_orphans = cnt / 2;
        sysctl_max_syn_backlog = max(128, cnt / 256);
 
+       tcp_init_mem(&init_net);
        /* Set per-socket limits to no more than 1/128 the pressure threshold */
-       limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1])
-               << (PAGE_SHIFT - 7);
+       limit = nr_free_buffer_pages() << (PAGE_SHIFT - 10);
+       limit = max(limit, 128UL);
        max_share = min(4UL*1024*1024, limit);
 
        sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
index 6187eb4d1dcfe1e66dc90a799c50df496c2d8974..f45e1c24244091a750f5f34ca0fe9e9038731ca5 100644 (file)
@@ -63,7 +63,6 @@ static inline void bictcp_reset(struct bictcp *ca)
 {
        ca->cnt = 0;
        ca->last_max_cwnd = 0;
-       ca->loss_cwnd = 0;
        ca->last_cwnd = 0;
        ca->last_time = 0;
        ca->epoch_start = 0;
@@ -72,7 +71,11 @@ static inline void bictcp_reset(struct bictcp *ca)
 
 static void bictcp_init(struct sock *sk)
 {
-       bictcp_reset(inet_csk_ca(sk));
+       struct bictcp *ca = inet_csk_ca(sk);
+
+       bictcp_reset(ca);
+       ca->loss_cwnd = 0;
+
        if (initial_ssthresh)
                tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
 }
@@ -127,7 +130,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
        }
 
        /* if in slow start or link utilization is very low */
-       if (ca->loss_cwnd == 0) {
+       if (ca->last_max_cwnd == 0) {
                if (ca->cnt > 20) /* increase cwnd 5% per RTT */
                        ca->cnt = 20;
        }
@@ -185,7 +188,7 @@ static u32 bictcp_undo_cwnd(struct sock *sk)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        const struct bictcp *ca = inet_csk_ca(sk);
-       return max(tp->snd_cwnd, ca->last_max_cwnd);
+       return max(tp->snd_cwnd, ca->loss_cwnd);
 }
 
 static void bictcp_state(struct sock *sk, u8 new_state)
index f376b05cca818fd9496fe0cb8540a051e3e7e50a..a9077f441cb27b693d8ad1d710e4dba67aa93ebb 100644 (file)
@@ -107,7 +107,6 @@ static inline void bictcp_reset(struct bictcp *ca)
 {
        ca->cnt = 0;
        ca->last_max_cwnd = 0;
-       ca->loss_cwnd = 0;
        ca->last_cwnd = 0;
        ca->last_time = 0;
        ca->bic_origin_point = 0;
@@ -142,7 +141,10 @@ static inline void bictcp_hystart_reset(struct sock *sk)
 
 static void bictcp_init(struct sock *sk)
 {
-       bictcp_reset(inet_csk_ca(sk));
+       struct bictcp *ca = inet_csk_ca(sk);
+
+       bictcp_reset(ca);
+       ca->loss_cwnd = 0;
 
        if (hystart)
                bictcp_hystart_reset(sk);
@@ -275,7 +277,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
         * The initial growth of cubic function may be too conservative
         * when the available bandwidth is still unknown.
         */
-       if (ca->loss_cwnd == 0 && ca->cnt > 20)
+       if (ca->last_max_cwnd == 0 && ca->cnt > 20)
                ca->cnt = 20;   /* increase cwnd 5% per RTT */
 
        /* TCP Friendly */
@@ -342,7 +344,7 @@ static u32 bictcp_undo_cwnd(struct sock *sk)
 {
        struct bictcp *ca = inet_csk_ca(sk);
 
-       return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
+       return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
 }
 
 static void bictcp_state(struct sock *sk, u8 new_state)
index 2877c3e0958777dff87612bb7c057df451f5b57a..53c8ce4046b207cf6dc65735a8a030932095734d 100644 (file)
@@ -105,7 +105,6 @@ int sysctl_tcp_abc __read_mostly;
 #define FLAG_SYN_ACKED         0x10 /* This ACK acknowledged SYN.              */
 #define FLAG_DATA_SACKED       0x20 /* New SACK.                               */
 #define FLAG_ECE               0x40 /* ECE in this ACK                         */
-#define FLAG_DATA_LOST         0x80 /* SACK detected data lossage.             */
 #define FLAG_SLOWPATH          0x100 /* Do not skip RFC checks for window update.*/
 #define FLAG_ONLY_ORIG_SACKED  0x200 /* SACKs only non-rexmit sent before RTO */
 #define FLAG_SND_UNA_ADVANCED  0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
@@ -1040,13 +1039,11 @@ static void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp,
  * These 6 states form finite state machine, controlled by the following events:
  * 1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue())
  * 2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue())
- * 3. Loss detection event of one of three flavors:
+ * 3. Loss detection event of two flavors:
  *     A. Scoreboard estimator decided the packet is lost.
  *        A'. Reno "three dupacks" marks head of queue lost.
- *        A''. Its FACK modfication, head until snd.fack is lost.
- *     B. SACK arrives sacking data transmitted after never retransmitted
- *        hole was sent out.
- *     C. SACK arrives sacking SND.NXT at the moment, when the
+ *        A''. Its FACK modification, head until snd.fack is lost.
+ *     B. SACK arrives sacking SND.NXT at the moment, when the
  *        segment was retransmitted.
  * 4. D-SACK added new rule: D-SACK changes any tag to S.
  *
@@ -1153,7 +1150,7 @@ static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack,
 }
 
 /* Check for lost retransmit. This superb idea is borrowed from "ratehalving".
- * Event "C". Later note: FACK people cheated me again 8), we have to account
+ * Event "B". Later note: FACK people cheated me again 8), we have to account
  * for reordering! Ugly, but should help.
  *
  * Search retransmitted skbs from write_queue that were sent when snd_nxt was
@@ -1310,25 +1307,26 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
        return in_sack;
 }
 
-static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
-                         struct tcp_sacktag_state *state,
+/* Mark the given newly-SACKed range as such, adjusting counters and hints. */
+static u8 tcp_sacktag_one(struct sock *sk,
+                         struct tcp_sacktag_state *state, u8 sacked,
+                         u32 start_seq, u32 end_seq,
                          int dup_sack, int pcount)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       u8 sacked = TCP_SKB_CB(skb)->sacked;
        int fack_count = state->fack_count;
 
        /* Account D-SACK for retransmitted packet. */
        if (dup_sack && (sacked & TCPCB_RETRANS)) {
                if (tp->undo_marker && tp->undo_retrans &&
-                   after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
+                   after(end_seq, tp->undo_marker))
                        tp->undo_retrans--;
                if (sacked & TCPCB_SACKED_ACKED)
                        state->reord = min(fack_count, state->reord);
        }
 
        /* Nothing to do; acked frame is about to be dropped (was ACKed). */
-       if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
+       if (!after(end_seq, tp->snd_una))
                return sacked;
 
        if (!(sacked & TCPCB_SACKED_ACKED)) {
@@ -1347,13 +1345,13 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
                                /* New sack for not retransmitted frame,
                                 * which was in hole. It is reordering.
                                 */
-                               if (before(TCP_SKB_CB(skb)->seq,
+                               if (before(start_seq,
                                           tcp_highest_sack_seq(tp)))
                                        state->reord = min(fack_count,
                                                           state->reord);
 
                                /* SACK enhanced F-RTO (RFC4138; Appendix B) */
-                               if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark))
+                               if (!after(end_seq, tp->frto_highmark))
                                        state->flag |= FLAG_ONLY_ORIG_SACKED;
                        }
 
@@ -1371,8 +1369,7 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
 
                /* Lost marker hint past SACKed? Tweak RFC3517 cnt */
                if (!tcp_is_fack(tp) && (tp->lost_skb_hint != NULL) &&
-                   before(TCP_SKB_CB(skb)->seq,
-                          TCP_SKB_CB(tp->lost_skb_hint)->seq))
+                   before(start_seq, TCP_SKB_CB(tp->lost_skb_hint)->seq))
                        tp->lost_cnt_hint += pcount;
 
                if (fack_count > tp->fackets_out)
@@ -1391,6 +1388,9 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
        return sacked;
 }
 
+/* Shift newly-SACKed bytes from this skb to the immediately previous
+ * already-SACKed sk_buff. Mark the newly-SACKed bytes as such.
+ */
 static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
                           struct tcp_sacktag_state *state,
                           unsigned int pcount, int shifted, int mss,
@@ -1398,10 +1398,13 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *prev = tcp_write_queue_prev(sk, skb);
+       u32 start_seq = TCP_SKB_CB(skb)->seq;   /* start of newly-SACKed */
+       u32 end_seq = start_seq + shifted;      /* end of newly-SACKed */
 
        BUG_ON(!pcount);
 
-       if (skb == tp->lost_skb_hint)
+       /* Adjust hint for FACK. Non-FACK is handled in tcp_sacktag_one(). */
+       if (tcp_is_fack(tp) && (skb == tp->lost_skb_hint))
                tp->lost_cnt_hint += pcount;
 
        TCP_SKB_CB(prev)->end_seq += shifted;
@@ -1427,8 +1430,11 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
                skb_shinfo(skb)->gso_type = 0;
        }
 
-       /* We discard results */
-       tcp_sacktag_one(skb, sk, state, dup_sack, pcount);
+       /* Adjust counters and hints for the newly sacked sequence range but
+        * discard the return value since prev is already marked.
+        */
+       tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked,
+                       start_seq, end_seq, dup_sack, pcount);
 
        /* Difference in this won't matter, both ACKed by the same cumul. ACK */
        TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS);
@@ -1667,10 +1673,14 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
                        break;
 
                if (in_sack) {
-                       TCP_SKB_CB(skb)->sacked = tcp_sacktag_one(skb, sk,
-                                                                 state,
-                                                                 dup_sack,
-                                                                 tcp_skb_pcount(skb));
+                       TCP_SKB_CB(skb)->sacked =
+                               tcp_sacktag_one(sk,
+                                               state,
+                                               TCP_SKB_CB(skb)->sacked,
+                                               TCP_SKB_CB(skb)->seq,
+                                               TCP_SKB_CB(skb)->end_seq,
+                                               dup_sack,
+                                               tcp_skb_pcount(skb));
 
                        if (!before(TCP_SKB_CB(skb)->seq,
                                    tcp_highest_sack_seq(tp)))
@@ -1844,10 +1854,6 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
                if (found_dup_sack && ((i + 1) == first_sack_index))
                        next_dup = &sp[i + 1];
 
-               /* Event "B" in the comment above. */
-               if (after(end_seq, tp->high_seq))
-                       state.flag |= FLAG_DATA_LOST;
-
                /* Skip too early cached blocks */
                while (tcp_sack_cache_ok(tp, cache) &&
                       !before(start_seq, cache->end_seq))
@@ -2515,8 +2521,11 @@ static void tcp_timeout_skbs(struct sock *sk)
        tcp_verify_left_out(tp);
 }
 
-/* Mark head of queue up as lost. With RFC3517 SACK, the packets is
- * is against sacked "cnt", otherwise it's against facked "cnt"
+/* Detect loss in event "A" above by marking head of queue up as lost.
+ * For FACK or non-SACK(Reno) senders, the first "packets" number of segments
+ * are considered lost. For RFC3517 SACK, a segment is considered lost if it
+ * has at least tp->reordering SACKed seqments above it; "packets" refers to
+ * the maximum SACKed segments to pass before reaching this limit.
  */
 static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
 {
@@ -2525,6 +2534,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
        int cnt, oldcnt;
        int err;
        unsigned int mss;
+       /* Use SACK to deduce losses of new sequences sent during recovery */
+       const u32 loss_high = tcp_is_sack(tp) ?  tp->snd_nxt : tp->high_seq;
 
        WARN_ON(packets > tp->packets_out);
        if (tp->lost_skb_hint) {
@@ -2546,7 +2557,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
                tp->lost_skb_hint = skb;
                tp->lost_cnt_hint = cnt;
 
-               if (after(TCP_SKB_CB(skb)->end_seq, tp->high_seq))
+               if (after(TCP_SKB_CB(skb)->end_seq, loss_high))
                        break;
 
                oldcnt = cnt;
@@ -3033,19 +3044,10 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
        if (tcp_check_sack_reneging(sk, flag))
                return;
 
-       /* C. Process data loss notification, provided it is valid. */
-       if (tcp_is_fack(tp) && (flag & FLAG_DATA_LOST) &&
-           before(tp->snd_una, tp->high_seq) &&
-           icsk->icsk_ca_state != TCP_CA_Open &&
-           tp->fackets_out > tp->reordering) {
-               tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering, 0);
-               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSS);
-       }
-
-       /* D. Check consistency of the current state. */
+       /* C. Check consistency of the current state. */
        tcp_verify_left_out(tp);
 
-       /* E. Check state exit conditions. State can be terminated
+       /* D. Check state exit conditions. State can be terminated
         *    when high_seq is ACKed. */
        if (icsk->icsk_ca_state == TCP_CA_Open) {
                WARN_ON(tp->retrans_out != 0);
@@ -3077,7 +3079,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                }
        }
 
-       /* F. Process state. */
+       /* E. Process state. */
        switch (icsk->icsk_ca_state) {
        case TCP_CA_Recovery:
                if (!(flag & FLAG_SND_UNA_ADVANCED)) {
index 1eb4ad57670eb0f47c4a3ecde927819cb83ef12f..94d683a61cba45c04eb13c7882cb44bb91d0f96f 100644 (file)
@@ -631,7 +631,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
        arg.iov[0].iov_len  = sizeof(rep.th);
 
 #ifdef CONFIG_TCP_MD5SIG
-       key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
+       key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
        if (key) {
                rep.opt[0] = htonl((TCPOPT_NOP << 24) |
                                   (TCPOPT_NOP << 16) |
@@ -651,6 +651,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
        arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
+       /* When socket is gone, all binding information is lost.
+        * routing might fail in this case. using iif for oif to
+        * make sure we can deliver it
+        */
+       arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
 
        net = dev_net(skb_dst(skb)->dev);
        arg.tos = ip_hdr(skb)->tos;
index 8c8de2780c7a7add9e91805300824e7182d40f28..4ff3b6dc74fc013b00720443587e2f40d2f1bbbf 100644 (file)
@@ -1141,11 +1141,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
        sk_mem_uncharge(sk, len);
        sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
 
-       /* Any change of skb->len requires recalculation of tso
-        * factor and mss.
-        */
+       /* Any change of skb->len requires recalculation of tso factor. */
        if (tcp_skb_pcount(skb) > 1)
-               tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk));
+               tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb));
 
        return 0;
 }
index a516d1e399dfcb1a22ca39e452f3dbe725455ade..cd2e0723266d12b508569be0f4f6836cb21f94e7 100644 (file)
@@ -77,10 +77,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)
        if (sk->sk_err_soft)
                shift++;
 
-       if (tcp_too_many_orphans(sk, shift)) {
-               if (net_ratelimit())
-                       printk(KERN_INFO "Out of socket memory\n");
-
+       if (tcp_check_oom(sk, shift)) {
                /* Catch exceptional cases, when connection requires reset.
                 *      1. Last segment was sent recently. */
                if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
index e5e18cb8a58686a2331480c53edac2a77b901e8c..8a949f19deb6dc93542396138004a5a6b2bfeeab 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/udp.h>
 #include <net/udp.h>
 #include <net/udplite.h>
-#include <linux/inet_diag.h>
 #include <linux/sock_diag.h>
 
 static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
index a225d5ee3c2fc877f25e7af417c58de124fe8cb9..c02280a4d126980540daac44a8b541b92c0b16f0 100644 (file)
@@ -502,29 +502,31 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
        rcu_read_unlock();
 }
 
-static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
+static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
 {
        struct net *net;
+       int old;
+
+       if (!rtnl_trylock())
+               return restart_syscall();
 
        net = (struct net *)table->extra2;
-       if (p == &net->ipv6.devconf_dflt->forwarding)
-               return 0;
+       old = *p;
+       *p = newf;
 
-       if (!rtnl_trylock()) {
-               /* Restore the original values before restarting */
-               *p = old;
-               return restart_syscall();
+       if (p == &net->ipv6.devconf_dflt->forwarding) {
+               rtnl_unlock();
+               return 0;
        }
 
        if (p == &net->ipv6.devconf_all->forwarding) {
-               __s32 newf = net->ipv6.devconf_all->forwarding;
                net->ipv6.devconf_dflt->forwarding = newf;
                addrconf_forward_change(net, newf);
-       } else if ((!*p) ^ (!old))
+       } else if ((!newf) ^ (!old))
                dev_forward_change((struct inet6_dev *)table->extra1);
        rtnl_unlock();
 
-       if (*p)
+       if (newf)
                rt6_purge_dflt_routers(net);
        return 1;
 }
@@ -4260,9 +4262,17 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
        int *valp = ctl->data;
        int val = *valp;
        loff_t pos = *ppos;
+       ctl_table lctl;
        int ret;
 
-       ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+       /*
+        * ctl->data points to idev->cnf.forwarding, we should
+        * not modify it until we get the rtnl lock.
+        */
+       lctl = *ctl;
+       lctl.data = &val;
+
+       ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
 
        if (write)
                ret = addrconf_fixup_forwarding(ctl, valp, val);
@@ -4300,26 +4310,27 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
        rcu_read_unlock();
 }
 
-static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
+static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
 {
        struct net *net;
+       int old;
+
+       if (!rtnl_trylock())
+               return restart_syscall();
 
        net = (struct net *)table->extra2;
+       old = *p;
+       *p = newf;
 
-       if (p == &net->ipv6.devconf_dflt->disable_ipv6)
+       if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
+               rtnl_unlock();
                return 0;
-
-       if (!rtnl_trylock()) {
-               /* Restore the original values before restarting */
-               *p = old;
-               return restart_syscall();
        }
 
        if (p == &net->ipv6.devconf_all->disable_ipv6) {
-               __s32 newf = net->ipv6.devconf_all->disable_ipv6;
                net->ipv6.devconf_dflt->disable_ipv6 = newf;
                addrconf_disable_change(net, newf);
-       } else if ((!*p) ^ (!old))
+       } else if ((!newf) ^ (!old))
                dev_disable_change((struct inet6_dev *)table->extra1);
 
        rtnl_unlock();
@@ -4333,9 +4344,17 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write,
        int *valp = ctl->data;
        int val = *valp;
        loff_t pos = *ppos;
+       ctl_table lctl;
        int ret;
 
-       ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+       /*
+        * ctl->data points to idev->cnf.disable_ipv6, we should
+        * not modify it until we get the rtnl lock.
+        */
+       lctl = *ctl;
+       lctl.data = &val;
+
+       ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
 
        if (write)
                ret = addrconf_disable_ipv6(ctl, valp, val);
index ae08aee1773c678187f8be84414f95ac472aa426..251e7cd75e89787f5346037a278bfd7e5b8c8ced 100644 (file)
@@ -575,7 +575,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
        }
        if (np->rxopt.bits.rxorigdstaddr) {
                struct sockaddr_in6 sin6;
-               u16 *ports = (u16 *) skb_transport_header(skb);
+               __be16 *ports = (__be16 *) skb_transport_header(skb);
 
                if (skb_transport_offset(skb) + 4 <= skb->len) {
                        /* All current transport protocols have the port numbers in the
index fdeb6d03da812d136874fccc870b90c69efee7b1..da2e92d05c15a5052ea2cc19ba9bfc5751c23cf6 100644 (file)
@@ -237,8 +237,8 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v)
        struct inet6_dev *idev = (struct inet6_dev *)seq->private;
 
        seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
-       snmp6_seq_show_item(seq, (void __percpu **)idev->stats.ipv6, NULL,
-                           snmp6_ipstats_list);
+       snmp6_seq_show_item64(seq, (void __percpu **)idev->stats.ipv6,
+                           snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp));
        snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs,
                            snmp6_icmp6_list);
        snmp6_seq_show_icmpv6msg(seq, idev->stats.icmpv6msgdev->mibs);
index 07361dfa80852cbbe4db66027f8da5ef13ade4c1..8c2e3ab58f2af211c04f17c337929bd2802cbe27 100644 (file)
@@ -1091,6 +1091,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        else {
                neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr);
                if (IS_ERR(neigh)) {
+                       in6_dev_put(idev);
                        dst_free(&rt->dst);
                        return ERR_CAST(neigh);
                }
index 906c7ca43542e020c53759ec554f952f20b9d1e4..3edd05ae4388741176949e9c72f3543fa8d52c87 100644 (file)
@@ -1083,7 +1083,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 
 #ifdef CONFIG_TCP_MD5SIG
        if (sk)
-               key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
+               key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
 #endif
 
        if (th->ack)
index d21e7ebd91ca5b846b076adb4aeec53a6768d3e5..55670ec3cd0f916143759cbc73320cf85b7ef196 100644 (file)
@@ -393,11 +393,6 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
 
-       if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
-               goto drop;
-
-       nf_reset(skb);
-
        /* Charge it to the socket, dropping if the queue is full. */
        rc = sock_queue_rcv_skb(sk, skb);
        if (rc < 0)
index a18e6c3d36e37e699089ed5e0910c857da073d1c..b9bef2c750267cfd0adeaf918c1cc5503461d3db 100644 (file)
@@ -713,6 +713,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct sk_buff *skb = NULL;
        struct sock *sk = sock->sk;
        struct llc_sock *llc = llc_sk(sk);
+       unsigned long cpu_flags;
        size_t copied = 0;
        u32 peek_seq = 0;
        u32 *seq;
@@ -838,7 +839,9 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                        goto copy_uaddr;
 
                if (!(flags & MSG_PEEK)) {
+                       spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
                        sk_eat_skb(sk, skb, 0);
+                       spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
                        *seq = 0;
                }
 
@@ -859,7 +862,9 @@ copy_uaddr:
                llc_cmsg_rcv(msg, skb);
 
        if (!(flags & MSG_PEEK)) {
+                       spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
                        sk_eat_skb(sk, skb, 0);
+                       spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
                        *seq = 0;
        }
 
index e60df48fa4d4d235016398706bf3b32e5633c1e0..296620d6ca0c0c2388f05ffaffd9c5d832eb3cbd 100644 (file)
@@ -791,7 +791,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
                        ret = sta_info_move_state_checked(sta,
                                        IEEE80211_STA_AUTHORIZED);
-               else
+               else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
                        ret = sta_info_move_state_checked(sta,
                                        IEEE80211_STA_ASSOC);
                if (ret)
index 38e6101190d9a51eded895cbf2b7db6d5b09a0b6..59edcd95a58dbcec31833568f9d5f8bd8893da09 100644 (file)
@@ -225,9 +225,9 @@ KEY_OPS(key);
                            key, &key_##name##_ops);
 
 void ieee80211_debugfs_key_add(struct ieee80211_key *key)
-  {
+{
        static int keycount;
-       char buf[50];
+       char buf[100];
        struct sta_info *sta;
 
        if (!key->local->debugfs.keys)
@@ -244,7 +244,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
 
        sta = key->sta;
        if (sta) {
-               sprintf(buf, "../../stations/%pM", sta->sta.addr);
+               sprintf(buf, "../../netdev:%s/stations/%pM",
+                       sta->sdata->name, sta->sta.addr);
                key->debugfs.stalink =
                        debugfs_create_symlink("station", key->debugfs.dir, buf);
        }
index b3d76b756cd55e4c8e513bfa506c336ab77e667b..a4643969a13b22524a7f90f0304c18d917f025be 100644 (file)
@@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
        sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
 
+       local->oper_channel = chan;
        channel_type = ifibss->channel_type;
        if (channel_type > NL80211_CHAN_HT20 &&
            !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
index e47768cb8cb3b18eb98e3e16abc542a3735ad9e3..01a21c2f6ab37df336f5f69c55f33de4e0a698f3 100644 (file)
@@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
                        continue;
                }
                /* count everything else */
+               sdata->vif.bss_conf.idle = false;
                count++;
        }
 
index 0a0d94ad9b08374fe90e0f653da4d4b352e8f6c9..b142bd4c239096f51fbf0e79e9b507a2bf35d1d0 100644 (file)
@@ -910,6 +910,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
                            result);
 
+       ieee80211_led_init(local);
+
        rtnl_lock();
 
        result = ieee80211_init_rate_ctrl_alg(local,
@@ -931,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
        rtnl_unlock();
 
-       ieee80211_led_init(local);
-
        local->network_latency_notifier.notifier_call =
                ieee80211_max_network_latency;
        result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
index 73abb7524b2cee3ce83d122efe0dcbbda7257f85..54df1b2bafd2882454bc71b3a018161f0f83e5e3 100644 (file)
@@ -119,12 +119,12 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
        int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
                      sizeof(mgmt->u.action.u.mesh_action);
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+       skb = dev_alloc_skb(local->tx_headroom +
                            hdr_len +
                            2 + 37); /* max HWMP IE */
        if (!skb)
                return -1;
-       skb_reserve(skb, local->hw.extra_tx_headroom);
+       skb_reserve(skb, local->tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
        memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -250,12 +250,12 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
        if (time_before(jiffies, ifmsh->next_perr))
                return -EAGAIN;
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+       skb = dev_alloc_skb(local->tx_headroom +
                            hdr_len +
                            2 + 15 /* PERR IE */);
        if (!skb)
                return -1;
-       skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
+       skb_reserve(skb, local->tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
        memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
index 41ef1b4764422a85d56334f16c320b8d1d4db292..a17251730b9e603097ca8763f3301452168444a7 100644 (file)
@@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
        int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
                      sizeof(mgmt->u.action.u.self_prot);
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+       skb = dev_alloc_skb(local->tx_headroom +
                            hdr_len +
                            2 + /* capability info */
                            2 + /* AID */
@@ -186,7 +186,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                            sdata->u.mesh.ie_len);
        if (!skb)
                return -1;
-       skb_reserve(skb, local->hw.extra_tx_headroom);
+       skb_reserve(skb, local->tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
        memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
index ecb4c84c1bb389decfedfb182bea2b534dcd258d..295be92f7c7747238ae1ae9204982db8fd264d77 100644 (file)
@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       struct ieee80211_work *wk;
        u8 bssid[ETH_ALEN];
        bool assoc_bss = false;
 
@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                assoc_bss = true;
        } else {
                bool not_auth_yet = false;
+               struct ieee80211_work *tmp, *wk = NULL;
 
                mutex_unlock(&ifmgd->mtx);
 
                mutex_lock(&local->mtx);
-               list_for_each_entry(wk, &local->work_list, list) {
-                       if (wk->sdata != sdata)
+               list_for_each_entry(tmp, &local->work_list, list) {
+                       if (tmp->sdata != sdata)
                                continue;
 
-                       if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
-                           wk->type != IEEE80211_WORK_AUTH &&
-                           wk->type != IEEE80211_WORK_ASSOC &&
-                           wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
+                       if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
+                           tmp->type != IEEE80211_WORK_AUTH &&
+                           tmp->type != IEEE80211_WORK_ASSOC &&
+                           tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
                                continue;
 
-                       if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
+                       if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN))
                                continue;
 
-                       not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
-                       list_del_rcu(&wk->list);
-                       free_work(wk);
+                       not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
+                       list_del_rcu(&tmp->list);
+                       synchronize_rcu();
+                       wk = tmp;
                        break;
                }
                mutex_unlock(&local->mtx);
 
+               if (wk && wk->type == IEEE80211_WORK_ASSOC) {
+                       /* clean up dummy sta & TX sync */
+                       sta_info_destroy_addr(wk->sdata, wk->filter_ta);
+                       if (wk->assoc.synced)
+                               drv_finish_tx_sync(local, wk->sdata,
+                                                  wk->filter_ta,
+                                                  IEEE80211_TX_SYNC_ASSOC);
+               } else if (wk && wk->type == IEEE80211_WORK_AUTH) {
+                       if (wk->probe_auth.synced)
+                               drv_finish_tx_sync(local, wk->sdata,
+                                                  wk->filter_ta,
+                                                  IEEE80211_TX_SYNC_AUTH);
+               }
+               kfree(wk);
+
                /*
                 * If somebody requests authentication and we haven't
                 * sent out an auth frame yet there's no need to send
index f407427c642f4a6fdd1d6b38fb2462b244f00da1..5a5e504a8ffbc9cbf1d22bf8e35949311990406e 100644 (file)
@@ -611,7 +611,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
        index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
                                                tid_agg_rx->buf_size;
        if (!tid_agg_rx->reorder_buf[index] &&
-           tid_agg_rx->stored_mpdu_num > 1) {
+           tid_agg_rx->stored_mpdu_num) {
                /*
                 * No buffers ready to be released, but check whether any
                 * frames in the reorder buffer have timed out.
@@ -1979,6 +1979,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3,
                                    0, reason, fwd_hdr->addr2, sdata);
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
+               kfree_skb(fwd_skb);
                return RX_DROP_MONITOR;
        }
 
index 3c428d4839c7c5cca61ba535197068f3b5c10dbd..ff11f6bf8266dc1a01b1b16330b416a054d702de 100644 (file)
@@ -238,9 +238,11 @@ static void sta_unblock(struct work_struct *wk)
        if (sta->dead)
                return;
 
-       if (!test_sta_flag(sta, WLAN_STA_PS_STA))
+       if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
+               local_bh_disable();
                ieee80211_sta_ps_deliver_wakeup(sta);
-       else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
+               local_bh_enable();
+       } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
                clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 
                local_bh_disable();
index edcd1c7ab83f94fcaffdb049a93540bdf77c5baf..e05667cd5e766057c22770670834e6f2b19e3301 100644 (file)
@@ -1001,8 +1001,6 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
 {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-
        if (!tx->key)
                return TX_CONTINUE;
 
@@ -1017,13 +1015,7 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
        case WLAN_CIPHER_SUITE_AES_CMAC:
                return ieee80211_crypto_aes_cmac_encrypt(tx);
        default:
-               /* handle hw-only algorithm */
-               if (info->control.hw_key) {
-                       ieee80211_tx_set_protected(tx);
-                       return TX_CONTINUE;
-               }
-               break;
-
+               return ieee80211_crypto_hw_encrypt(tx);
        }
 
        return TX_DROP;
index 422b79851ec510ef4272f9f2565bb56a0e002aef..b758350919ff4641e69127a220f3c450fb07fcc9 100644 (file)
@@ -643,3 +643,22 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
 
        return RX_CONTINUE;
 }
+
+ieee80211_tx_result
+ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
+{
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *info = NULL;
+
+       skb_queue_walk(&tx->skbs, skb) {
+               info  = IEEE80211_SKB_CB(skb);
+
+               /* handle hw-only algorithm */
+               if (!info->control.hw_key)
+                       return TX_DROP;
+       }
+
+       ieee80211_tx_set_protected(tx);
+
+       return TX_CONTINUE;
+}
index baba0608313ef5419cccff809d28166b1178bf7b..07e33f899c71fc52f9ff1771cd283226a8a64084 100644 (file)
@@ -32,5 +32,7 @@ ieee80211_tx_result
 ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);
 ieee80211_rx_result
 ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
+ieee80211_tx_result
+ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
 
 #endif /* WPA_H */
index 86137b558f455d9e1740a977aa09ea1e294bb241..32dbf0fa89db7661e1ee22cee519c273a229c9ca 100644 (file)
@@ -77,35 +77,42 @@ find_set_type(const char *name, u8 family, u8 revision)
 }
 
 /* Unlock, try to load a set type module and lock again */
-static int
-try_to_load_type(const char *name)
+static bool
+load_settype(const char *name)
 {
        nfnl_unlock();
        pr_debug("try to load ip_set_%s\n", name);
        if (request_module("ip_set_%s", name) < 0) {
                pr_warning("Can't find ip_set type %s\n", name);
                nfnl_lock();
-               return -IPSET_ERR_FIND_TYPE;
+               return false;
        }
        nfnl_lock();
-       return -EAGAIN;
+       return true;
 }
 
 /* Find a set type and reference it */
+#define find_set_type_get(name, family, revision, found)       \
+       __find_set_type_get(name, family, revision, found, false)
+
 static int
-find_set_type_get(const char *name, u8 family, u8 revision,
-                 struct ip_set_type **found)
+__find_set_type_get(const char *name, u8 family, u8 revision,
+                   struct ip_set_type **found, bool retry)
 {
        struct ip_set_type *type;
        int err;
 
+       if (retry && !load_settype(name))
+               return -IPSET_ERR_FIND_TYPE;
+
        rcu_read_lock();
        *found = find_set_type(name, family, revision);
        if (*found) {
                err = !try_module_get((*found)->me) ? -EFAULT : 0;
                goto unlock;
        }
-       /* Make sure the type is loaded but we don't support the revision */
+       /* Make sure the type is already loaded
+        * but we don't support the revision */
        list_for_each_entry_rcu(type, &ip_set_type_list, list)
                if (STREQ(type->name, name)) {
                        err = -IPSET_ERR_FIND_TYPE;
@@ -113,7 +120,8 @@ find_set_type_get(const char *name, u8 family, u8 revision,
                }
        rcu_read_unlock();
 
-       return try_to_load_type(name);
+       return retry ? -IPSET_ERR_FIND_TYPE :
+               __find_set_type_get(name, family, revision, found, true);
 
 unlock:
        rcu_read_unlock();
@@ -124,12 +132,19 @@ unlock:
  * If we succeeded, the supported minimal and maximum revisions are
  * filled out.
  */
+#define find_set_type_minmax(name, family, min, max) \
+       __find_set_type_minmax(name, family, min, max, false)
+
 static int
-find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
+__find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
+                      bool retry)
 {
        struct ip_set_type *type;
        bool found = false;
 
+       if (retry && !load_settype(name))
+               return -IPSET_ERR_FIND_TYPE;
+
        *min = 255; *max = 0;
        rcu_read_lock();
        list_for_each_entry_rcu(type, &ip_set_type_list, list)
@@ -145,7 +160,8 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
        if (found)
                return 0;
 
-       return try_to_load_type(name);
+       return retry ? -IPSET_ERR_FIND_TYPE :
+               __find_set_type_minmax(name, family, min, max, true);
 }
 
 #define family_name(f) ((f) == AF_INET ? "inet" : \
@@ -1126,6 +1142,7 @@ release_refcount:
        if (ret || !cb->args[2]) {
                pr_debug("release set %s\n", ip_set_list[index]->name);
                ip_set_put_byindex(index);
+               cb->args[2] = 0;
        }
 out:
        if (nlh) {
index 299fec91f74189a562f7fcb0d47914d9b279c286..bbe23baa19b64f4df7b2532b1471614a5315cc26 100644 (file)
@@ -121,18 +121,6 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
        int ret = 0;
 
        if (tmpl != NULL) {
-               /* we've got a userspace helper. */
-               if (tmpl->status & IPS_USERSPACE_HELPER) {
-                       help = nf_ct_helper_ext_add(ct, flags);
-                       if (help == NULL) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       rcu_assign_pointer(help->helper, NULL);
-                       __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);
-                       ret = 0;
-                       goto out;
-               }
                help = nfct_help(tmpl);
                if (help != NULL)
                        helper = help->helper;
index 2a4834b83332afa2ebf87b37102cd2a9d6dcd8d1..9307b033c0c9d9ff35c60b31755aaceef8d89087 100644 (file)
@@ -2042,10 +2042,6 @@ ctnetlink_create_expect(struct net *net, u16 zone,
        }
        help = nfct_help(ct);
        if (!help) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
-       if (test_bit(IPS_USERSPACE_HELPER_BIT, &ct->status)) {
                if (!cda[CTA_EXPECT_TIMEOUT]) {
                        err = -EINVAL;
                        goto out;
index 8e87123f1373a1a4a42ddb6211c1737d2346047d..0221d10de75a517dbc4c5e5c7d40b432abef15a3 100644 (file)
@@ -62,8 +62,8 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
        int ret = 0;
        u8 proto;
 
-       if (info->flags & ~(XT_CT_NOTRACK | XT_CT_USERSPACE_HELPER))
-               return -EOPNOTSUPP;
+       if (info->flags & ~XT_CT_NOTRACK)
+               return -EINVAL;
 
        if (info->flags & XT_CT_NOTRACK) {
                ct = nf_ct_untracked_get();
@@ -92,9 +92,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
                                  GFP_KERNEL))
                goto err3;
 
-       if (info->flags & XT_CT_USERSPACE_HELPER) {
-               __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);
-       } else if (info->helper[0]) {
+       if (info->helper[0]) {
                ret = -ENOENT;
                proto = xt_ct_find_proto(par);
                if (!proto) {
index 8e4992101875086cd412154d102793c99ffa6bed..d95f9c963cde01cfcd4d6541de352c85f44fc6f8 100644 (file)
@@ -445,7 +445,6 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
 {
        __be16 _ports[2], *ports;
        u8 nexthdr;
-       __be16 frag_off;
        int poff;
 
        memset(dst, 0, sizeof(*dst));
@@ -466,6 +465,9 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
                break;
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
        case NFPROTO_IPV6:
+       {
+               __be16 frag_off;
+
                if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
                        memcpy(&dst->ip6.dst, &ipv6_hdr(skb)->daddr,
                               sizeof(dst->ip6.dst));
@@ -485,6 +487,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
                if ((int)protoff < 0)
                        return -1;
                break;
+       }
 #endif
        default:
                BUG();
index 9a2725114e99bad3a1e69351ac55ec764a295cc6..ce64c18b8c79a99ef4251e7c9d2a752105207725 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2011 Nicira Networks.
+ * Copyright (c) 2007-2012 Nicira Networks.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -36,7 +36,6 @@
 #include <linux/rcupdate.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
-#include <linux/version.h>
 #include <linux/ethtool.h>
 #include <linux/wait.h>
 #include <asm/system.h>
@@ -1397,9 +1396,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
        int i = 0;
 
        list_for_each_entry(dp, &dps, list_node) {
-               if (i < skip)
-                       continue;
-               if (ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid,
+               if (i >= skip &&
+                   ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid,
                                         cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                         OVS_DP_CMD_NEW) < 0)
                        break;
index 5b9f884b7055a6c75205fc00082f2f541202df7f..c73370cc1f02df24d32026c0e775efef72451dfc 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/u64_stats_sync.h>
-#include <linux/version.h>
 
 #include "flow.h"
 
index fe7f020a843efa2519f47c80ca4b340e14299917..1252c3081ef12740a0b818fbd58ae3ab6e9b870e 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/in.h>
 #include <linux/rcupdate.h>
 #include <linux/if_arp.h>
-#include <linux/if_ether.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/tcp.h>
index 8fc28b86f2b3e4666fd2ef18d63ad785aed2c25d..322b8d206693dde98a30f1d36a6db4d800e0f17a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
 
 #include "datapath.h"
 #include "vport-internal_dev.h"
index 7f0ef3794c515064c67d719b8f65c564aa82295d..6c066ba25dc71c24c8a94e4acc50014d610f77a6 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/rcupdate.h>
 #include <linux/rtnetlink.h>
 #include <linux/compat.h>
-#include <linux/version.h>
 
 #include "vport.h"
 #include "vport-internal_dev.h"
index bb6ad81b671d055b89fbe74287ed328a834aac03..424ff622ab5f8e77dc69c7b54b98bdaafa350329 100644 (file)
@@ -68,7 +68,6 @@ static int rds_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
        struct rds_sock *rs;
-       unsigned long flags;
 
        if (!sk)
                goto out;
@@ -94,10 +93,10 @@ static int rds_release(struct socket *sock)
        rds_rdma_drop_keys(rs);
        rds_notify_queue_get(rs, NULL);
 
-       spin_lock_irqsave(&rds_sock_lock, flags);
+       spin_lock_bh(&rds_sock_lock);
        list_del_init(&rs->rs_item);
        rds_sock_count--;
-       spin_unlock_irqrestore(&rds_sock_lock, flags);
+       spin_unlock_bh(&rds_sock_lock);
 
        rds_trans_put(rs->rs_transport);
 
@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = {
 
 static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
 {
-       unsigned long flags;
        struct rds_sock *rs;
 
        sock_init_data(sock, sk);
@@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
        spin_lock_init(&rs->rs_rdma_lock);
        rs->rs_rdma_keys = RB_ROOT;
 
-       spin_lock_irqsave(&rds_sock_lock, flags);
+       spin_lock_bh(&rds_sock_lock);
        list_add_tail(&rs->rs_item, &rds_sock_list);
        rds_sock_count++;
-       spin_unlock_irqrestore(&rds_sock_lock, flags);
+       spin_unlock_bh(&rds_sock_lock);
 
        return 0;
 }
@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len,
 {
        struct rds_sock *rs;
        struct rds_incoming *inc;
-       unsigned long flags;
        unsigned int total = 0;
 
        len /= sizeof(struct rds_info_message);
 
-       spin_lock_irqsave(&rds_sock_lock, flags);
+       spin_lock_bh(&rds_sock_lock);
 
        list_for_each_entry(rs, &rds_sock_list, rs_item) {
                read_lock(&rs->rs_recv_lock);
@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len,
                read_unlock(&rs->rs_recv_lock);
        }
 
-       spin_unlock_irqrestore(&rds_sock_lock, flags);
+       spin_unlock_bh(&rds_sock_lock);
 
        lens->nr = total;
        lens->each = sizeof(struct rds_info_message);
@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len,
 {
        struct rds_info_socket sinfo;
        struct rds_sock *rs;
-       unsigned long flags;
 
        len /= sizeof(struct rds_info_socket);
 
-       spin_lock_irqsave(&rds_sock_lock, flags);
+       spin_lock_bh(&rds_sock_lock);
 
        if (len < rds_sock_count)
                goto out;
@@ -529,7 +525,7 @@ out:
        lens->nr = rds_sock_count;
        lens->each = sizeof(struct rds_info_socket);
 
-       spin_unlock_irqrestore(&rds_sock_lock, flags);
+       spin_unlock_bh(&rds_sock_lock);
 }
 
 static void rds_exit(void)
index 4cba13e46ffd7e13868526ec5acaee5fdde005e2..ae3a035f53908daea1784fcb5224d16946af5314 100644 (file)
@@ -232,7 +232,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
        if (toklen <= (n_parts + 1) * 4)
                return -EINVAL;
 
-       princ->name_parts = kcalloc(sizeof(char *), n_parts, GFP_KERNEL);
+       princ->name_parts = kcalloc(n_parts, sizeof(char *), GFP_KERNEL);
        if (!princ->name_parts)
                return -ENOMEM;
 
@@ -355,7 +355,7 @@ static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td,
 
                _debug("n_elem %d", n_elem);
 
-               td = kcalloc(sizeof(struct krb5_tagged_data), n_elem,
+               td = kcalloc(n_elem, sizeof(struct krb5_tagged_data),
                             GFP_KERNEL);
                if (!td)
                        return -ENOMEM;
index e465064d39a369aad077f8ed55a54fd1f1cac31d..7e267d7b9c75730ef8351798ec1540b92e31f101 100644 (file)
@@ -148,8 +148,7 @@ struct choke_skb_cb {
 
 static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb)
 {
-       BUILD_BUG_ON(sizeof(skb->cb) <
-               sizeof(struct qdisc_skb_cb) + sizeof(struct choke_skb_cb));
+       qdisc_cb_private_validate(skb, sizeof(struct choke_skb_cb));
        return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data;
 }
 
index e7e1d0b57b3d2a28d5e99276cd195f7dfde999d0..e83d61ca78cab71c7a54c22b7d09cc94611726a8 100644 (file)
@@ -130,8 +130,7 @@ struct netem_skb_cb {
 
 static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
 {
-       BUILD_BUG_ON(sizeof(skb->cb) <
-               sizeof(struct qdisc_skb_cb) + sizeof(struct netem_skb_cb));
+       qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
        return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
 }
 
@@ -419,7 +418,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        cb = netem_skb_cb(skb);
        if (q->gap == 0 ||              /* not doing reordering */
-           q->counter < q->gap ||      /* inside last reordering gap */
+           q->counter < q->gap - 1 ||  /* inside last reordering gap */
            q->reorder < get_crandom(&q->reorder_cor)) {
                psched_time_t now;
                psched_tdiff_t delay;
index 96e42cae4c7a4580e753c41b9c4f1e5c29cabbcd..d7eea99333e96a33a953106a3a0f2fdb32a12385 100644 (file)
@@ -94,8 +94,7 @@ struct sfb_skb_cb {
 
 static inline struct sfb_skb_cb *sfb_skb_cb(const struct sk_buff *skb)
 {
-       BUILD_BUG_ON(sizeof(skb->cb) <
-               sizeof(struct qdisc_skb_cb) + sizeof(struct sfb_skb_cb));
+       qdisc_cb_private_validate(skb, sizeof(struct sfb_skb_cb));
        return (struct sfb_skb_cb *)qdisc_skb_cb(skb)->data;
 }
 
index 67494aef9acf3c230aa80dd4d70d1369a5318c04..60d47180f0432e0d65c92ef5a6f6cf865b29a3c0 100644 (file)
@@ -166,9 +166,8 @@ struct sfq_skb_cb {
 
 static inline struct sfq_skb_cb *sfq_skb_cb(const struct sk_buff *skb)
 {
-       BUILD_BUG_ON(sizeof(skb->cb) <
-               sizeof(struct qdisc_skb_cb) + sizeof(struct sfq_skb_cb));
-       return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;
+       qdisc_cb_private_validate(skb, sizeof(struct sfq_skb_cb));
+       return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;
 }
 
 static unsigned int sfq_hash(const struct sfq_sched_data *q,
index 1426ec3d0a531ecd4ec0b227c5f7aa22843a1750..75762f346975ed6e2be6d639ed7a3e1d83ede077 100644 (file)
@@ -92,6 +92,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        if (gcred->acred.group_info != NULL)
                get_group_info(gcred->acred.group_info);
        gcred->acred.machine_cred = acred->machine_cred;
+       gcred->acred.principal = acred->principal;
 
        dprintk("RPC:       allocated %s cred %p for uid %d gid %d\n",
                        gcred->acred.machine_cred ? "machine" : "generic",
@@ -123,6 +124,17 @@ generic_destroy_cred(struct rpc_cred *cred)
        call_rcu(&cred->cr_rcu, generic_free_cred_callback);
 }
 
+static int
+machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags)
+{
+       if (!gcred->acred.machine_cred ||
+           gcred->acred.principal != acred->principal ||
+           gcred->acred.uid != acred->uid ||
+           gcred->acred.gid != acred->gid)
+               return 0;
+       return 1;
+}
+
 /*
  * Match credentials against current process creds.
  */
@@ -132,9 +144,12 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
        struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
        int i;
 
+       if (acred->machine_cred)
+               return machine_cred_match(acred, gcred, flags);
+
        if (gcred->acred.uid != acred->uid ||
            gcred->acred.gid != acred->gid ||
-           gcred->acred.machine_cred != acred->machine_cred)
+           gcred->acred.machine_cred != 0)
                goto out_nomatch;
 
        /* Optimisation in the case where pointers are identical... */
index aad8fb699989d26c0cfe727ea529b312e79c65ce..85d3bb7490aabcb26fd10b08adfcddebb5cbeb59 100644 (file)
@@ -1918,7 +1918,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                struct sk_buff *skb;
 
                unix_state_lock(sk);
-               skb = skb_dequeue(&sk->sk_receive_queue);
+               skb = skb_peek(&sk->sk_receive_queue);
                if (skb == NULL) {
                        unix_sk(sk)->recursion_level = 0;
                        if (copied >= target)
@@ -1958,11 +1958,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                if (check_creds) {
                        /* Never glue messages from different writers */
                        if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
-                           (UNIXCB(skb).cred != siocb->scm->cred)) {
-                               skb_queue_head(&sk->sk_receive_queue, skb);
-                               sk->sk_data_ready(sk, skb->len);
+                           (UNIXCB(skb).cred != siocb->scm->cred))
                                break;
-                       }
                } else {
                        /* Copy credentials */
                        scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
@@ -1977,8 +1974,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 
                chunk = min_t(unsigned int, skb->len, size);
                if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
-                       skb_queue_head(&sk->sk_receive_queue, skb);
-                       sk->sk_data_ready(sk, skb->len);
                        if (copied == 0)
                                copied = -EFAULT;
                        break;
@@ -1993,13 +1988,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                        if (UNIXCB(skb).fp)
                                unix_detach_fds(siocb->scm, skb);
 
-                       /* put the skb back if we didn't use it up.. */
-                       if (skb->len) {
-                               skb_queue_head(&sk->sk_receive_queue, skb);
-                               sk->sk_data_ready(sk, skb->len);
+                       if (skb->len)
                                break;
-                       }
 
+                       skb_unlink(skb, &sk->sk_receive_queue);
                        consume_skb(skb);
 
                        if (siocb->scm->fp)
@@ -2010,9 +2002,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                        if (UNIXCB(skb).fp)
                                siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
 
-                       /* put message back and return */
-                       skb_queue_head(&sk->sk_receive_queue, skb);
-                       sk->sk_data_ready(sk, skb->len);
                        break;
                }
        } while (size);
index e3bfcbe8a520b63639b04115bf148fb4ddd144eb..a3b9782441f9e49a3a3522107e40dc3ffee913b8 100755 (executable)
@@ -1924,6 +1924,12 @@ sub process {
                        my $pre_ctx = "$1$2";
 
                        my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
+
+                       if ($line =~ /^\+\t{6,}/) {
+                               WARN("DEEP_INDENTATION",
+                                    "Too many leading tabs - consider code refactoring\n" . $herecurr);
+                       }
+
                        my $ctx_cnt = $realcnt - $#ctx - 1;
                        my $ctx = join("\n", @ctx);
 
index d793001929cf40c0e3a773927ac047878a81df30..9b0c0b8b4ab4cd483158cfb606aaba038fbbabb5 100755 (executable)
@@ -5,7 +5,7 @@ use strict;
 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
 ## Copyright (C) 2001  Simon Huggins                             ##
-## Copyright (C) 2005-2010  Randy Dunlap                         ##
+## Copyright (C) 2005-2012  Randy Dunlap                         ##
 ##                                                              ##
 ## #define enhancements by Armin Kuster <akuster@mvista.com>    ##
 ## Copyright (c) 2000 MontaVista Software, Inc.                         ##
@@ -1785,6 +1785,7 @@ sub dump_function($$) {
     $prototype =~ s/__devinit +//;
     $prototype =~ s/__init +//;
     $prototype =~ s/__init_or_module +//;
+    $prototype =~ s/__must_check +//;
     $prototype =~ s/^#\s*define\s+//; #ak added
     $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
 
index c0e14b3f2306f77b6e85d2d6f7f25a70b6b41a22..d0de2a2c3a2de00cacf74ba796f5b02fa5b56a5d 100644 (file)
@@ -823,16 +823,6 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id,
 }
 ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry);
 
-/* Looks like: mcp:S */
-static int do_mcp_entry(const char *filename, struct mcp_device_id *id,
-                       char *alias)
-{
-       sprintf(alias, MCP_MODULE_PREFIX "%s", id->name);
-
-       return 1;
-}
-ADD_TO_DEVTABLE("mcp", struct mcp_device_id, do_mcp_entry); 
-
 static const struct dmifield {
        const char *prefix;
        int field;
@@ -942,7 +932,7 @@ static int do_isapnp_entry(const char *filename,
                (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f);
        return 1;
 }
-ADD_TO_DEVTABLE("isa", struct isapnp_device_id, do_isapnp_entry);
+ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry);
 
 /*
  * Append a match expression for a single masked hex digit.
index 2bd594e6d1b4115fd8647f8f64b62580eac772ae..9adb667dd31aec6911a7049a6d3a4d91412b1d43 100644 (file)
@@ -1494,6 +1494,13 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
        return 0;
 }
 
+#ifndef R_ARM_CALL
+#define R_ARM_CALL     28
+#endif
+#ifndef R_ARM_JUMP24
+#define R_ARM_JUMP24   29
+#endif
+
 static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
 {
        unsigned int r_typ = ELF_R_TYPE(r->r_info);
@@ -1505,6 +1512,8 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
                              (elf->symtab_start + ELF_R_SYM(r->r_info));
                break;
        case R_ARM_PC24:
+       case R_ARM_CALL:
+       case R_ARM_JUMP24:
                /* From ARM ABI: ((S + A) | T) - P */
                r->r_addend = (int)(long)(elf->hdr +
                              sechdr->sh_offset +
index d384ea921482088dea0c7c13f54e2d3c57c18f26..5bd1cc1b4a54dcae8681bf7e0c092d374614ab6d 100644 (file)
@@ -3,11 +3,11 @@ config INTEGRITY
        def_bool y
        depends on IMA || EVM
 
-config INTEGRITY_DIGSIG
+config INTEGRITY_SIGNATURE
        boolean "Digital signature verification using multiple keyrings"
        depends on INTEGRITY && KEYS
        default n
-       select DIGSIG
+       select SIGNATURE
        help
          This option enables digital signature verification support
          using multiple keyrings. It defines separate keyrings for each
index bece0563ee5e019bc9fa56bd2dff4e426cf262b7..d43799cc14f69a67da22249d637b5f9d1334b357 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_INTEGRITY) += integrity.o
-obj-$(CONFIG_INTEGRITY_DIGSIG) += digsig.o
+obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 
 integrity-y := iint.o
 
index c5c5a72c30be30b0477446cd311e8f329cb7dd30..2ad942fb1e236e694eb50538ac71a33a90e8d40a 100644 (file)
@@ -56,9 +56,11 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
                audit_log_format(ab, " name=");
                audit_log_untrustedstring(ab, fname);
        }
-       if (inode)
-               audit_log_format(ab, " dev=%s ino=%lu",
-                                inode->i_sb->s_id, inode->i_ino);
+       if (inode) {
+               audit_log_format(ab, " dev=");
+               audit_log_untrustedstring(ab, inode->i_sb->s_id);
+               audit_log_format(ab, " ino=%lu", inode->i_ino);
+       }
        audit_log_format(ab, " res=%d", !result ? 0 : 1);
        audit_log_end(ab);
 }
index d661afbe474c2fce8f74907869be0a644c5789c9..d45061d02feec0d8b3e55f356d81df41580ad506 100644 (file)
@@ -99,6 +99,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
                            struct inode *inode, enum ima_hooks func, int mask)
 {
        struct task_struct *tsk = current;
+       const struct cred *cred = current_cred();
        int i;
 
        if ((rule->flags & IMA_FUNC) && rule->func != func)
@@ -108,7 +109,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
        if ((rule->flags & IMA_FSMAGIC)
            && rule->fsmagic != inode->i_sb->s_magic)
                return false;
-       if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
+       if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
                return false;
        for (i = 0; i < MAX_LSM_RULES; i++) {
                int rc = 0;
index 4da6ba81d1532aa4690cc95b99ba682ddb0254b1..7a25ecec5aaac6b8d00c2bf0f926deaeea561163 100644 (file)
@@ -51,7 +51,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
 #define INTEGRITY_KEYRING_IMA          2
 #define INTEGRITY_KEYRING_MAX          3
 
-#ifdef CONFIG_INTEGRITY_DIGSIG
+#ifdef CONFIG_INTEGRITY_SIGNATURE
 
 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
                                        const char *digest, int digestlen);
@@ -65,7 +65,7 @@ static inline int integrity_digsig_verify(const unsigned int id,
        return -EOPNOTSUPP;
 }
 
-#endif /* CONFIG_INTEGRITY_DIGSIG */
+#endif /* CONFIG_INTEGRITY_SIGNATURE */
 
 /* set during initialization */
 extern int iint_initialized;
index 41144f71d6154f612570f8f2c5243269becf68a4..2d1bb8af7696d5d431394cfbe8ac6d5e40f24da2 100644 (file)
@@ -314,7 +314,7 @@ static struct key *request_user_key(const char *master_desc, u8 **master_key,
                goto error;
 
        down_read(&ukey->sem);
-       upayload = rcu_dereference(ukey->payload.data);
+       upayload = ukey->payload.data;
        *master_key = upayload->data;
        *master_keylen = upayload->datalen;
 error:
@@ -810,7 +810,7 @@ static int encrypted_instantiate(struct key *key, const void *data,
                goto out;
        }
 
-       rcu_assign_pointer(key->payload.data, epayload);
+       rcu_assign_keypointer(key, epayload);
 out:
        kfree(datablob);
        return ret;
@@ -874,7 +874,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
        memcpy(new_epayload->payload_data, epayload->payload_data,
               epayload->payload_datalen);
 
-       rcu_assign_pointer(key->payload.data, new_epayload);
+       rcu_assign_keypointer(key, new_epayload);
        call_rcu(&epayload->rcu, encrypted_rcu_free);
 out:
        kfree(buf);
index df87272e3f519ca6909e9f9e4ab8132554ae9abb..013f7e5d3a2fce42d026fd87a4a0d6e94af1d53f 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/module.h>
 #include <linux/err.h>
 #include <keys/trusted-type.h>
+#include <keys/encrypted-type.h>
+#include "encrypted.h"
 
 /*
  * request_trusted_key - request the trusted key
@@ -37,7 +39,7 @@ struct key *request_trusted_key(const char *trusted_desc,
                goto error;
 
        down_read(&tkey->sem);
-       tpayload = rcu_dereference(tkey->payload.data);
+       tpayload = tkey->payload.data;
        *master_key = tpayload->key;
        *master_keylen = tpayload->key_len;
 error:
index bf4d8da5a79502f626a849473e4af18e229eb074..a42b45531aac173a337498cfc26fd09ded18baee 100644 (file)
@@ -145,7 +145,9 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
        if (!klist)
                goto unlock_dont_gc;
 
-       for (loop = klist->nkeys - 1; loop >= 0; loop--) {
+       loop = klist->nkeys;
+       smp_rmb();
+       for (loop--; loop >= 0; loop--) {
                key = klist->keys[loop];
                if (test_bit(KEY_FLAG_DEAD, &key->flags) ||
                    (key->expiry > 0 && key->expiry <= limit))
index c7a7caec4830b33e414ac7fa3b665633b853a080..65647f825584becdfa1db48302be9ba5e33df88e 100644 (file)
@@ -33,6 +33,7 @@
 
 extern struct key_type key_type_dead;
 extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
 
 /*****************************************************************************/
 /*
index 4f64c7267afb64332db0e6218754a8d17190c870..7ada8019be1f2c08314fe0c8c14d3058a1ee26ea 100644 (file)
@@ -999,6 +999,7 @@ void __init key_init(void)
        list_add_tail(&key_type_keyring.link, &key_types_list);
        list_add_tail(&key_type_dead.link, &key_types_list);
        list_add_tail(&key_type_user.link, &key_types_list);
+       list_add_tail(&key_type_logon.link, &key_types_list);
 
        /* record the root user tracking */
        rb_link_node(&root_key_user.node,
index 37a7f3b28852e098f57ab1cd98eb2eccdad5c7c5..d605f75292e4390da5d7f8cd763266004288ecf2 100644 (file)
@@ -319,7 +319,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
        struct key *keyring, *key;
        key_ref_t key_ref;
        long err;
-       int sp, kix;
+       int sp, nkeys, kix;
 
        keyring = key_ref_to_ptr(keyring_ref);
        possessed = is_key_possessed(keyring_ref);
@@ -380,7 +380,9 @@ descend:
                goto not_this_keyring;
 
        /* iterate through the keys in this keyring first */
-       for (kix = 0; kix < keylist->nkeys; kix++) {
+       nkeys = keylist->nkeys;
+       smp_rmb();
+       for (kix = 0; kix < nkeys; kix++) {
                key = keylist->keys[kix];
                kflags = key->flags;
 
@@ -421,7 +423,9 @@ descend:
        /* search through the keyrings nested in this one */
        kix = 0;
 ascend:
-       for (; kix < keylist->nkeys; kix++) {
+       nkeys = keylist->nkeys;
+       smp_rmb();
+       for (; kix < nkeys; kix++) {
                key = keylist->keys[kix];
                if (key->type != &key_type_keyring)
                        continue;
@@ -515,7 +519,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
        struct keyring_list *klist;
        unsigned long possessed;
        struct key *keyring, *key;
-       int loop;
+       int nkeys, loop;
 
        keyring = key_ref_to_ptr(keyring_ref);
        possessed = is_key_possessed(keyring_ref);
@@ -524,7 +528,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
 
        klist = rcu_dereference(keyring->payload.subscriptions);
        if (klist) {
-               for (loop = 0; loop < klist->nkeys; loop++) {
+               nkeys = klist->nkeys;
+               smp_rmb();
+               for (loop = 0; loop < nkeys ; loop++) {
                        key = klist->keys[loop];
 
                        if (key->type == ktype &&
@@ -622,7 +628,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
 
        struct keyring_list *keylist;
        struct key *subtree, *key;
-       int sp, kix, ret;
+       int sp, nkeys, kix, ret;
 
        rcu_read_lock();
 
@@ -645,7 +651,9 @@ descend:
 
 ascend:
        /* iterate through the remaining keys in this keyring */
-       for (; kix < keylist->nkeys; kix++) {
+       nkeys = keylist->nkeys;
+       smp_rmb();
+       for (; kix < nkeys; kix++) {
                key = keylist->keys[kix];
 
                if (key == A)
index 0ed5fdf238a22c6712e5375207f5bd6d8a168ef6..2d5d041f2049f323e5072c701f068d695f3f2c6c 100644 (file)
@@ -993,7 +993,7 @@ out:
        kfree(datablob);
        kfree(options);
        if (!ret)
-               rcu_assign_pointer(key->payload.data, payload);
+               rcu_assign_keypointer(key, payload);
        else
                kfree(payload);
        return ret;
@@ -1067,7 +1067,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen)
                        goto out;
                }
        }
-       rcu_assign_pointer(key->payload.data, new_p);
+       rcu_assign_keypointer(key, new_p);
        call_rcu(&p->rcu, trusted_rcu_free);
 out:
        kfree(datablob);
index 69ff52c08e97bb0eab715b1ea61c709e4f80faad..c7660a25a3e4502673714b39553a0d9d00873672 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/uaccess.h>
 #include "internal.h"
 
+static int logon_vet_description(const char *desc);
+
 /*
  * user defined keys take an arbitrary string as the description and an
  * arbitrary blob of data as the payload
@@ -35,6 +37,24 @@ struct key_type key_type_user = {
 
 EXPORT_SYMBOL_GPL(key_type_user);
 
+/*
+ * This key type is essentially the same as key_type_user, but it does
+ * not define a .read op. This is suitable for storing username and
+ * password pairs in the keyring that you do not want to be readable
+ * from userspace.
+ */
+struct key_type key_type_logon = {
+       .name                   = "logon",
+       .instantiate            = user_instantiate,
+       .update                 = user_update,
+       .match                  = user_match,
+       .revoke                 = user_revoke,
+       .destroy                = user_destroy,
+       .describe               = user_describe,
+       .vet_description        = logon_vet_description,
+};
+EXPORT_SYMBOL_GPL(key_type_logon);
+
 /*
  * instantiate a user defined key
  */
@@ -59,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen)
        /* attach the data */
        upayload->datalen = datalen;
        memcpy(upayload->data, data, datalen);
-       rcu_assign_pointer(key->payload.data, upayload);
+       rcu_assign_keypointer(key, upayload);
        ret = 0;
 
 error:
@@ -98,7 +118,7 @@ int user_update(struct key *key, const void *data, size_t datalen)
        if (ret == 0) {
                /* attach the new data, displacing the old */
                zap = key->payload.data;
-               rcu_assign_pointer(key->payload.data, upayload);
+               rcu_assign_keypointer(key, upayload);
                key->expiry = 0;
        }
 
@@ -133,7 +153,7 @@ void user_revoke(struct key *key)
        key_payload_reserve(key, 0);
 
        if (upayload) {
-               rcu_assign_pointer(key->payload.data, NULL);
+               rcu_assign_keypointer(key, NULL);
                kfree_rcu(upayload, rcu);
        }
 }
@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
 }
 
 EXPORT_SYMBOL_GPL(user_read);
+
+/* Vet the description for a "logon" key */
+static int logon_vet_description(const char *desc)
+{
+       char *p;
+
+       /* require a "qualified" description string */
+       p = strchr(desc, ':');
+       if (!p)
+               return -EINVAL;
+
+       /* also reject description with ':' as first char */
+       if (p == desc)
+               return -EINVAL;
+
+       return 0;
+}
index 7bd6f138236b3a010d457ab473ea73fd02641c8c..293b8c45b1d1bbf9a28edff35001b8c02eb09191 100644 (file)
@@ -232,13 +232,14 @@ static void dump_common_audit_data(struct audit_buffer *ab,
        case LSM_AUDIT_DATA_PATH: {
                struct inode *inode;
 
-               audit_log_d_path(ab, "path=", &a->u.path);
+               audit_log_d_path(ab, " path=", &a->u.path);
 
                inode = a->u.path.dentry->d_inode;
-               if (inode)
-                       audit_log_format(ab, " dev=%s ino=%lu",
-                                       inode->i_sb->s_id,
-                                       inode->i_ino);
+               if (inode) {
+                       audit_log_format(ab, " dev=");
+                       audit_log_untrustedstring(ab, inode->i_sb->s_id);
+                       audit_log_format(ab, " ino=%lu", inode->i_ino);
+               }
                break;
        }
        case LSM_AUDIT_DATA_DENTRY: {
@@ -248,10 +249,11 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
 
                inode = a->u.dentry->d_inode;
-               if (inode)
-                       audit_log_format(ab, " dev=%s ino=%lu",
-                                       inode->i_sb->s_id,
-                                       inode->i_ino);
+               if (inode) {
+                       audit_log_format(ab, " dev=");
+                       audit_log_untrustedstring(ab, inode->i_sb->s_id);
+                       audit_log_format(ab, " ino=%lu", inode->i_ino);
+               }
                break;
        }
        case LSM_AUDIT_DATA_INODE: {
@@ -266,8 +268,9 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                                         dentry->d_name.name);
                        dput(dentry);
                }
-               audit_log_format(ab, " dev=%s ino=%lu", inode->i_sb->s_id,
-                                inode->i_ino);
+               audit_log_format(ab, " dev=");
+               audit_log_untrustedstring(ab, inode->i_sb->s_id);
+               audit_log_format(ab, " ino=%lu", inode->i_ino);
                break;
        }
        case LSM_AUDIT_DATA_TASK:
@@ -315,7 +318,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                                                .dentry = u->dentry,
                                                .mnt = u->mnt
                                        };
-                                       audit_log_d_path(ab, "path=", &path);
+                                       audit_log_d_path(ab, " path=", &path);
                                        break;
                                }
                                if (!u->addr)
index 4a9b4b2eb755c0129d408b371ebb3f102b862662..867558c983349d144c5f46a729af55a2a72dbe0a 100644 (file)
@@ -492,13 +492,13 @@ static bool tomoyo_correct_word2(const char *string, size_t len)
                                if (d < '0' || d > '7' || e < '0' || e > '7')
                                        break;
                                c = tomoyo_make_byte(c, d, e);
-                               if (tomoyo_invalid(c))
-                                       continue; /* pattern is not \000 */
+                               if (c <= ' ' || c >= 127)
+                                       continue;
                        }
                        goto out;
                } else if (in_repetition && c == '/') {
                        goto out;
-               } else if (tomoyo_invalid(c)) {
+               } else if (c <= ' ' || c >= 127) {
                        goto out;
                }
        }
index 6fd9391b3a6cd1c4aeb60d791effd9edd985ac18..4fa1dbd8ee8381e1fbc4260c779cfecdea1d1923 100644 (file)
@@ -133,7 +133,7 @@ static int atmel_abdac_prepare_dma(struct atmel_abdac *dac,
        period_len = frames_to_bytes(runtime, runtime->period_size);
 
        cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
-                       period_len, DMA_TO_DEVICE);
+                       period_len, DMA_MEM_TO_DEV);
        if (IS_ERR(cdesc)) {
                dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n");
                return PTR_ERR(cdesc);
index 73516f69ac7ca8a33244cb300df8958ac2d77e20..61dade6983582ce415afdbe3cf88d208bb628c46 100644 (file)
@@ -102,7 +102,7 @@ static void atmel_ac97c_dma_capture_period_done(void *arg)
 
 static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
                struct snd_pcm_substream *substream,
-               enum dma_data_direction direction)
+               enum dma_transfer_direction direction)
 {
        struct dma_chan                 *chan;
        struct dw_cyclic_desc           *cdesc;
@@ -118,7 +118,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
                return -EINVAL;
        }
 
-       if (direction == DMA_TO_DEVICE)
+       if (direction == DMA_MEM_TO_DEV)
                chan = chip->dma.tx_chan;
        else
                chan = chip->dma.rx_chan;
@@ -133,7 +133,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
                return PTR_ERR(cdesc);
        }
 
-       if (direction == DMA_TO_DEVICE) {
+       if (direction == DMA_MEM_TO_DEV) {
                cdesc->period_callback = atmel_ac97c_dma_playback_period_done;
                set_bit(DMA_TX_READY, &chip->flags);
        } else {
@@ -393,7 +393,7 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
        if (cpu_is_at32ap7000()) {
                if (!test_bit(DMA_TX_READY, &chip->flags))
                        retval = atmel_ac97c_prepare_dma(chip, substream,
-                                       DMA_TO_DEVICE);
+                                       DMA_MEM_TO_DEV);
        } else {
                /* Initialize and start the PDC */
                writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);
@@ -484,7 +484,7 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
        if (cpu_is_at32ap7000()) {
                if (!test_bit(DMA_RX_READY, &chip->flags))
                        retval = atmel_ac97c_prepare_dma(chip, substream,
-                                       DMA_FROM_DEVICE);
+                                       DMA_DEV_TO_MEM);
        } else {
                /* Initialize and start the PDC */
                writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);
index ad409381f8cca21370f4802b1a5044af2f946b71..b413ed05e74deae78fbd97809c99f0fd68f1ee46 100644 (file)
@@ -12,6 +12,9 @@ config SND_HWDEP
 config SND_RAWMIDI
        tristate
 
+config SND_COMPRESS_OFFLOAD
+       tristate
+
 # To be effective this also requires INPUT - users should say:
 #    select SND_JACK if INPUT=y || INPUT=SND
 # to avoid having to force INPUT on.
@@ -154,16 +157,6 @@ config SND_DYNAMIC_MINORS
 
          If you are unsure about this, say N here.
 
-config SND_COMPRESS_OFFLOAD
-       tristate "ALSA Compressed audio offload support"
-       default n
-       help
-         If you want support for offloading compressed audio and have such
-         a hardware, then you should say Y here and also to the DSP driver
-         of your platform.
-
-         If you are unsure about this, say N here.
-
 config SND_SUPPORT_OLD_API
        bool "Support old ALSA API"
        default y
index dac3633507c9631a300abb4d7f3c35bbaa3ddb5a..a68aed7fce0205462ce08183f560015eeb0060cb 100644 (file)
@@ -441,19 +441,22 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
                params = kmalloc(sizeof(*params), GFP_KERNEL);
                if (!params)
                        return -ENOMEM;
-               if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
-                       return -EFAULT;
+               if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
+                       retval = -EFAULT;
+                       goto out;
+               }
                retval = snd_compr_allocate_buffer(stream, params);
                if (retval) {
-                       kfree(params);
-                       return -ENOMEM;
+                       retval = -ENOMEM;
+                       goto out;
                }
                retval = stream->ops->set_params(stream, params);
                if (retval)
                        goto out;
                stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-       } else
+       } else {
                return -EPERM;
+       }
 out:
        kfree(params);
        return retval;
index e09f144177f502f6176139e3e2258890ae88a560..c99c6078be3376fa792f8b335e31f57a80a7c221 100644 (file)
@@ -22,7 +22,6 @@
 #include "emu8000_local.h"
 #include <asm/uaccess.h>
 #include <linux/moduleparam.h>
-#include <linux/moduleparam.h>
 
 static int emu8000_reset_addr;
 module_param(emu8000_reset_addr, int, 0444);
index 762bb108c51c139b71e93cf8d627ebae858a25d2..f13ad536b2d59fe19ab9826b5abc0c301d5133cf 100644 (file)
@@ -268,8 +268,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                card->shortname, chip->io, chip->irq);
 
        // (4) Alloc components.
+       err = snd_vortex_mixer(chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
        // ADB pcm.
-       if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
+       err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
+       if (err < 0) {
                snd_card_free(card);
                return err;
        }
@@ -299,11 +305,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return err;
        }
 #endif
-       // snd_ac97_mixer and Vortex mixer.
-       if ((err = snd_vortex_mixer(chip)) < 0) {
-               snd_card_free(card);
-               return err;
-       }
        if ((err = snd_vortex_midi(chip)) < 0) {
                snd_card_free(card);
                return err;
index 02f6e08f7592e8bcd6c539598f397ebbf88856aa..bb938153a964811b41f471f064fbd293fb660e77 100644 (file)
 #define MIX_SPDIF(x) (vortex->mixspdif[x])
 
 #define NR_WTPB 0x20           /* WT channels per each bank. */
+#define NR_PCM 0x10
 
 /* Structs */
 typedef struct {
index 0488633ea87474c608591601201030a65a1c91f5..0ef2f97122080f206699a01e32b7f1f1ce7b6825 100644 (file)
@@ -168,6 +168,7 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
                        runtime->hw = snd_vortex_playback_hw_adb;
 #ifdef CHIP_AU8830
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+                       VORTEX_IS_QUAD(vortex) &&
                        VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
                        runtime->hw.channels_max = 4;
                        snd_pcm_hw_constraint_list(runtime, 0,
index 5b68435d195ba29d530113dd8471f06ea5d8e64e..501501ef36a9d0133d8635795e617d1694ea4496 100644 (file)
@@ -762,16 +762,22 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
        /* Looks like the unsol event is incompatible with the standard
         * definition.  4bit tag is placed at 28 bit!
         */
-       switch (res >> 28) {
+       res >>= 28;
+       switch (res) {
        case ALC_MIC_EVENT:
                alc88x_simple_mic_automute(codec);
                break;
        default:
-               alc_sku_unsol_event(codec, res);
+               alc_exec_unsol_event(codec, res);
                break;
        }
 }
 
+static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       alc_exec_unsol_event(codec, res >> 28);
+}
+
 static void alc880_uniwill_p53_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -800,10 +806,11 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
        /* Looks like the unsol event is incompatible with the standard
         * definition.  4bit tag is placed at 28 bit!
         */
-       if ((res >> 28) == ALC_DCVOL_EVENT)
+       res >>= 28;
+       if (res == ALC_DCVOL_EVENT)
                alc880_uniwill_p53_dcvol_automute(codec);
        else
-               alc_sku_unsol_event(codec, res);
+               alc_exec_unsol_event(codec, res);
 }
 
 /*
@@ -1677,7 +1684,7 @@ static const struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_lg_ch_modes,
                .need_dac_fix = 1,
                .input_mux = &alc880_lg_capture_source,
-               .unsol_event = alc_sku_unsol_event,
+               .unsol_event = alc880_unsol_event,
                .setup = alc880_lg_setup,
                .init_hook = alc_hp_automute,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
index bdf0ed4ab3e24663284013856ed9f83a95c86acd..bb364a53f546bd65154115ce0cc81bc613f38f72 100644 (file)
@@ -730,6 +730,11 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
                alc889A_mb31_automute(codec);
 }
 
+static void alc882_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       alc_exec_unsol_event(codec, res >> 26);
+}
+
 /*
  * configuration and preset
  */
@@ -775,7 +780,7 @@ static const struct alc_config_preset alc882_presets[] = {
                        .channel_mode = alc885_mba21_ch_modes,
                        .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
                        .input_mux = &alc882_capture_source,
-                       .unsol_event = alc_sku_unsol_event,
+                       .unsol_event = alc882_unsol_event,
                        .setup = alc885_mba21_setup,
                        .init_hook = alc_hp_automute,
        },
@@ -791,7 +796,7 @@ static const struct alc_config_preset alc882_presets[] = {
                .input_mux = &alc882_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_sku_unsol_event,
+               .unsol_event = alc882_unsol_event,
                .setup = alc885_mbp3_setup,
                .init_hook = alc_hp_automute,
        },
@@ -806,7 +811,7 @@ static const struct alc_config_preset alc882_presets[] = {
                .input_mux = &mb5_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_sku_unsol_event,
+               .unsol_event = alc882_unsol_event,
                .setup = alc885_mb5_setup,
                .init_hook = alc_hp_automute,
        },
@@ -821,7 +826,7 @@ static const struct alc_config_preset alc882_presets[] = {
                .input_mux = &macmini3_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_sku_unsol_event,
+               .unsol_event = alc882_unsol_event,
                .setup = alc885_macmini3_setup,
                .init_hook = alc_hp_automute,
        },
@@ -836,7 +841,7 @@ static const struct alc_config_preset alc882_presets[] = {
                .input_mux = &alc889A_imac91_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_sku_unsol_event,
+               .unsol_event = alc882_unsol_event,
                .setup = alc885_imac91_setup,
                .init_hook = alc_hp_automute,
        },
index 4df72c0e8c37c9011cecff85cca8e834d74260de..c2c65f63bf068a0d39fbfd271be81d74c22d0459 100644 (file)
@@ -1447,7 +1447,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                for (i = 0; i < c->cvt_setups.used; i++) {
                        p = snd_array_elem(&c->cvt_setups, i);
                        if (!p->active && p->stream_tag == stream_tag &&
-                           get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+                           get_wcaps_type(get_wcaps(c, p->nid)) == type)
                                p->dirty = 1;
                }
        }
index 0852e204a4c8439e557bd553dcde3aae1f7c173a..95dfb687494144e54b191e3f7f4dbe7179bcf37d 100644 (file)
@@ -469,6 +469,7 @@ struct azx {
        unsigned int irq_pending_warned :1;
        unsigned int probing :1; /* codec probing phase */
        unsigned int snoop:1;
+       unsigned int align_buffer_size:1;
 
        /* for debugging */
        unsigned int last_cmd[AZX_MAX_CODECS];
@@ -1690,7 +1691,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        runtime->hw.rates = hinfo->rates;
        snd_pcm_limit_hw_rates(runtime);
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-       if (align_buffer_size)
+       if (chip->align_buffer_size)
                /* constrain buffer sizes to be multiple of 128
                   bytes. This is more efficient in terms of memory
                   access but isn't required by the HDA spec and
@@ -2498,6 +2499,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
@@ -2772,8 +2774,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        }
 
        /* disable buffer size rounding to 128-byte multiples if supported */
+       chip->align_buffer_size = align_buffer_size;
        if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
-               align_buffer_size = 0;
+               chip->align_buffer_size = 0;
 
        /* allow 64bit DMA address if supported by H/W */
        if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
index d8a35da0803ff853becddd8c899e2cddba8b6293..9d819c4b4923d18c67447953b02395408e923afc 100644 (file)
@@ -282,7 +282,8 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
 
 static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
-                        const struct auto_pin_cfg *cfg)
+                        const struct auto_pin_cfg *cfg,
+                        char *lastname, int *lastidx)
 {
        unsigned int def_conf, conn;
        char name[44];
@@ -298,6 +299,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
                return 0;
 
        snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
+       if (!strcmp(name, lastname) && idx == *lastidx)
+               idx++;
+       strncpy(lastname, name, 44);
+       *lastidx = idx;
        err = snd_hda_jack_add_kctl(codec, nid, name, idx);
        if (err < 0)
                return err;
@@ -311,41 +316,42 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
                           const struct auto_pin_cfg *cfg)
 {
        const hda_nid_t *p;
-       int i, err;
+       int i, err, lastidx = 0;
+       char lastname[44] = "";
 
        for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
                if (*p == *cfg->line_out_pins) /* might be duplicated */
                        break;
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
                if (*p == *cfg->line_out_pins) /* might be duplicated */
                        break;
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0; i < cfg->num_inputs; i++) {
-               err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
+               err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
-               err = add_jack_kctl(codec, *p, cfg);
+               err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
                if (err < 0)
                        return err;
        }
-       err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
+       err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);
        if (err < 0)
                return err;
-       err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
+       err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);
        if (err < 0)
                return err;
        return 0;
index 35abe3c6290884f1e842d3bd1caa5ccef955de88..21d91d580da8b9e29091dca8ad5d91440b38797a 100644 (file)
@@ -728,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,
 
        err = chipio_read(codec, REG_CODEC_MUTE, &data);
        if (err < 0)
-               return err;
+               goto exit;
 
        /* *valp 0 is mute, 1 is unmute */
        data = (data & 0x7f) | (*valp ? 0 : 0x80);
-       chipio_write(codec, REG_CODEC_MUTE, data);
+       err = chipio_write(codec, REG_CODEC_MUTE, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        spec->curr_hp_switch = *valp;
 
+ exit:
        snd_hda_power_down(codec);
-       return 1;
+       return err < 0 ? err : 1;
 }
 
 static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol,
@@ -770,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol,
 
        err = chipio_read(codec, REG_CODEC_MUTE, &data);
        if (err < 0)
-               return err;
+               goto exit;
 
        /* *valp 0 is mute, 1 is unmute */
        data = (data & 0xef) | (*valp ? 0 : 0x10);
-       chipio_write(codec, REG_CODEC_MUTE, data);
+       err = chipio_write(codec, REG_CODEC_MUTE, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        spec->curr_speaker_switch = *valp;
 
+ exit:
        snd_hda_power_down(codec);
-       return 1;
+       return err < 0 ? err : 1;
 }
 
 static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol,
@@ -819,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol,
 
        err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data);
        if (err < 0)
-               return err;
+               goto exit;
 
        val = 31 - left_vol;
        data = (data & 0xe0) | val;
-       chipio_write(codec, REG_CODEC_HP_VOL_L, data);
+       err = chipio_write(codec, REG_CODEC_HP_VOL_L, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        val = 31 - right_vol;
        data = (data & 0xe0) | val;
-       chipio_write(codec, REG_CODEC_HP_VOL_R, data);
+       err = chipio_write(codec, REG_CODEC_HP_VOL_R, data);
        if (err < 0)
-               return err;
+               goto exit;
 
        spec->curr_hp_volume[0] = left_vol;
        spec->curr_hp_volume[1] = right_vol;
 
+ exit:
        snd_hda_power_down(codec);
-       return 1;
+       return err < 0 ? err : 1;
 }
 
 static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid)
@@ -936,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec)
                if (err < 0)
                        return err;
                err = add_in_volume(codec, spec->dig_in, "IEC958");
+               if (err < 0)
+                       return err;
        }
        return 0;
 }
index 0e99357e822c201a03ffeadf451e9cc29e2001c0..bc5a993d11461868a2115d5b81efec25114a9996 100644 (file)
@@ -988,8 +988,10 @@ static void cs_automic(struct hda_codec *codec)
                        change_cur_input(codec, !spec->automic_idx, 0);
        } else {
                if (present) {
-                       spec->last_input = spec->cur_input;
-                       spec->cur_input = spec->automic_idx;
+                       if (spec->cur_input != spec->automic_idx) {
+                               spec->last_input = spec->cur_input;
+                               spec->cur_input = spec->automic_idx;
+                       }
                } else  {
                        spec->cur_input = spec->last_input;
                }
index 8a32a69c83c330939b18f10f2cd3a6c9cfc10ebe..a7a5733aa4d20d2ea25edf104e4568b4e42cab3d 100644 (file)
@@ -3027,7 +3027,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
-       SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO),
        SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO),
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
index 5e82acf77c5ae84cbd3f77b1d3b8165246a8df22..3647baa9bfed302b63e6fcaf8f9726da7d050389 100644 (file)
@@ -80,6 +80,8 @@ enum {
        ALC_AUTOMUTE_MIXER,     /* mute/unmute mixer widget AMP */
 };
 
+#define MAX_VOL_NIDS   0x40
+
 struct alc_spec {
        /* codec parameterization */
        const struct snd_kcontrol_new *mixers[5];       /* mixer arrays */
@@ -118,8 +120,8 @@ struct alc_spec {
        const hda_nid_t *capsrc_nids;
        hda_nid_t dig_in_nid;           /* digital-in NID; optional */
        hda_nid_t mixer_nid;            /* analog-mixer NID */
-       DECLARE_BITMAP(vol_ctls, 0x20 << 1);
-       DECLARE_BITMAP(sw_ctls, 0x20 << 1);
+       DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
+       DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
 
        /* capture setup for dynamic dual-adc switch */
        hda_nid_t cur_adc;
@@ -177,6 +179,7 @@ struct alc_spec {
        unsigned int detect_lo:1;       /* Line-out detection enabled */
        unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
        unsigned int automute_lo_possible:1;      /* there are line outs and HP */
+       unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
 
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
@@ -185,7 +188,6 @@ struct alc_spec {
        unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
        unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
        unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
-       unsigned int use_jack_tbl:1; /* 1 for model=auto */
 
        /* auto-mute control */
        int automute_mode;
@@ -496,13 +498,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
 
        for (i = 0; i < num_pins; i++) {
                hda_nid_t nid = pins[i];
+               unsigned int val;
                if (!nid)
                        break;
                switch (spec->automute_mode) {
                case ALC_AUTOMUTE_PIN:
+                       /* don't reset VREF value in case it's controlling
+                        * the amp (see alc861_fixup_asus_amp_vref_0f())
+                        */
+                       if (spec->keep_vref_in_automute) {
+                               val = snd_hda_codec_read(codec, nid, 0,
+                                       AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+                               val &= ~PIN_HP;
+                       } else
+                               val = 0;
+                       val |= pin_bits;
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                           pin_bits);
+                                           val);
                        break;
                case ALC_AUTOMUTE_AMP:
                        snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -621,17 +634,10 @@ static void alc_mic_automute(struct hda_codec *codec)
                alc_mux_select(codec, 0, spec->int_mic_idx, false);
 }
 
-/* unsolicited event for HP jack sensing */
-static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+/* handle the specified unsol action (ALC_XXX_EVENT) */
+static void alc_exec_unsol_event(struct hda_codec *codec, int action)
 {
-       struct alc_spec *spec = codec->spec;
-       if (codec->vendor_id == 0x10ec0880)
-               res >>= 28;
-       else
-               res >>= 26;
-       if (spec->use_jack_tbl)
-               res = snd_hda_jack_get_action(codec, res);
-       switch (res) {
+       switch (action) {
        case ALC_HP_EVENT:
                alc_hp_automute(codec);
                break;
@@ -645,6 +651,17 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
        snd_hda_jack_report_sync(codec);
 }
 
+/* unsolicited event for HP jack sensing */
+static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       if (codec->vendor_id == 0x10ec0880)
+               res >>= 28;
+       else
+               res >>= 26;
+       res = snd_hda_jack_get_action(codec, res);
+       alc_exec_unsol_event(codec, res);
+}
+
 /* call init functions of standard auto-mute helpers */
 static void alc_inithook(struct hda_codec *codec)
 {
@@ -1840,6 +1857,8 @@ static const char * const alc_slave_vols[] = {
        "Speaker Playback Volume",
        "Mono Playback Volume",
        "Line-Out Playback Volume",
+       "CLFE Playback Volume",
+       "Bass Speaker Playback Volume",
        "PCM Playback Volume",
        NULL,
 };
@@ -1855,6 +1874,8 @@ static const char * const alc_slave_sws[] = {
        "Mono Playback Switch",
        "IEC958 Playback Switch",
        "Line-Out Playback Switch",
+       "CLFE Playback Switch",
+       "Bass Speaker Playback Switch",
        "PCM Playback Switch",
        NULL,
 };
@@ -1883,7 +1904,7 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = {
 };
 #endif
 
-static int alc_build_controls(struct hda_codec *codec)
+static int __alc_build_controls(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct snd_kcontrol *kctl = NULL;
@@ -2029,11 +2050,16 @@ static int alc_build_controls(struct hda_codec *codec)
 
        alc_free_kctls(codec); /* no longer needed */
 
-       err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+       return 0;
+}
+
+static int alc_build_controls(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       int err = __alc_build_controls(codec);
        if (err < 0)
                return err;
-
-       return 0;
+       return snd_hda_jack_add_kctls(codec, &spec->autocfg);
 }
 
 
@@ -2298,7 +2324,7 @@ static int alc_build_pcms(struct hda_codec *codec)
                 "%s Analog", codec->chip_name);
        info->name = spec->stream_name_analog;
 
-       if (spec->multiout.dac_nids > 0) {
+       if (spec->multiout.num_dacs > 0) {
                p = spec->stream_analog_playback;
                if (!p)
                        p = &alc_pcm_analog_playback;
@@ -3125,7 +3151,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 static inline unsigned int get_ctl_pos(unsigned int data)
 {
        hda_nid_t nid = get_amp_nid_(data);
-       unsigned int dir = get_amp_direction_(data);
+       unsigned int dir;
+       if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
+               return 0;
+       dir = get_amp_direction_(data);
        return (nid << 1) | dir;
 }
 
@@ -3233,7 +3262,7 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
        int i, err, noutputs;
 
        noutputs = cfg->line_outs;
-       if (spec->multi_ios > 0)
+       if (spec->multi_ios > 0 && cfg->line_outs < 3)
                noutputs += spec->multi_ios;
 
        for (i = 0; i < noutputs; i++) {
@@ -3904,7 +3933,6 @@ static void set_capture_mixer(struct hda_codec *codec)
 static void alc_auto_init_std(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       spec->use_jack_tbl = 1;
        alc_auto_init_multi_out(codec);
        alc_auto_init_extra_out(codec);
        alc_auto_init_analog_input(codec);
@@ -4168,6 +4196,8 @@ static int patch_alc880(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC_MODEL_AUTO)
                spec->init_hook = alc_auto_init_std;
+       else
+               codec->patch_ops.build_controls = __alc_build_controls;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc880_loopbacks;
@@ -4297,6 +4327,8 @@ static int patch_alc260(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC_MODEL_AUTO)
                spec->init_hook = alc_auto_init_std;
+       else
+               codec->patch_ops.build_controls = __alc_build_controls;
        spec->shutup = alc_eapd_shutup;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
@@ -4347,6 +4379,7 @@ enum {
        ALC882_FIXUP_ACER_ASPIRE_8930G,
        ALC882_FIXUP_ASPIRE_8930G_VERBS,
        ALC885_FIXUP_MACPRO_GPIO,
+       ALC889_FIXUP_DAC_ROUTE,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -4400,6 +4433,31 @@ static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
        alc882_gpio_mute(codec, 1, 0);
 }
 
+/* Fix the connection of some pins for ALC889:
+ * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
+ * work correctly (bko#42740)
+ */
+static void alc889_fixup_dac_route(struct hda_codec *codec,
+                                  const struct alc_fixup *fix, int action)
+{
+       if (action == ALC_FIXUP_ACT_PRE_PROBE) {
+               /* fake the connections during parsing the tree */
+               hda_nid_t conn1[2] = { 0x0c, 0x0d };
+               hda_nid_t conn2[2] = { 0x0e, 0x0f };
+               snd_hda_override_conn_list(codec, 0x14, 2, conn1);
+               snd_hda_override_conn_list(codec, 0x15, 2, conn1);
+               snd_hda_override_conn_list(codec, 0x18, 2, conn2);
+               snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
+       } else if (action == ALC_FIXUP_ACT_PROBE) {
+               /* restore the connections */
+               hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
+               snd_hda_override_conn_list(codec, 0x14, 5, conn);
+               snd_hda_override_conn_list(codec, 0x15, 5, conn);
+               snd_hda_override_conn_list(codec, 0x18, 5, conn);
+               snd_hda_override_conn_list(codec, 0x1a, 5, conn);
+       }
+}
+
 static const struct alc_fixup alc882_fixups[] = {
        [ALC882_FIXUP_ABIT_AW9D_MAX] = {
                .type = ALC_FIXUP_PINS,
@@ -4547,6 +4605,10 @@ static const struct alc_fixup alc882_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc885_fixup_macpro_gpio,
        },
+       [ALC889_FIXUP_DAC_ROUTE] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc889_fixup_dac_route,
+       },
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -4571,6 +4633,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
                      ALC882_FIXUP_ACER_ASPIRE_4930G),
        SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
+       SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
        SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
        SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
@@ -4691,6 +4754,8 @@ static int patch_alc882(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC_MODEL_AUTO)
                spec->init_hook = alc_auto_init_std;
+       else
+               codec->patch_ops.build_controls = __alc_build_controls;
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
@@ -4722,7 +4787,6 @@ enum {
        ALC262_FIXUP_FSC_H270,
        ALC262_FIXUP_HP_Z200,
        ALC262_FIXUP_TYAN,
-       ALC262_FIXUP_TOSHIBA_RX1,
        ALC262_FIXUP_LENOVO_3000,
        ALC262_FIXUP_BENQ,
        ALC262_FIXUP_BENQ_T31,
@@ -4752,16 +4816,6 @@ static const struct alc_fixup alc262_fixups[] = {
                        { }
                }
        },
-       [ALC262_FIXUP_TOSHIBA_RX1] = {
-               .type = ALC_FIXUP_PINS,
-               .v.pins = (const struct alc_pincfg[]) {
-                       { 0x14, 0x90170110 }, /* speaker */
-                       { 0x15, 0x0421101f }, /* HP */
-                       { 0x1a, 0x40f000f0 }, /* N/A */
-                       { 0x1b, 0x40f000f0 }, /* N/A */
-                       { 0x1e, 0x40f000f0 }, /* N/A */
-               }
-       },
        [ALC262_FIXUP_LENOVO_3000] = {
                .type = ALC_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -4794,8 +4848,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
        SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
        SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
        SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
-       SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
-                     ALC262_FIXUP_TOSHIBA_RX1),
        SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
        SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
        SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
@@ -5364,7 +5416,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
                      ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
@@ -5573,8 +5624,28 @@ static const struct hda_amp_list alc861_loopbacks[] = {
 /* Pin config fixes */
 enum {
        PINFIX_FSC_AMILO_PI1505,
+       PINFIX_ASUS_A6RP,
 };
 
+/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
+static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
+                       const struct alc_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int val;
+
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       val = snd_hda_codec_read(codec, 0x0f, 0,
+                                AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+       if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
+               val |= AC_PINCTL_IN_EN;
+       val |= AC_PINCTL_VREF_50;
+       snd_hda_codec_write(codec, 0x0f, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+       spec->keep_vref_in_automute = 1;
+}
+
 static const struct alc_fixup alc861_fixups[] = {
        [PINFIX_FSC_AMILO_PI1505] = {
                .type = ALC_FIXUP_PINS,
@@ -5584,9 +5655,16 @@ static const struct alc_fixup alc861_fixups[] = {
                        { }
                }
        },
+       [PINFIX_ASUS_A6RP] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc861_fixup_asus_amp_vref_0f,
+       },
 };
 
 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+       SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
+       SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),   
+       SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
        SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
        {}
 };
index 87e684fa830f83df49bfec3aa5e894d8c97bfa07..6345df131a005a7202b696ccea02fb5dbfeb0898 100644 (file)
@@ -1596,7 +1596,7 @@ static const struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
                                "Dell Studio 1557", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
-                               "Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+                               "Dell Studio XPS 1645", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
                                "Dell Studio 1558", STAC_DELL_M6_DMIC),
        {} /* terminator */
@@ -1608,7 +1608,7 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
        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),
+                     "Alienware M17x R3", STAC_DELL_EQ),
        {} /* terminator */
 };
 
@@ -4163,13 +4163,15 @@ static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
        return 1;
 }
 
-static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
+static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
 {
        int i;
        for (i = 0; i < cfg->hp_outs; i++)
                if (cfg->hp_pins[i] == nid)
                        return 1; /* nid is a HP-Out */
-
+       for (i = 0; i < cfg->line_outs; i++)
+               if (cfg->line_out_pins[i] == nid)
+                       return 1; /* nid is a line-Out */
        return 0; /* nid is not a HP-Out */
 };
 
@@ -4375,7 +4377,7 @@ static int stac92xx_init(struct hda_codec *codec)
                        continue;
                }
 
-               if (is_nid_hp_pin(cfg, nid))
+               if (is_nid_out_jack_pin(cfg, nid))
                        continue; /* already has an unsol event */
 
                pinctl = snd_hda_codec_read(codec, nid, 0,
@@ -4868,7 +4870,14 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
                        /* BIOS bug: unfilled OEM string */
                        if (strstr(dev->name, "HP_Mute_LED_P_G")) {
                                set_hp_led_gpio(codec);
-                               spec->gpio_led_polarity = 1;
+                               switch (codec->subsystem_id) {
+                               case 0x103c148a:
+                                       spec->gpio_led_polarity = 0;
+                                       break;
+                               default:
+                                       spec->gpio_led_polarity = 1;
+                                       break;
+                               }
                                return 1;
                        }
                }
@@ -5069,9 +5078,9 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
                                spec->gpio_dir, spec->gpio_data);
        } else {
                notmtd_lvl = spec->gpio_led_polarity ?
-                               AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
+                               AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
                muted_lvl = spec->gpio_led_polarity ?
-                               AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
+                               AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50;
                spec->vref_led = muted ? muted_lvl : notmtd_lvl;
                stac_vrefout_set(codec, spec->vref_mute_led_nid,
                                 spec->vref_led);
index 03e63fed9caf7d9e8342373901a5086f884122d9..dff9a00ee8fbf136101243c031d3cd3222cff291 100644 (file)
@@ -199,6 +199,9 @@ struct via_spec {
        unsigned int no_pin_power_ctl;
        enum VIA_HDA_CODEC codec_type;
 
+       /* analog low-power control */
+       bool alc_mode;
+
        /* smart51 setup */
        unsigned int smart51_nums;
        hda_nid_t smart51_pins[2];
@@ -663,6 +666,9 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
        /* init input-src */
        for (i = 0; i < spec->num_adc_nids; i++) {
                int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx;
+               /* secondary ADCs must have the unique MUX */
+               if (i > 0 && !spec->mux_nids[i])
+                       break;
                if (spec->mux_nids[adc_idx]) {
                        int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx;
                        snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
@@ -687,6 +693,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
        }
 }
 
+static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
+                              unsigned int parm)
+{
+       if (snd_hda_codec_read(codec, nid, 0,
+                              AC_VERB_GET_POWER_STATE, 0) == parm)
+               return;
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
 static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
                                unsigned int *affected_parm)
 {
@@ -709,7 +724,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
        } else
                parm = AC_PWRST_D3;
 
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, nid, parm);
 }
 
 static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
@@ -749,6 +764,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
                return 0;
        spec->no_pin_power_ctl = val;
        set_widgets_power_state(codec);
+       analog_low_current_mode(codec);
        return 1;
 }
 
@@ -1036,13 +1052,19 @@ static bool is_aa_path_mute(struct hda_codec *codec)
 }
 
 /* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec)
+static void __analog_low_current_mode(struct hda_codec *codec, bool force)
 {
        struct via_spec *spec = codec->spec;
        bool enable;
        unsigned int verb, parm;
 
-       enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
+       if (spec->no_pin_power_ctl)
+               enable = false;
+       else
+               enable = is_aa_path_mute(codec) && !spec->opened_streams;
+       if (enable == spec->alc_mode && !force)
+               return;
+       spec->alc_mode = enable;
 
        /* decide low current mode's verb & parameter */
        switch (spec->codec_type) {
@@ -1074,6 +1096,11 @@ static void analog_low_current_mode(struct hda_codec *codec)
        snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
 }
 
+static void analog_low_current_mode(struct hda_codec *codec)
+{
+       return __analog_low_current_mode(codec, false);
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -1446,6 +1473,7 @@ static int via_build_controls(struct hda_codec *codec)
        struct snd_kcontrol *kctl;
        int err, i;
 
+       spec->no_pin_power_ctl = 1;
        if (spec->set_widgets_power_state)
                if (!via_clone_control(spec, &via_pin_power_ctl_enum))
                        return -ENOMEM;
@@ -1499,10 +1527,6 @@ static int via_build_controls(struct hda_codec *codec)
                        return err;
        }
 
-       /* init power states */
-       set_widgets_power_state(codec);
-       analog_low_current_mode(codec);
-
        via_free_kctls(codec); /* no longer needed */
 
        err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
@@ -2295,10 +2319,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
 
        if (mux) {
                /* switch to D0 beofre change index */
-               if (snd_hda_codec_read(codec, mux, 0,
-                              AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
-                       snd_hda_codec_write(codec, mux, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, mux, AC_PWRST_D0);
                snd_hda_codec_write(codec, mux, 0,
                                    AC_VERB_SET_CONNECT_SEL,
                                    spec->inputs[cur].mux_idx);
@@ -2776,6 +2797,10 @@ static int via_init(struct hda_codec *codec)
        for (i = 0; i < spec->num_iverbs; i++)
                snd_hda_sequence_write(codec, spec->init_verbs[i]);
 
+       /* init power states */
+       set_widgets_power_state(codec);
+       __analog_low_current_mode(codec, true);
+
        via_auto_init_multi_out(codec);
        via_auto_init_hp_out(codec);
        via_auto_init_speaker_out(codec);
@@ -2922,9 +2947,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0;
        /* SW0 (17h), AIW 0/1 (13h/14h) */
-       snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x17, parm);
+       update_power_state(codec, 0x13, parm);
+       update_power_state(codec, 0x14, parm);
 
        /* outputs */
        /* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -2932,8 +2957,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
        set_pin_power_state(codec, 0x19, &parm);
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1b, &parm);
-       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* PW6 (22h), SW2 (26h), AOW2 (24h) */
        if (is_8ch) {
@@ -2941,20 +2966,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
                set_pin_power_state(codec, 0x22, &parm);
                if (spec->smart51_enabled)
                        set_pin_power_state(codec, 0x1a, &parm);
-               snd_hda_codec_write(codec, 0x26, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x24, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x26, parm);
+               update_power_state(codec, 0x24, parm);
        } else if (codec->vendor_id == 0x11064397) {
                /* PW7(23h), SW2(27h), AOW2(25h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x23, &parm);
                if (spec->smart51_enabled)
                        set_pin_power_state(codec, 0x1a, &parm);
-               snd_hda_codec_write(codec, 0x27, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x27, parm);
+               update_power_state(codec, 0x25, parm);
        }
 
        /* PW 3/4/7 (1ch/1dh/23h) */
@@ -2966,17 +2987,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
                set_pin_power_state(codec, 0x23, &parm);
 
        /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
-       snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x10, parm);
        if (is_8ch) {
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x27, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x25, parm);
+               update_power_state(codec, 0x27, parm);
        } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x25, parm);
 }
 
 static int patch_vt1708S(struct hda_codec *codec);
@@ -3149,10 +3166,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
        /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
-       snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x13, parm);
+       update_power_state(codec, 0x12, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x20, parm);
 
        /* outputs */
        /* PW 3/4 (16h/17h) */
@@ -3160,10 +3177,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
        set_pin_power_state(codec, 0x17, &parm);
        set_pin_power_state(codec, 0x16, &parm);
        /* MW0 (1ah), AOW 0/1 (10h/1dh) */
-       snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x1d, parm);
 }
 
 static int patch_vt1702(struct hda_codec *codec)
@@ -3228,52 +3244,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0;
        /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
-       snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* outputs */
        /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x27, &parm);
-       snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1a, parm);
+       update_power_state(codec, 0xb, parm);
 
        /* PW2 (26h), AOW2 (ah) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x26, &parm);
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x2b, &parm);
-       snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0xa, parm);
 
        /* PW0 (24h), AOW0 (8h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x24, &parm);
        if (!spec->hp_independent_mode) /* check for redirected HP */
                set_pin_power_state(codec, 0x28, &parm);
-       snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x8, parm);
        /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
-       snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
 
        /* PW1 (25h), AOW1 (9h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x25, &parm);
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x2a, &parm);
-       snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x9, parm);
 
        if (spec->hp_independent_mode) {
                /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x28, &parm);
-               snd_hda_codec_write(codec, 0x1b, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x34, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0xc, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x1b, parm);
+               update_power_state(codec, 0x34, parm);
+               update_power_state(codec, 0xc, parm);
        }
 }
 
@@ -3433,8 +3445,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        if (imux_is_smixer)
                parm = AC_PWRST_D0;
        /* SW0 (17h), AIW0(13h) */
-       snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x17, parm);
+       update_power_state(codec, 0x13, parm);
 
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x1e, &parm);
@@ -3442,12 +3454,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        if (spec->dmic_enabled)
                set_pin_power_state(codec, 0x22, &parm);
        else
-               snd_hda_codec_write(codec, 0x22, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x22, AC_PWRST_D3);
 
        /* SW2(26h), AIW1(14h) */
-       snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x26, parm);
+       update_power_state(codec, 0x14, parm);
 
        /* outputs */
        /* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -3456,8 +3467,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        /* Smart 5.1 PW2(1bh) */
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1b, &parm);
-       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* PW7 (23h), SW3 (27h), AOW3 (25h) */
        parm = AC_PWRST_D3;
@@ -3465,12 +3476,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        /* Smart 5.1 PW1(1ah) */
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1a, &parm);
-       snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x27, parm);
 
        /* Smart 5.1 PW5(1eh) */
        if (spec->smart51_enabled)
                set_pin_power_state(codec, 0x1e, &parm);
-       snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x25, parm);
 
        /* Mono out */
        /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
@@ -3486,9 +3497,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
                        mono_out = 1;
        }
        parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
-       snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x28, parm);
+       update_power_state(codec, 0x29, parm);
+       update_power_state(codec, 0x2a, parm);
 
        /* PW 3/4 (1ch/1dh) */
        parm = AC_PWRST_D3;
@@ -3496,15 +3507,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
        set_pin_power_state(codec, 0x1d, &parm);
        /* HP Independent Mode, power on AOW3 */
        if (spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x25, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x25, parm);
 
        /* force to D0 for internal Speaker */
        /* MW0 (16h), AOW0 (10h) */
-       snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
-                           imux_is_smixer ? AC_PWRST_D0 : parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
-                           mono_out ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+       update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
 }
 
 static int patch_vt1716S(struct hda_codec *codec)
@@ -3580,54 +3588,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
        set_pin_power_state(codec, 0x2b, &parm);
        parm = AC_PWRST_D0;
        /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
-       snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* outputs */
        /* AOW0 (8h)*/
-       snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x8, parm);
 
        if (spec->codec_type == VT1802) {
                /* PW4 (28h), MW4 (18h), MUX4(38h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x28, &parm);
-               snd_hda_codec_write(codec, 0x18, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x38, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x18, parm);
+               update_power_state(codec, 0x38, parm);
        } else {
                /* PW4 (26h), MW4 (1ch), MUX4(37h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x26, &parm);
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x37, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x1c, parm);
+               update_power_state(codec, 0x37, parm);
        }
 
        if (spec->codec_type == VT1802) {
                /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x25, &parm);
-               snd_hda_codec_write(codec, 0x15, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x35, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x15, parm);
+               update_power_state(codec, 0x35, parm);
        } else {
                /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
                parm = AC_PWRST_D3;
                set_pin_power_state(codec, 0x25, &parm);
-               snd_hda_codec_write(codec, 0x19, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x35, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x19, parm);
+               update_power_state(codec, 0x35, parm);
        }
 
        if (spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x9, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x9, AC_PWRST_D0);
 
        /* Class-D */
        /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
@@ -3637,12 +3636,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
        set_pin_power_state(codec, 0x24, &parm);
        parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
        if (spec->codec_type == VT1802)
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x14, parm);
        else
-               snd_hda_codec_write(codec, 0x18, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x34, parm);
 
        /* Mono Out */
        present = snd_hda_jack_detect(codec, 0x26);
@@ -3650,28 +3647,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
        parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
        if (spec->codec_type == VT1802) {
                /* PW15 (33h), MW8(1ch), MUX8(3ch) */
-               snd_hda_codec_write(codec, 0x33, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x3c, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x33, parm);
+               update_power_state(codec, 0x1c, parm);
+               update_power_state(codec, 0x3c, parm);
        } else {
                /* PW15 (31h), MW8(17h), MUX8(3bh) */
-               snd_hda_codec_write(codec, 0x31, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x17, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
-               snd_hda_codec_write(codec, 0x3b, 0,
-                                   AC_VERB_SET_POWER_STATE, parm);
+               update_power_state(codec, 0x31, parm);
+               update_power_state(codec, 0x17, parm);
+               update_power_state(codec, 0x3b, parm);
        }
        /* MW9 (21h) */
        if (imux_is_smixer || !is_aa_path_mute(codec))
-               snd_hda_codec_write(codec, 0x21, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x21, AC_PWRST_D0);
        else
-               snd_hda_codec_write(codec, 0x21, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x21, AC_PWRST_D3);
 }
 
 /* patch for vt2002P */
@@ -3731,30 +3720,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
        set_pin_power_state(codec, 0x2b, &parm);
        parm = AC_PWRST_D0;
        /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
-       snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
 
        /* outputs */
        /* AOW0 (8h)*/
-       snd_hda_codec_write(codec, 0x8, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+       update_power_state(codec, 0x8, AC_PWRST_D0);
 
        /* PW4 (28h), MW4 (18h), MUX4(38h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x28, &parm);
-       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x18, parm);
+       update_power_state(codec, 0x38, parm);
 
        /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x25, &parm);
-       snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x15, parm);
+       update_power_state(codec, 0x35, parm);
        if (spec->hp_independent_mode)
-               snd_hda_codec_write(codec, 0x9, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x9, AC_PWRST_D0);
 
        /* Internal Speaker */
        /* PW0 (24h), MW0(14h), MUX0(34h) */
@@ -3763,15 +3750,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x24, &parm);
        if (present) {
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-               snd_hda_codec_write(codec, 0x34, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x14, AC_PWRST_D3);
+               update_power_state(codec, 0x34, AC_PWRST_D3);
        } else {
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-               snd_hda_codec_write(codec, 0x34, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x14, AC_PWRST_D0);
+               update_power_state(codec, 0x34, AC_PWRST_D0);
        }
 
 
@@ -3782,26 +3765,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x31, &parm);
        if (present) {
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-               snd_hda_codec_write(codec, 0x3c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-               snd_hda_codec_write(codec, 0x3e, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+               update_power_state(codec, 0x1c, AC_PWRST_D3);
+               update_power_state(codec, 0x3c, AC_PWRST_D3);
+               update_power_state(codec, 0x3e, AC_PWRST_D3);
        } else {
-               snd_hda_codec_write(codec, 0x1c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-               snd_hda_codec_write(codec, 0x3c, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-               snd_hda_codec_write(codec, 0x3e, 0,
-                                   AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+               update_power_state(codec, 0x1c, AC_PWRST_D0);
+               update_power_state(codec, 0x3c, AC_PWRST_D0);
+               update_power_state(codec, 0x3e, AC_PWRST_D0);
        }
 
        /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
        parm = AC_PWRST_D3;
        set_pin_power_state(codec, 0x33, &parm);
-       snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
-       snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+       update_power_state(codec, 0x1d, parm);
+       update_power_state(codec, 0x3d, parm);
 
 }
 
index 9f3b01bb72c85abd7972629eaefe2c4b9402dc63..e0a4263baa2028f995b45741745dd703e2191875 100644 (file)
@@ -2100,6 +2100,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .name = "MSI P4 ATX 645 Ultra",
                .type = AC97_TUNE_HP_ONLY
        },
+       {
+               .subvendor = 0x161f,
+               .subdevice = 0x202f,
+               .name = "Gateway M520",
+               .type = AC97_TUNE_INV_EAPD
+       },
        {
                .subvendor = 0x161f,
                .subdevice = 0x203a,
index 26c7e8bcb229361b03397e52a59c37eb183ed18d..c0dbb52d45be5306799fb144e63e60d81348045e 100644 (file)
@@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
        mutex_lock(&chip->mutex);
        reg = oxygen_read_ac97(chip, codec, index);
        mutex_unlock(&chip->mutex);
-       value->value.integer.value[0] = 31 - (reg & 0x1f);
-       if (stereo)
-               value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
+       if (!stereo) {
+               value->value.integer.value[0] = 31 - (reg & 0x1f);
+       } else {
+               value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f);
+               value->value.integer.value[1] = 31 - (reg & 0x1f);
+       }
        return 0;
 }
 
@@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
 
        mutex_lock(&chip->mutex);
        oldreg = oxygen_read_ac97(chip, codec, index);
-       newreg = oldreg;
-       newreg = (newreg & ~0x1f) |
-               (31 - (value->value.integer.value[0] & 0x1f));
-       if (stereo)
-               newreg = (newreg & ~0x1f00) |
-                       ((31 - (value->value.integer.value[1] & 0x1f)) << 8);
-       else
-               newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8);
+       if (!stereo) {
+               newreg = oldreg & ~0x1f;
+               newreg |= 31 - (value->value.integer.value[0] & 0x1f);
+       } else {
+               newreg = oldreg & ~0x1f1f;
+               newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8;
+               newreg |= 31 - (value->value.integer.value[1] & 0x1f);
+       }
        change = newreg != oldreg;
        if (change)
                oxygen_write_ac97(chip, codec, index, newreg);
index 478303e6c2b0801c16c2ae52ee4eff0996fac472..63cff90706bf1749b9b7154f1c6ec81c903f68fd 100644 (file)
@@ -177,6 +177,7 @@ static void wm8776_registers_init(struct oxygen *chip)
        struct xonar_wm87x6 *data = chip->model_data;
 
        wm8776_write(chip, WM8776_RESET, 0);
+       wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK);
        wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
                     WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
        wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
index e57b89e8aa8926604425b2283d0238327609c63c..94ab728f5ca8b5a28b5a11ef9f36a723e3ebb707 100644 (file)
@@ -286,17 +286,22 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
                snd_card_free(card);
                return err;
        }
-       if ((err = snd_ymfpci_pcm_4ch(chip, 2, NULL)) < 0) {
+       err = snd_ymfpci_mixer(chip, rear_switch[dev]);
+       if (err < 0) {
                snd_card_free(card);
                return err;
        }
-       if ((err = snd_ymfpci_pcm2(chip, 3, NULL)) < 0) {
-               snd_card_free(card);
-               return err;
-       }
-       if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) {
-               snd_card_free(card);
-               return err;
+       if (chip->ac97->ext_id & AC97_EI_SDAC) {
+               err = snd_ymfpci_pcm_4ch(chip, 2, NULL);
+               if (err < 0) {
+                       snd_card_free(card);
+                       return err;
+               }
+               err = snd_ymfpci_pcm2(chip, 3, NULL);
+               if (err < 0) {
+                       snd_card_free(card);
+                       return err;
+               }
        }
        if ((err = snd_ymfpci_timer(chip, 0)) < 0) {
                snd_card_free(card);
index 03ee4e3653113820674ad6234fb0017c69dae91e..12a9a2b0338719c556446c2c716d5ff4a8742196 100644 (file)
@@ -1614,6 +1614,14 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        return change;
 }
 
+static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "4ch Duplication",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = snd_ymfpci_info_dup4ch,
+       .get = snd_ymfpci_get_dup4ch,
+       .put = snd_ymfpci_put_dup4ch,
+};
 
 static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
 {
@@ -1642,13 +1650,6 @@ YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL),
 YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0),
 YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0),
 YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4),
-{
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "4ch Duplication",
-       .info = snd_ymfpci_info_dup4ch,
-       .get = snd_ymfpci_get_dup4ch,
-       .put = snd_ymfpci_put_dup4ch,
-},
 };
 
 
@@ -1838,6 +1839,12 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
                if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)
                        return err;
        }
+       if (chip->ac97->ext_id & AC97_EI_SDAC) {
+               kctl = snd_ctl_new1(&snd_ymfpci_dup4ch, chip);
+               err = snd_ctl_add(chip->card, kctl);
+               if (err < 0)
+                       return err;
+       }
 
        /* add S/PDIF control */
        if (snd_BUG_ON(!chip->pcm_spdif))
index 5ef70b5d27e4eae85f6e4e1a1c310ea273e0eb60..278c0a0575f5596b5fe4249759c34202a3b02be5 100644 (file)
@@ -146,13 +146,10 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 
        SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
                         0, 0xFF, 1, out_tlv),
-
-       SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0),
 };
 
-static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = {
-       SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0),
-};
+static const struct snd_kcontrol_new ak4642_headphone_control =
+       SOC_DAPM_SINGLE("Switch", PW_MGMT2, 6, 1, 0);
 
 static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = {
        SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0),
@@ -165,13 +162,12 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("HPOUTR"),
        SND_SOC_DAPM_OUTPUT("LINEOUT"),
 
-       SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0,
-                          &ak4642_hpout_mixer_controls[0],
-                          ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+       SND_SOC_DAPM_PGA("HPL Out", PW_MGMT2, 5, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HPR Out", PW_MGMT2, 4, 0, NULL, 0),
+       SND_SOC_DAPM_SWITCH("Headphone Enable", SND_SOC_NOPM, 0, 0,
+                           &ak4642_headphone_control),
 
-       SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0,
-                          &ak4642_hpout_mixer_controls[0],
-                          ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+       SND_SOC_DAPM_PGA("DACH", MD_CTL4, 0, 0, NULL, 0),
 
        SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0,
                           &ak4642_lout_mixer_controls[0],
@@ -184,12 +180,17 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
 static const struct snd_soc_dapm_route ak4642_intercon[] = {
 
        /* Outputs */
-       {"HPOUTL", NULL, "HPOUTL Mixer"},
-       {"HPOUTR", NULL, "HPOUTR Mixer"},
+       {"HPOUTL", NULL, "HPL Out"},
+       {"HPOUTR", NULL, "HPR Out"},
        {"LINEOUT", NULL, "LINEOUT Mixer"},
 
-       {"HPOUTL Mixer", "DACH", "DAC"},
-       {"HPOUTR Mixer", "DACH", "DAC"},
+       {"HPL Out", NULL, "Headphone Enable"},
+       {"HPR Out", NULL, "Headphone Enable"},
+
+       {"Headphone Enable", "Switch", "DACH"},
+
+       {"DACH", NULL, "DAC"},
+
        {"LINEOUT Mixer", "DACL", "DAC"},
 };
 
index 9d38db8f1919d3b81bf6d7f68b99232ad324331e..78979b3e0e95ad41c3af9836889e03a422da00ec 100644 (file)
@@ -1113,7 +1113,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
                priv->config[id].mmcc &= 0xC0;
                priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
                priv->config[id].spc &= 0xFC;
-               priv->config[id].spc &= MCK_SCLK_64FS;
+               priv->config[id].spc |= MCK_SCLK_MCLK;
        } else {
                /* CS42L73 Slave */
                priv->config[id].spc &= 0xFC;
index d7bd91831611cb3a7a45395a76a82f34b10177df..7f4ba819a9f681dad3f962ae7c65c60d73b0f2a3 100644 (file)
@@ -987,12 +987,12 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
        /* restore regular registers */
        for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
 
-               /* this regs depends on the others */
+               /* These regs should restore in particular order */
                if (reg == SGTL5000_CHIP_ANA_POWER ||
                        reg == SGTL5000_CHIP_CLK_CTRL ||
                        reg == SGTL5000_CHIP_LINREG_CTRL ||
                        reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
-                       reg == SGTL5000_CHIP_CLK_CTRL)
+                       reg == SGTL5000_CHIP_REF_CTRL)
                        continue;
 
                snd_soc_write(codec, reg, cache[reg]);
@@ -1003,8 +1003,17 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
                snd_soc_write(codec, reg, cache[reg]);
 
        /*
-        * restore power and other regs according
-        * to set_power() and set_clock()
+        * restore these regs according to the power setting sequence in
+        * sgtl5000_set_power_regs() and clock setting sequence in
+        * sgtl5000_set_clock().
+        *
+        * The order of restore is:
+        * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
+        *    SGTL5000_CHIP_ANA_POWER PLL bits set
+        * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
+        *    SGTL5000_CHIP_ANA_POWER LINREG_D restored
+        * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
+        *    prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
         */
        snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
                        cache[SGTL5000_CHIP_LINREG_CTRL]);
@@ -1457,5 +1466,5 @@ static void __exit sgtl5000_exit(void)
 module_exit(sgtl5000_exit);
 
 MODULE_DESCRIPTION("Freescale SGTL5000 ALSA SoC Codec Driver");
-MODULE_AUTHOR("Zeng Zhaoming <zhaoming.zeng@freescale.com>");
+MODULE_AUTHOR("Zeng Zhaoming <zengzm.kernel@gmail.com>");
 MODULE_LICENSE("GPL");
index eb401ef021fb7130055d8c73d9385d19daada0ff..372b0b83bd9f191c104dd18dcff3a7756021f1dc 100644 (file)
@@ -60,7 +60,6 @@ struct aic32x4_rate_divs {
 
 struct aic32x4_priv {
        u32 sysclk;
-       s32 master;
        u8 page_no;
        void *control_data;
        u32 power_cfg;
@@ -369,7 +368,6 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
        u8 iface_reg_1;
        u8 iface_reg_2;
        u8 iface_reg_3;
@@ -384,11 +382,9 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
-               aic32x4->master = 1;
                iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
-               aic32x4->master = 0;
                break;
        default:
                printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
@@ -526,64 +522,58 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
 static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
                                  enum snd_soc_bias_level level)
 {
-       struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-
        switch (level) {
        case SND_SOC_BIAS_ON:
-               if (aic32x4->master) {
-                       /* Switch on PLL */
-                       snd_soc_update_bits(codec, AIC32X4_PLLPR,
-                                           AIC32X4_PLLEN, AIC32X4_PLLEN);
-
-                       /* Switch on NDAC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_NDAC,
-                                           AIC32X4_NDACEN, AIC32X4_NDACEN);
-
-                       /* Switch on MDAC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_MDAC,
-                                           AIC32X4_MDACEN, AIC32X4_MDACEN);
-
-                       /* Switch on NADC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_NADC,
-                                           AIC32X4_NADCEN, AIC32X4_NADCEN);
-
-                       /* Switch on MADC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_MADC,
-                                           AIC32X4_MADCEN, AIC32X4_MADCEN);
-
-                       /* Switch on BCLK_N Divider */
-                       snd_soc_update_bits(codec, AIC32X4_BCLKN,
-                                           AIC32X4_BCLKEN, AIC32X4_BCLKEN);
-               }
+               /* Switch on PLL */
+               snd_soc_update_bits(codec, AIC32X4_PLLPR,
+                                   AIC32X4_PLLEN, AIC32X4_PLLEN);
+
+               /* Switch on NDAC Divider */
+               snd_soc_update_bits(codec, AIC32X4_NDAC,
+                                   AIC32X4_NDACEN, AIC32X4_NDACEN);
+
+               /* Switch on MDAC Divider */
+               snd_soc_update_bits(codec, AIC32X4_MDAC,
+                                   AIC32X4_MDACEN, AIC32X4_MDACEN);
+
+               /* Switch on NADC Divider */
+               snd_soc_update_bits(codec, AIC32X4_NADC,
+                                   AIC32X4_NADCEN, AIC32X4_NADCEN);
+
+               /* Switch on MADC Divider */
+               snd_soc_update_bits(codec, AIC32X4_MADC,
+                                   AIC32X4_MADCEN, AIC32X4_MADCEN);
+
+               /* Switch on BCLK_N Divider */
+               snd_soc_update_bits(codec, AIC32X4_BCLKN,
+                                   AIC32X4_BCLKEN, AIC32X4_BCLKEN);
                break;
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
-               if (aic32x4->master) {
-                       /* Switch off PLL */
-                       snd_soc_update_bits(codec, AIC32X4_PLLPR,
-                                           AIC32X4_PLLEN, 0);
-
-                       /* Switch off NDAC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_NDAC,
-                                           AIC32X4_NDACEN, 0);
-
-                       /* Switch off MDAC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_MDAC,
-                                           AIC32X4_MDACEN, 0);
-
-                       /* Switch off NADC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_NADC,
-                                           AIC32X4_NADCEN, 0);
-
-                       /* Switch off MADC Divider */
-                       snd_soc_update_bits(codec, AIC32X4_MADC,
-                                           AIC32X4_MADCEN, 0);
-
-                       /* Switch off BCLK_N Divider */
-                       snd_soc_update_bits(codec, AIC32X4_BCLKN,
-                                           AIC32X4_BCLKEN, 0);
-               }
+               /* Switch off PLL */
+               snd_soc_update_bits(codec, AIC32X4_PLLPR,
+                                   AIC32X4_PLLEN, 0);
+
+               /* Switch off NDAC Divider */
+               snd_soc_update_bits(codec, AIC32X4_NDAC,
+                                   AIC32X4_NDACEN, 0);
+
+               /* Switch off MDAC Divider */
+               snd_soc_update_bits(codec, AIC32X4_MDAC,
+                                   AIC32X4_MDACEN, 0);
+
+               /* Switch off NADC Divider */
+               snd_soc_update_bits(codec, AIC32X4_NADC,
+                                   AIC32X4_NADCEN, 0);
+
+               /* Switch off MADC Divider */
+               snd_soc_update_bits(codec, AIC32X4_MADC,
+                                   AIC32X4_MADCEN, 0);
+
+               /* Switch off BCLK_N Divider */
+               snd_soc_update_bits(codec, AIC32X4_BCLKN,
+                                   AIC32X4_BCLKEN, 0);
                break;
        case SND_SOC_BIAS_OFF:
                break;
@@ -651,9 +641,11 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
        if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
                snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
        }
-       if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
-               snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN);
-       }
+
+       tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
+                       AIC32X4_LDOCTLEN : 0;
+       snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
+
        tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
        if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
                tmp_reg |= AIC32X4_LDOIN_18_36;
index c2880907fcedc0e74aed4b377e697d5223bee579..a75c3766aedeec9192c0d887ebe9b8ff366e1e5b 100644 (file)
@@ -733,8 +733,9 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        struct wm2000_priv *wm2000;
        struct wm2000_platform_data *pdata;
        const char *filename;
-       const struct firmware *fw;
-       int reg, ret;
+       const struct firmware *fw = NULL;
+       int ret;
+       int reg;
        u16 id;
 
        wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
@@ -751,7 +752,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
                ret = PTR_ERR(wm2000->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
                        ret);
-               goto err;
+               goto out;
        }
 
        /* Verify that this is a WM2000 */
@@ -763,7 +764,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        if (id != 0x2000) {
                dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
                ret = -ENODEV;
-               goto err_regmap;
+               goto out_regmap_exit;
        }
 
        reg = wm2000_read(i2c, WM2000_REG_REVISON);
@@ -782,7 +783,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        ret = request_firmware(&fw, filename, &i2c->dev);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
-               goto err_regmap;
+               goto out_regmap_exit;
        }
 
        /* Pre-cook the concatenation of the register address onto the image */
@@ -793,15 +794,13 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        if (wm2000->anc_download == NULL) {
                dev_err(&i2c->dev, "Out of memory\n");
                ret = -ENOMEM;
-               goto err_fw;
+               goto out_regmap_exit;
        }
 
        wm2000->anc_download[0] = 0x80;
        wm2000->anc_download[1] = 0x00;
        memcpy(wm2000->anc_download + 2, fw->data, fw->size);
 
-       release_firmware(fw);
-
        wm2000->anc_eng_ena = 1;
        wm2000->anc_active = 1;
        wm2000->spk_ena = 1;
@@ -809,18 +808,14 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
 
        wm2000_reset(wm2000);
 
-       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000,
-                                    NULL, 0);
-       if (ret != 0)
-               goto err_fw;
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
+       if (!ret)
+               goto out;
 
-       return 0;
-
-err_fw:
-       release_firmware(fw);
-err_regmap:
+out_regmap_exit:
        regmap_exit(wm2000->regmap);
-err:
+out:
+       release_firmware(fw);
        return ret;
 }
 
index 8b24323d6b2c89ecb5a751b17e1e747cb2d35807..89f2af77b1c3983afaa407e6ff2740ec95e0c068 100644 (file)
@@ -1377,6 +1377,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
 
                        switch (wm5100->rev) {
                        case 0:
+                               regcache_cache_bypass(wm5100->regmap, true);
                                snd_soc_write(codec, 0x11, 0x3);
                                snd_soc_write(codec, 0x203, 0xc);
                                snd_soc_write(codec, 0x206, 0);
@@ -1392,6 +1393,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
                                        snd_soc_write(codec,
                                                      wm5100_reva_patches[i].reg,
                                                      wm5100_reva_patches[i].val);
+                               regcache_cache_bypass(wm5100->regmap, false);
                                break;
                        default:
                                break;
@@ -1402,6 +1404,8 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_OFF:
+               regcache_cache_only(wm5100->regmap, true);
+               regcache_mark_dirty(wm5100->regmap);
                if (wm5100->pdata.ldo_ena)
                        gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
                regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
@@ -2180,6 +2184,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
                if (wm5100->jack_detecting) {
                        dev_dbg(codec->dev, "Microphone detected\n");
                        wm5100->jack_mic = true;
+                       wm5100->jack_detecting = false;
                        snd_soc_jack_report(wm5100->jack,
                                            SND_JACK_HEADSET,
                                            SND_JACK_HEADSET | SND_JACK_BTN_0);
@@ -2218,6 +2223,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
                                            SND_JACK_BTN_0);
                } else if (wm5100->jack_detecting) {
                        dev_dbg(codec->dev, "Headphone detected\n");
+                       wm5100->jack_detecting = false;
                        snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
                                            SND_JACK_HEADPHONE);
 
@@ -2607,6 +2613,13 @@ static const struct regmap_config wm5100_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
+static const unsigned int wm5100_mic_ctrl_reg[] = {
+       WM5100_IN1L_CONTROL,
+       WM5100_IN2L_CONTROL,
+       WM5100_IN3L_CONTROL,
+       WM5100_IN4L_CONTROL,
+};
+
 static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
@@ -2739,7 +2752,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
        }
 
        for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
-               regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
+               regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],
                                   WM5100_IN1_MODE_MASK |
                                   WM5100_IN1_DMIC_SUP_MASK,
                                   (wm5100->pdata.in_mode[i] <<
index 8d4ea43d40a383298023165e517ed1c9de510063..40ac888faf3d7633f433257ab96e2f190d6f4174 100644 (file)
@@ -55,7 +55,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
                return 0;
 
        if (fw->size < 32) {
-               dev_err(codec->dev, "%s: firmware too short (%d bytes)\n",
+               dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n",
                        name, fw->size);
                goto err;
        }
index 296de4e30d26f49729cd25bc4c22134b01fb90aa..0ac228b7dc049a8d584b7219e3fa844262af3769 100644 (file)
@@ -96,7 +96,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \
        struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               regcache_cache_only(wm8962->regmap, true);      \
+               regcache_mark_dirty(wm8962->regmap);    \
        } \
        return 0; \
 }
@@ -2564,7 +2564,7 @@ static int dsp2_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
-static const char *st_text[] = { "None", "Right", "Left" };
+static const char *st_text[] = { "None", "Left", "Right" };
 
 static const struct soc_enum str_enum =
        SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
@@ -3159,13 +3159,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_S16_LE:
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
-               aif0 |= 0x40;
+               aif0 |= 0x4;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               aif0 |= 0x80;
+               aif0 |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               aif0 |= 0xc0;
+               aif0 |= 0xc;
                break;
        default:
                return -EINVAL;
index 2b40c93601ed493a11bf0222dd5ba0c09754355b..7c7fd925db8da78c1ad6bb08bdde66eb60d7210b 100644 (file)
@@ -444,6 +444,12 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        /* Enable the FLL */
        snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
 
+       /* Both overestimates */
+       if (Fref < 1000000)
+               msleep(3);
+       else
+               msleep(1);
+
        dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
 
        wm8993->fll_fref = Fref;
index 93d27b6602571c3f600f9272defe0b05f12a8c3b..ec69a6c152fea9a8b55a7c16c1f3935fb3dc305d 100644 (file)
@@ -770,6 +770,8 @@ static void vmid_reference(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
+       pm_runtime_get_sync(codec->dev);
+
        wm8994->vmid_refcount++;
 
        dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
@@ -783,7 +785,12 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                    WM8994_VMID_RAMP_MASK,
                                    WM8994_STARTUP_BIAS_ENA |
                                    WM8994_VMID_BUF_ENA |
-                                   (0x11 << WM8994_VMID_RAMP_SHIFT));
+                                   (0x3 << WM8994_VMID_RAMP_SHIFT));
+
+               /* Remove discharge for line out */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH, 0);
 
                /* Main bias enable, VMID=2x40k */
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -837,6 +844,8 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_VMID_BUF_ENA |
                                    WM8994_VMID_RAMP_MASK, 0);
        }
+
+       pm_runtime_put(codec->dev);
 }
 
 static int vmid_event(struct snd_soc_dapm_widget *w,
@@ -2753,11 +2762,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
                codec->cache_only = 0;
        }
 
-       /* Restore the registers */
-       ret = snd_soc_cache_sync(codec);
-       if (ret != 0)
-               dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
-
        wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
index d8da10fe5b522a0ab2ba584d9ac6afe8383a776f..61f7daa4d0e681571222fce0910ab148e8b0f18a 100644 (file)
@@ -108,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
        struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               regcache_cache_only(wm8996->regmap, true);      \
+               regcache_mark_dirty(wm8996->regmap);    \
        } \
        return 0; \
 }
@@ -1120,7 +1120,8 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
-                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+                     SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@@ -2007,6 +2008,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        int lfclk = 0;
        int ratediv = 0;
+       int sync = WM8996_REG_SYNC;
        int src;
        int old;
 
@@ -2051,6 +2053,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
        case 32000:
        case 32768:
                lfclk = WM8996_LFCLK_ENA;
+               sync = 0;
                break;
        default:
                dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
@@ -2064,6 +2067,8 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
                            WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK,
                            src << WM8996_SYSCLK_SRC_SHIFT | ratediv);
        snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk);
+       snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1,
+                           WM8996_REG_SYNC, sync);
        snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
                            WM8996_SYSCLK_ENA, old);
 
index 0fde643194ceaccbc8c65e5cdd68d8d18010bbf0..de9ac3e44aec840fc718445333d334b2d4f96b63 100644 (file)
@@ -1567,6 +1567,10 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 /*
  * R257 (0x101) - Control Interface (1)
  */
+#define WM8996_REG_SYNC                         0x8000  /* REG_SYNC */
+#define WM8996_REG_SYNC_MASK                    0x8000  /* REG_SYNC */
+#define WM8996_REG_SYNC_SHIFT                       15  /* REG_SYNC */
+#define WM8996_REG_SYNC_WIDTH                        1  /* REG_SYNC */
 #define WM8996_AUTO_INC                         0x0004  /* AUTO_INC */
 #define WM8996_AUTO_INC_MASK                    0x0004  /* AUTO_INC */
 #define WM8996_AUTO_INC_SHIFT                        2  /* AUTO_INC */
index 2a61094075f86dfd40fff87787b2dba70804b36d..8a68cea4a3ee6af7860ae65f4ccab119b10cc425 100644 (file)
@@ -586,14 +586,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
 };
 
 static const struct snd_kcontrol_new line2_mix[] = {
-SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
 };
 
 static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
 };
 
 static const struct snd_kcontrol_new line2p_mix[] = {
@@ -613,6 +613,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
 SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
 
+SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
+
 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
                   in1l_pga, ARRAY_SIZE(in1l_pga)),
 SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -834,9 +836,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+       { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
        { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
 
+       { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
 
        { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -844,8 +848,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
-       { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
-       { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+       { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
+       { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
        { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
 
        { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
@@ -853,9 +857,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+       { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
        { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
 
+       { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
        { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
 
        { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
index 3fc96130d1a6b0ccb76470e979eb34896682e965..de83904498730dbf43447cdcc4ef42cd34a9d0d7 100644 (file)
@@ -113,9 +113,9 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
        rtd->dma_data.name = dma_params->name;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               rtd->dma_data.direction = DMA_TO_DEVICE;
+               rtd->dma_data.direction = DMA_MEM_TO_DEV;
        else
-               rtd->dma_data.direction = DMA_FROM_DEVICE;
+               rtd->dma_data.direction = DMA_DEV_TO_MEM;
 
        rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
                                            &rtd->dma_data);
index 1cf2fe889f6adaa885c77bf2c74da9dd9f56a3d8..5780c9b9d569cf78f82edb63104322c896b7c234 100644 (file)
@@ -88,11 +88,13 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
        iprtd->dma_data.dma_request = dma_params->dma;
 
        /* Try to grab a DMA channel */
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-       iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
-       if (!iprtd->dma_chan)
-               return -EINVAL;
+       if (!iprtd->dma_chan) {
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+               iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
+               if (!iprtd->dma_chan)
+                       return -EINVAL;
+       }
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
@@ -107,12 +109,12 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
        }
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               slave_config.direction = DMA_TO_DEVICE;
+               slave_config.direction = DMA_MEM_TO_DEV;
                slave_config.dst_addr = dma_params->dma_addr;
                slave_config.dst_addr_width = buswidth;
                slave_config.dst_maxburst = dma_params->burstsize;
        } else {
-               slave_config.direction = DMA_FROM_DEVICE;
+               slave_config.direction = DMA_DEV_TO_MEM;
                slave_config.src_addr = dma_params->dma_addr;
                slave_config.src_addr_width = buswidth;
                slave_config.src_maxburst = dma_params->burstsize;
@@ -159,7 +161,7 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
                        iprtd->period_bytes * iprtd->periods,
                        iprtd->period_bytes,
                        substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-                       DMA_TO_DEVICE : DMA_FROM_DEVICE);
+                       DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
        if (!iprtd->desc) {
                dev_err(&chan->dev->device, "cannot prepare slave dma\n");
                return -EINVAL;
index 0e12f4e0a76d60ac10dab9b70ad4e12f80e0d0c7..105f42a394df6460e80899f22c567f3ac6192c7f 100644 (file)
@@ -136,7 +136,7 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
                        iprtd->period_bytes * iprtd->periods,
                        iprtd->period_bytes,
                        substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-                       DMA_TO_DEVICE : DMA_FROM_DEVICE);
+                       DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
        if (!iprtd->desc) {
                dev_err(&chan->dev->device, "cannot prepare slave dma\n");
                return -EINVAL;
index dccfb37a96261dd1523ca5e3bf13f1145d0b68e0..f204dbac11d4e044edf12501b51238adcd069c28 100644 (file)
@@ -124,6 +124,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
         *
         * If MCLK is not used, we just set saif clk to 512*fs.
         */
+       clk_prepare_enable(master_saif->clk);
+
        if (master_saif->mclk_in_use) {
                if (mclk % 32 == 0) {
                        scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
@@ -133,6 +135,7 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
                        ret = clk_set_rate(master_saif->clk, 384 * rate);
                } else {
                        /* SAIF MCLK should be either 32x or 48x */
+                       clk_disable_unprepare(master_saif->clk);
                        return -EINVAL;
                }
        } else {
@@ -140,6 +143,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
                scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
        }
 
+       clk_disable_unprepare(master_saif->clk);
+
        if (ret)
                return ret;
 
index 427ae0d9817bb95cb09fbab000d6a2d0a35d32c8..e4ba17ce6b32cf3c8d3d3a0762d70c7b7c969b3c 100644 (file)
@@ -86,7 +86,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
        dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
        dma_info.direction =
                (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-               ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+               ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
        dma_info.fp = audio_buffdone;
        dma_info.fp_param = substream;
        dma_info.period = prtd->dma_period;
@@ -171,7 +171,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
                dma_info.client = prtd->params->client;
                dma_info.direction =
                        (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-                       ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+                       ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
                dma_info.width = prtd->params->dma_size;
                dma_info.fifo = prtd->params->dma_addr;
                prtd->params->ch = prtd->params->ops->request(
index 7ac0ba2025c337b5f313996f00a04c52975cb9a5..c6012ff5bd3ea977cd18f5bb98e4e7e6ded82d1e 100644 (file)
@@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
 
 /* GTA02 specific routes and controls */
 
-#ifdef CONFIG_MACH_NEO1973_GTA02
-
 static int gta02_speaker_enabled;
 
 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
@@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
        return 0;
 }
 
-#else
-static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
-#endif
-
 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
@@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
        int ret;
 
        /* set up NC codec pins */
-       if (machine_is_neo1973_gta01()) {
-               snd_soc_dapm_nc_pin(dapm, "LOUT2");
-               snd_soc_dapm_nc_pin(dapm, "ROUT2");
-       }
        snd_soc_dapm_nc_pin(dapm, "OUT3");
        snd_soc_dapm_nc_pin(dapm, "OUT4");
        snd_soc_dapm_nc_pin(dapm, "LINE1");
@@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-/* GTA01 specific controls */
-
-#ifdef CONFIG_MACH_NEO1973_GTA01
-
-static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
-       {"Amp IN", NULL, "ROUT1"},
-       {"Amp IN", NULL, "LOUT1"},
-
-       {"Handset Spk", NULL, "Amp EP"},
-       {"Stereo Out", NULL, "Amp LS"},
-       {"Headphone", NULL, "Amp HP"},
-};
-
-static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
-       SND_SOC_DAPM_SPK("Handset Spk", NULL),
-       SND_SOC_DAPM_SPK("Stereo Out", NULL),
-       SND_SOC_DAPM_HP("Headphone", NULL),
-};
-
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
-{
-       int ret;
-
-       ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
-                       ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
-       if (ret)
-               return ret;
-
-       ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
-                       ARRAY_SIZE(neo1973_lm4857_routes));
-       if (ret)
-               return ret;
-
-       snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
-       snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
-       snd_soc_dapm_ignore_suspend(dapm, "Headphone");
-
-       return 0;
-}
-
-#else
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
-#endif
-
 static struct snd_soc_dai_link neo1973_dai[] = {
 { /* Hifi Playback - for similatious use with voice below */
        .name = "WM8753",
@@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = {
                .name = "dfbmcs320",
                .codec_name = "dfbmcs320.0",
        },
-       {
-               .name = "lm4857",
-               .codec_name = "lm4857.0-007c",
-               .init = neo1973_lm4857_init,
-       },
 };
 
 static struct snd_soc_codec_conf neo1973_codec_conf[] = {
@@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = {
        },
 };
 
-#ifdef CONFIG_MACH_NEO1973_GTA02
 static const struct gpio neo1973_gta02_gpios[] = {
        { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
        { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
 };
-#else
-static const struct gpio neo1973_gta02_gpios[] = {};
-#endif
 
 static struct snd_soc_card neo1973 = {
        .name = "neo1973",
@@ -480,7 +417,7 @@ static int __init neo1973_init(void)
 {
        int ret;
 
-       if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
+       if (!machine_is_neo1973_gta02())
                return -ENODEV;
 
        if (machine_is_neo1973_gta02()) {
index db6c89a28bda9924a8c96b3e4c3ee85fc9482871..ea4a82d01160f5657e19a4f1f4df4ca928d1737a 100644 (file)
@@ -1152,12 +1152,8 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
        struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
-       int samples_pos = io->buff_sample_pos - 1;
 
-       if (samples_pos < 0)
-               samples_pos = 0;
-
-       return fsi_sample2frame(fsi, samples_pos);
+       return fsi_sample2frame(fsi, io->buff_sample_pos);
 }
 
 static struct snd_pcm_ops fsi_pcm_ops = {
index f8f681690a712d6c978ec607196fdd956c6fca2a..0193e595d415da8b82e7bf383b243dbdba25f88e 100644 (file)
@@ -131,7 +131,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
        sg_dma_address(&sg) = buff;
 
        desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
-               &sg, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dev_err(dev, "Failed to allocate a dma descriptor\n");
                return -ENOMEM;
@@ -181,7 +181,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
        sg_dma_address(&sg) = buff;
 
        desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
-               &sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dev_err(dev, "Failed to allocate dma descriptor\n");
                return -ENOMEM;
index 3986520b4677244b9bd592b85f2350889bda5cdf..92cee24ed2dcce7eb7b7e8de3a87f09d0ffe5138 100644 (file)
@@ -567,6 +567,17 @@ int snd_soc_suspend(struct device *dev)
                if (!codec->suspended && codec->driver->suspend) {
                        switch (codec->dapm.bias_level) {
                        case SND_SOC_BIAS_STANDBY:
+                               /*
+                                * If the CODEC is capable of idle
+                                * bias off then being in STANDBY
+                                * means it's doing something,
+                                * otherwise fall through.
+                                */
+                               if (codec->dapm.idle_bias_off) {
+                                       dev_dbg(codec->dev,
+                                               "idle_bias_off CODEC on over suspend\n");
+                                       break;
+                               }
                        case SND_SOC_BIAS_OFF:
                                codec->driver->suspend(codec);
                                codec->suspended = 1;
@@ -907,6 +918,10 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                        if (err < 0)
                                printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
                }
+
+               /* Make sure all DAPM widgets are freed */
+               snd_soc_dapm_free(&platform->dapm);
+
                platform->probed = 0;
                list_del(&platform->card_list);
                module_put(platform->dev->driver->owner);
index 3ad1f59b80281cfc7c9ace89ae8a30d34317fe7a..1f55ded4047f03b9a538af971c01018f0fb5df10 100644 (file)
@@ -1426,7 +1426,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                        dapm->target_bias_level = SND_SOC_BIAS_ON;
                        break;
                case SND_SOC_DAPM_STREAM_STOP:
-                       if (dapm->codec->active)
+                       if (dapm->codec && dapm->codec->active)
                                dapm->target_bias_level = SND_SOC_BIAS_ON;
                        else
                                dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
index 93931def0dce62b3a5e162d7c759ac82f33745f2..21554611557c380ca391a9c384407a9744a056a1 100644 (file)
@@ -134,7 +134,7 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr)
        sg_dma_address(&sg) = buf_dma_addr;
        desc = chan->device->device_prep_slave_sg(chan, &sg, 1,
                dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-               DMA_TO_DEVICE : DMA_FROM_DEVICE,
+               DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dev_err(&chan->dev->device, "cannot prepare slave dma\n");
index 2cf87f5afed4e2fbc93cdcdf4d72277b8afae52f..fde9a7a29cb6e670ba2d58e49b8b9e39a5cd7f15 100644 (file)
@@ -311,8 +311,10 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
 
        spin_lock(&dev->spinlock);
 
-       if (dev->input_panic || dev->output_panic)
+       if (dev->input_panic || dev->output_panic) {
                ptr = SNDRV_PCM_POS_XRUN;
+               goto unlock;
+       }
 
        if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
                ptr = bytes_to_frames(sub->runtime,
@@ -321,6 +323,7 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
                ptr = bytes_to_frames(sub->runtime,
                                        dev->audio_in_buf_pos[index]);
 
+unlock:
        spin_unlock(&dev->spinlock);
        return ptr;
 }
index a39edcc32a93f0986c87498de66ca37206b38915..da5fa1ac4edaf3608c7811dea5194b98a8bab37c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __USBAUDIO_CARD_H
 #define __USBAUDIO_CARD_H
 
+#define MAX_NR_RATES   1024
 #define MAX_PACKS      20
 #define MAX_PACKS_HS   (MAX_PACKS * 8) /* in high speed mode */
 #define MAX_URBS       8
index e09aba19375cf938eafd28aedec9edf2ea55dbbe..ddfef57c4c9fbe93c9551de6af2959051bba4c21 100644 (file)
@@ -209,8 +209,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
        return 0;
 }
 
-#define MAX_UAC2_NR_RATES 1024
-
 /*
  * Helper function to walk the array of sample rate triplets reported by
  * the device. The problem is that we need to parse whole array first to
@@ -255,7 +253,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
                        fp->rates |= snd_pcm_rate_to_rate_bit(rate);
 
                        nr_rates++;
-                       if (nr_rates >= MAX_UAC2_NR_RATES) {
+                       if (nr_rates >= MAX_NR_RATES) {
                                snd_printk(KERN_ERR "invalid uac2 rates\n");
                                break;
                        }
index 8edc5035fc8fc5929b948a765cc463498c0a8a9e..d89ab4c7d44b28bc0c52f9e4ec817030059b0692 100644 (file)
@@ -1617,6 +1617,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* Edirol UM-3G */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .ifnum = 0,
+               .type = QUIRK_MIDI_STANDARD_INTERFACE
+       }
+},
 {
        /* Boss JS-8 Jam Station  */
        USB_DEVICE(0x0582, 0x0109),
index a3ddac0deffd1eba937932a55553466f32308065..27817266867ae2c17b09f4ea85b6522a9d39e4ea 100644 (file)
@@ -132,10 +132,14 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
        unsigned *rate_table = NULL;
 
        fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
-       if (! fp) {
+       if (!fp) {
                snd_printk(KERN_ERR "cannot memdup\n");
                return -ENOMEM;
        }
+       if (fp->nr_rates > MAX_NR_RATES) {
+               kfree(fp);
+               return -EINVAL;
+       }
        if (fp->nr_rates > 0) {
                rate_table = kmemdup(fp->rate_table,
                                     sizeof(int) * fp->nr_rates, GFP_KERNEL);
index ac86d67b636e06b3bcf931c9d6f6a012d4f2801f..7c12650165aed5933bdcad60a8b298d2cd6f437a 100644 (file)
@@ -104,7 +104,7 @@ endif
 
 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
 EXTLIBS = -lpthread -lrt -lelf -lm
-ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
 
@@ -168,10 +168,7 @@ endif
 
 ### --- END CONFIGURATION SECTION ---
 
-# Those must not be GNU-specific; they are shared with perl/ which may
-# be built by a different compiler. (Note that this is an artifact now
-# but it still might be nice to keep that distinction.)
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
 # Guard against environment variables
index a57b66e853c24e3d68b73d80ce1831494320db4f..185a96d66dd18ce21b210f9747d7ab61b03b1fda 100644 (file)
@@ -1,2 +1,8 @@
 
 #include "../../../arch/x86/lib/memcpy_64.S"
+/*
+ * We need to provide note.GNU-stack section, saying that we want
+ * NOT executable stack. Otherwise the final linking will assume that
+ * the ELF stack should not be restricted at all and set it RWX.
+ */
+.section .note.GNU-stack,"",@progbits
index 59d43abfbfec1ce22b44ac9c2db18cd29f0ce612..fb8566181f27f2ef4dace5ba93fd273c6cae4f51 100644 (file)
@@ -20,7 +20,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  */
-#define _GNU_SOURCE
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -31,7 +30,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#undef _GNU_SOURCE
 #include "perf.h"
 #include "builtin.h"
 #include "util/util.h"
index 8f80df89603822e5431f45f1374cf926208f23ed..dd162aa24baad2f44c5cbb1b4176fb2b2cc7b26d 100644 (file)
@@ -89,8 +89,6 @@ void get_term_dimensions(struct winsize *ws)
 
 static void perf_top__update_print_entries(struct perf_top *top)
 {
-       top->print_entries = top->winsize.ws_row;
-
        if (top->print_entries > 9)
                top->print_entries -= 9;
 }
@@ -100,6 +98,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar
        struct perf_top *top = arg;
 
        get_term_dimensions(&top->winsize);
+       if (!top->print_entries
+           || (top->print_entries+4) > top->winsize.ws_row) {
+               top->print_entries = top->winsize.ws_row;
+       } else {
+               top->print_entries += 4;
+               top->winsize.ws_row = top->print_entries;
+       }
        perf_top__update_print_entries(top);
 }
 
@@ -453,8 +458,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
                                };
                                perf_top__sig_winch(SIGWINCH, NULL, top);
                                sigaction(SIGWINCH, &act, NULL);
-                       } else
+                       } else {
+                               perf_top__sig_winch(SIGWINCH, NULL, top);
                                signal(SIGWINCH, SIG_DFL);
+                       }
                        break;
                case 'E':
                        if (top->evlist->nr_entries > 1) {
index 73ddaf06b8e718e9dc7bd21765b9a2cf7250d8c0..2044324b755a51bc9b41536957dce8b35a11a6fd 100644 (file)
@@ -554,7 +554,7 @@ static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
 
        is_kernel_mmap = memcmp(event->mmap.filename,
                                kmmap_prefix,
-                               strlen(kmmap_prefix)) == 0;
+                               strlen(kmmap_prefix) - 1) == 0;
        if (event->mmap.filename[0] == '/' ||
            (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
 
index 667f3b78bb2c2f44fd4a93cbd94a80850cdd0e51..7132ee834e0e5ee714c481961ed3c9d4308cf5f0 100644 (file)
@@ -463,6 +463,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
        memset(data, 0, sizeof(*data));
        data->cpu = data->pid = data->tid = -1;
        data->stream_id = data->id = data->time = -1ULL;
+       data->period = 1;
 
        if (event->header.type != PERF_RECORD_SAMPLE) {
                if (!sample_id_all)
index 3e7e0b09c12c29339f3853c469dc0c3cc2d0d71c..ecd7f4dd7eea0156eb4e059eb335089d416d9c0b 100644 (file)
@@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,
        strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
 
        ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
-       size = strlen(name);
+       size = strlen(ev.event_type.event_type.name);
        size = ALIGN(size, sizeof(u64));
        ev.event_type.header.size = sizeof(ev.event_type) -
                (sizeof(ev.event_type.event_type.name) - size);
index eb25900e2211f936ee4caea544fd7a70c6df43e8..29cb654598113a66729a17b9bd00ff21da8c52d8 100644 (file)
@@ -19,7 +19,6 @@
  *
  */
 
-#define _GNU_SOURCE
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -33,7 +32,6 @@
 #include <limits.h>
 #include <elf.h>
 
-#undef _GNU_SOURCE
 #include "util.h"
 #include "event.h"
 #include "string.h"
index 215d50f2042e063ce53d9526a3aecbd0ec7ff461..0975438c3e7281f5d8fc70b28374e813e8715607 100644 (file)
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
index 6c164dc9ee957dbf3df642f712b2fdc1485d2dc6..1a8d4dc4f386b5bee9897686986cf4fa31548b9b 100644 (file)
  *  The parts for function graph printing was taken and modified from the
  *  Linux Kernel that were written by Frederic Weisbecker.
  */
-#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
 
-#undef _GNU_SOURCE
 #include "../perf.h"
 #include "util.h"
 #include "trace-event.h"
index 1212a386a0336e8b0faf02f62513d9172d42b55f..e81aef1f25698d36968da0b03a28680008d0e7c1 100644 (file)
@@ -1,6 +1,4 @@
-#define _GNU_SOURCE
 #include <stdio.h>
-#undef _GNU_SOURCE
 #include "../libslang.h"
 #include <stdlib.h>
 #include <string.h>
index 6ef3c56917626a38d835491d82461219b7dddf88..4f48f5901b303e040a0f515d1311e5d50726c83e 100644 (file)
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index b9c530cce79a793657778dcc5a1ce2c5dd2215da..ecf9898169c86975c50f484483122f5a3954e37b 100644 (file)
@@ -40,7 +40,6 @@
 #define decimal_length(x)      ((int)(sizeof(x) * 2.56 + 0.5) + 1)
 
 #define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
 #define _BSD_SOURCE 1
 #define HAS_BOOL
 
index 3c6f7808efae53b84cab8926f87b3a5f37ea60ee..310d3dd5e547023ea375f933cb2ad7ca61aee081 100644 (file)
@@ -811,6 +811,8 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
        case 0x2C:      /* Westmere EP - Gulftown */
        case 0x2A:      /* SNB */
        case 0x2D:      /* SNB Xeon */
+       case 0x3A:      /* IVB */
+       case 0x3D:      /* IVB Xeon */
                return 1;
        case 0x2E:      /* Nehalem-EX Xeon - Beckton */
        case 0x2F:      /* Westmere-EX Xeon - Eagleton */
index 7287bf5d1c9edc1fa84681aea4f989c9c750fa9c..a91f980077d843ca319dfe5d7b3b95e252e02bc3 100644 (file)
@@ -1543,7 +1543,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,
        if (memslot && memslot->dirty_bitmap) {
                unsigned long rel_gfn = gfn - memslot->base_gfn;
 
-               if (!__test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))
+               if (!test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))
                        memslot->nr_dirty_pages++;
        }
 }